]> git.saurik.com Git - apple/javascriptcore.git/commitdiff
JavaScriptCore-903.tar.gz ios-50 v903
authorApple <opensource@apple.com>
Tue, 11 Oct 2011 18:14:29 +0000 (18:14 +0000)
committerApple <opensource@apple.com>
Tue, 11 Oct 2011 18:14:29 +0000 (18:14 +0000)
697 files changed:
API/APICast.h
API/APIShims.h
API/JSBase.h
API/JSCallbackConstructor.cpp
API/JSCallbackConstructor.h
API/JSCallbackFunction.cpp
API/JSCallbackFunction.h
API/JSCallbackObject.cpp
API/JSCallbackObject.h
API/JSCallbackObjectFunctions.h
API/JSClassRef.cpp
API/JSClassRef.h
API/JSContextRef.cpp
API/JSContextRefPrivate.h
API/JSObjectRef.cpp
API/JSRetainPtr.h
API/JSStringRef.cpp
API/JSStringRef.h
API/JSStringRefBSTR.cpp
API/JSStringRefCF.cpp
API/JSValueRef.cpp
API/JSWeakObjectMapRefInternal.h
API/JSWeakObjectMapRefPrivate.cpp
API/JSWeakObjectMapRefPrivate.h
API/OpaqueJSString.cpp
API/OpaqueJSString.h
API/tests/testapi.c
API/tests/testapi.js
Android.mk [deleted file]
Android.v8.wtf.mk [deleted file]
CMakeLists.txt [new file with mode: 0644]
CMakeListsEfl.txt [new file with mode: 0644]
CMakeListsWinCE.txt [new file with mode: 0644]
DerivedSources.make
DerivedSources.pro
ForwardingHeaders/JavaScriptCore/APIShims.h [new file with mode: 0644]
GNUmakefile.am
GNUmakefile.list.am [new file with mode: 0644]
Info.plist
JavaScriptCore.JSVALUE32_64only.exp [new file with mode: 0644]
JavaScriptCore.JSVALUE64only.exp [new file with mode: 0644]
JavaScriptCore.exp
JavaScriptCore.gyp/JavaScriptCore.gyp
JavaScriptCore.gypi
JavaScriptCore.order
JavaScriptCore.pri
JavaScriptCore.pro
JavaScriptCorePrefix.h
JavaScriptCoreSources.bkl [deleted file]
KeywordLookupGenerator.py [new file with mode: 0644]
Makefile
assembler/ARMAssembler.cpp
assembler/ARMAssembler.h
assembler/ARMv7Assembler.cpp
assembler/ARMv7Assembler.h
assembler/AbstractMacroAssembler.h
assembler/AssemblerBuffer.h
assembler/AssemblerBufferWithConstantPool.h
assembler/CodeLocation.h
assembler/LinkBuffer.h
assembler/MIPSAssembler.h
assembler/MacroAssembler.h
assembler/MacroAssemblerARM.cpp
assembler/MacroAssemblerARM.h
assembler/MacroAssemblerARMv7.h
assembler/MacroAssemblerCodeRef.h
assembler/MacroAssemblerMIPS.h
assembler/MacroAssemblerSH4.cpp [new file with mode: 0644]
assembler/MacroAssemblerSH4.h [new file with mode: 0644]
assembler/MacroAssemblerX86.h
assembler/MacroAssemblerX86Common.h
assembler/MacroAssemblerX86_64.h
assembler/RepatchBuffer.h
assembler/SH4Assembler.h [new file with mode: 0644]
assembler/X86Assembler.h
bytecode/CodeBlock.cpp
bytecode/CodeBlock.h
bytecode/EvalCodeCache.h
bytecode/Instruction.h
bytecode/JumpTable.h
bytecode/Opcode.cpp
bytecode/Opcode.h
bytecode/SamplingTool.cpp
bytecode/SamplingTool.h
bytecode/StructureStubInfo.cpp
bytecode/StructureStubInfo.h
bytecompiler/BytecodeGenerator.cpp
bytecompiler/BytecodeGenerator.h
bytecompiler/NodesCodegen.cpp
bytecompiler/RegisterID.h
config.h
create_hash_table
create_jit_stubs
create_regex_tables
debugger/Debugger.cpp
debugger/Debugger.h
debugger/DebuggerActivation.cpp
debugger/DebuggerActivation.h
debugger/DebuggerCallFrame.cpp
debugger/DebuggerCallFrame.h
dfg/DFGAliasTracker.h [new file with mode: 0644]
dfg/DFGByteCodeParser.cpp [new file with mode: 0644]
dfg/DFGByteCodeParser.h [new file with mode: 0644]
dfg/DFGFPRInfo.h [new file with mode: 0644]
dfg/DFGGPRInfo.h [new file with mode: 0644]
dfg/DFGGenerationInfo.h [new file with mode: 0644]
dfg/DFGGraph.cpp [new file with mode: 0644]
dfg/DFGGraph.h [new file with mode: 0644]
dfg/DFGJITCodeGenerator.cpp [new file with mode: 0644]
dfg/DFGJITCodeGenerator.h [new file with mode: 0644]
dfg/DFGJITCompiler.cpp [new file with mode: 0644]
dfg/DFGJITCompiler.h [new file with mode: 0644]
dfg/DFGNode.h [new file with mode: 0644]
dfg/DFGNonSpeculativeJIT.cpp [new file with mode: 0644]
dfg/DFGNonSpeculativeJIT.h [new file with mode: 0644]
dfg/DFGOperations.cpp [new file with mode: 0644]
dfg/DFGOperations.h [new file with mode: 0644]
dfg/DFGRegisterBank.h [new file with mode: 0644]
dfg/DFGScoreBoard.h [new file with mode: 0644]
dfg/DFGSpeculativeJIT.cpp [new file with mode: 0644]
dfg/DFGSpeculativeJIT.h [new file with mode: 0644]
docs/make-bytecode-docs.pl
gyp/JavaScriptCore.gyp [new file with mode: 0644]
gyp/generate-derived-sources.sh [new file with mode: 0755]
gyp/generate-dtrace-header.sh [new file with mode: 0755]
gyp/gtk.gyp [new file with mode: 0644]
gyp/run-if-exists.sh [new file with mode: 0755]
gyp/update-info-plist.sh [new file with mode: 0755]
heap/ConservativeRoots.cpp [new file with mode: 0644]
heap/ConservativeRoots.h [new file with mode: 0644]
heap/Handle.h [new file with mode: 0644]
heap/HandleHeap.cpp [new file with mode: 0644]
heap/HandleHeap.h [new file with mode: 0644]
heap/HandleStack.cpp [new file with mode: 0644]
heap/HandleStack.h [new file with mode: 0644]
heap/HandleTypes.h [new file with mode: 0644]
heap/Heap.cpp [new file with mode: 0644]
heap/Heap.h [new file with mode: 0644]
heap/Local.h [new file with mode: 0644]
heap/LocalScope.h [new file with mode: 0644]
heap/MachineStackMarker.cpp [new file with mode: 0644]
heap/MachineStackMarker.h [new file with mode: 0644]
heap/MarkStack.cpp [new file with mode: 0644]
heap/MarkStack.h [new file with mode: 0644]
heap/MarkStackPosix.cpp [new file with mode: 0644]
heap/MarkStackSymbian.cpp [new file with mode: 0644]
heap/MarkStackWin.cpp [new file with mode: 0644]
heap/MarkedBlock.cpp [new file with mode: 0644]
heap/MarkedBlock.h [new file with mode: 0644]
heap/MarkedSpace.cpp [new file with mode: 0644]
heap/MarkedSpace.h [new file with mode: 0644]
heap/Strong.h [new file with mode: 0644]
heap/Weak.h [new file with mode: 0644]
interpreter/CachedCall.h
interpreter/CallFrame.cpp
interpreter/CallFrame.h
interpreter/CallFrameClosure.h
interpreter/Interpreter.cpp
interpreter/Interpreter.h
interpreter/Register.h
interpreter/RegisterFile.cpp
interpreter/RegisterFile.h
jit/ExecutableAllocator.cpp
jit/ExecutableAllocator.h
jit/ExecutableAllocatorFixedVMPool.cpp
jit/ExecutableAllocatorPosix.cpp [deleted file]
jit/ExecutableAllocatorSymbian.cpp [deleted file]
jit/ExecutableAllocatorWin.cpp [deleted file]
jit/JIT.cpp
jit/JIT.h
jit/JITArithmetic.cpp
jit/JITArithmetic32_64.cpp
jit/JITCall.cpp
jit/JITCall32_64.cpp [new file with mode: 0644]
jit/JITCode.h
jit/JITInlineMethods.h
jit/JITOpcodes.cpp
jit/JITOpcodes32_64.cpp
jit/JITPropertyAccess.cpp
jit/JITPropertyAccess32_64.cpp
jit/JITStubCall.h
jit/JITStubs.cpp
jit/JITStubs.h
jit/JITWriteBarrier.h [new file with mode: 0644]
jit/JSInterfaceJIT.h
jit/SpecializedThunkJIT.h
jit/ThunkGenerators.cpp
jit/ThunkGenerators.h
jsc.cpp
jsc.pro
jscore.bkl [deleted file]
make-generated-sources.sh
os-win32/inttypes.h [new file with mode: 0644]
parser/ASTBuilder.h [new file with mode: 0644]
parser/Grammar.y [deleted file]
parser/JSParser.cpp [new file with mode: 0644]
parser/JSParser.h [new file with mode: 0644]
parser/Lexer.cpp
parser/Lexer.h
parser/NodeConstructors.h
parser/Nodes.cpp
parser/Nodes.h
parser/Parser.cpp
parser/Parser.h
parser/ParserArena.cpp
parser/ParserArena.h
parser/SourceProvider.h
parser/SourceProviderCache.cpp [new file with mode: 0644]
parser/SourceProviderCache.h [new file with mode: 0644]
parser/SourceProviderCacheItem.h [new file with mode: 0644]
parser/SyntaxChecker.h [new file with mode: 0644]
pcre/AUTHORS [deleted file]
pcre/COPYING [deleted file]
pcre/dftables [deleted file]
pcre/pcre.h [deleted file]
pcre/pcre.pri [deleted file]
pcre/pcre_compile.cpp [deleted file]
pcre/pcre_exec.cpp [deleted file]
pcre/pcre_internal.h [deleted file]
pcre/pcre_tables.cpp [deleted file]
pcre/pcre_ucp_searchfuncs.cpp [deleted file]
pcre/pcre_xclass.cpp [deleted file]
pcre/ucpinternal.h [deleted file]
pcre/ucptable.cpp [deleted file]
profiler/CallIdentifier.h
profiler/Profile.cpp
profiler/ProfileGenerator.cpp
profiler/ProfileGenerator.h
profiler/ProfileNode.cpp
profiler/ProfileNode.h
profiler/Profiler.cpp
profiler/Profiler.h
profiler/ProfilerServer.mm
qt/ChangeLog [new file with mode: 0644]
qt/api/QtScript.pro
qt/api/qscriptconverter_p.h
qt/api/qscriptengine.cpp
qt/api/qscriptengine.h
qt/api/qscriptengine_p.cpp
qt/api/qscriptengine_p.h
qt/api/qscriptfunction.cpp [new file with mode: 0644]
qt/api/qscriptfunction_p.h [new file with mode: 0644]
qt/api/qscriptoriginalglobalobject_p.h [new file with mode: 0644]
qt/api/qscriptprogram_p.h
qt/api/qscriptstring_p.h
qt/api/qscriptsyntaxcheckresult.cpp
qt/api/qscriptvalue.cpp
qt/api/qscriptvalue.h
qt/api/qscriptvalue_p.h
qt/api/qscriptvalueiterator.cpp [new file with mode: 0644]
qt/api/qscriptvalueiterator.h [new file with mode: 0644]
qt/api/qscriptvalueiterator_p.h [new file with mode: 0644]
qt/benchmarks/benchmarks.pri [new file with mode: 0644]
qt/benchmarks/benchmarks.pro [new file with mode: 0644]
qt/benchmarks/qscriptengine/qscriptengine.pro [new file with mode: 0644]
qt/benchmarks/qscriptengine/tst_qscriptengine.cpp [new file with mode: 0644]
qt/benchmarks/qscriptvalue/qscriptvalue.pro [new file with mode: 0644]
qt/benchmarks/qscriptvalue/tst_qscriptvalue.cpp [new file with mode: 0644]
qt/tests/qscriptengine/tst_qscriptengine.cpp
qt/tests/qscriptvalue/qscriptvalue.pro
qt/tests/qscriptvalue/tst_qscriptvalue.cpp
qt/tests/qscriptvalue/tst_qscriptvalue.h
qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp [deleted file]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp [new file with mode: 0644]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_init.cpp [new file with mode: 0644]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_istype.cpp [new file with mode: 0644]
qt/tests/qscriptvalue/tst_qscriptvalue_generated_totype.cpp [new file with mode: 0644]
qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro [new file with mode: 0644]
qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp [new file with mode: 0644]
qt/tests/tests.pro
runtime/ArgList.cpp
runtime/ArgList.h
runtime/Arguments.cpp
runtime/Arguments.h
runtime/ArrayConstructor.cpp
runtime/ArrayConstructor.h
runtime/ArrayPrototype.cpp
runtime/ArrayPrototype.h
runtime/BatchedTransitionOptimizer.h
runtime/BooleanConstructor.cpp
runtime/BooleanConstructor.h
runtime/BooleanObject.cpp
runtime/BooleanObject.h
runtime/BooleanPrototype.cpp
runtime/BooleanPrototype.h
runtime/CachedTranscendentalFunction.h
runtime/CallData.cpp
runtime/CallData.h
runtime/Collector.cpp [deleted file]
runtime/Collector.h [deleted file]
runtime/CollectorHeapIterator.h [deleted file]
runtime/CommonIdentifiers.cpp
runtime/CommonIdentifiers.h
runtime/Completion.cpp
runtime/Completion.h
runtime/ConstructData.cpp
runtime/ConstructData.h
runtime/DateConstructor.cpp
runtime/DateConstructor.h
runtime/DateConversion.cpp
runtime/DateInstance.cpp
runtime/DateInstance.h
runtime/DateInstanceCache.h
runtime/DatePrototype.cpp
runtime/DatePrototype.h
runtime/Error.cpp
runtime/Error.h
runtime/ErrorConstructor.cpp
runtime/ErrorConstructor.h
runtime/ErrorInstance.cpp
runtime/ErrorInstance.h
runtime/ErrorPrototype.cpp
runtime/ErrorPrototype.h
runtime/ExceptionHelpers.cpp
runtime/ExceptionHelpers.h
runtime/Executable.cpp
runtime/Executable.h
runtime/FunctionConstructor.cpp
runtime/FunctionConstructor.h
runtime/FunctionPrototype.cpp
runtime/FunctionPrototype.h
runtime/GCActivityCallback.cpp [new file with mode: 0644]
runtime/GCActivityCallback.h [new file with mode: 0644]
runtime/GCActivityCallbackCF.cpp [new file with mode: 0644]
runtime/GetterSetter.cpp
runtime/GetterSetter.h
runtime/GlobalEvalFunction.cpp [deleted file]
runtime/GlobalEvalFunction.h [deleted file]
runtime/Identifier.cpp
runtime/Identifier.h
runtime/InitializeThreading.cpp
runtime/InternalFunction.cpp
runtime/InternalFunction.h
runtime/JSAPIValueWrapper.cpp
runtime/JSAPIValueWrapper.h
runtime/JSActivation.cpp
runtime/JSActivation.h
runtime/JSArray.cpp
runtime/JSArray.h
runtime/JSByteArray.cpp
runtime/JSByteArray.h
runtime/JSCell.cpp
runtime/JSCell.h
runtime/JSChunk.cpp [new file with mode: 0644]
runtime/JSChunk.h [new file with mode: 0644]
runtime/JSFunction.cpp
runtime/JSFunction.h
runtime/JSGlobalData.cpp
runtime/JSGlobalData.h
runtime/JSGlobalObject.cpp
runtime/JSGlobalObject.h
runtime/JSGlobalObjectFunctions.cpp
runtime/JSGlobalObjectFunctions.h
runtime/JSImmediate.cpp [deleted file]
runtime/JSImmediate.h [deleted file]
runtime/JSLock.cpp
runtime/JSLock.h
runtime/JSNotAnObject.cpp
runtime/JSNotAnObject.h
runtime/JSNumberCell.cpp [deleted file]
runtime/JSNumberCell.h [deleted file]
runtime/JSONObject.cpp
runtime/JSONObject.h
runtime/JSObject.cpp
runtime/JSObject.h
runtime/JSObjectWithGlobalObject.cpp [new file with mode: 0644]
runtime/JSObjectWithGlobalObject.h [new file with mode: 0644]
runtime/JSPropertyNameIterator.cpp
runtime/JSPropertyNameIterator.h
runtime/JSStaticScopeObject.cpp
runtime/JSStaticScopeObject.h
runtime/JSString.cpp
runtime/JSString.h
runtime/JSStringBuilder.h
runtime/JSType.h
runtime/JSTypeInfo.h
runtime/JSValue.cpp
runtime/JSValue.h
runtime/JSValueInlineMethods.h [new file with mode: 0644]
runtime/JSVariableObject.cpp
runtime/JSVariableObject.h
runtime/JSWrapperObject.cpp
runtime/JSWrapperObject.h
runtime/JSZombie.cpp
runtime/JSZombie.h
runtime/LiteralParser.cpp
runtime/LiteralParser.h
runtime/Lookup.cpp
runtime/Lookup.h
runtime/MarkStack.cpp [deleted file]
runtime/MarkStack.h [deleted file]
runtime/MarkStackNone.cpp [deleted file]
runtime/MarkStackPosix.cpp [deleted file]
runtime/MarkStackSymbian.cpp [deleted file]
runtime/MarkStackWin.cpp [deleted file]
runtime/MathObject.cpp
runtime/MathObject.h
runtime/MemoryStatistics.cpp [new file with mode: 0644]
runtime/MemoryStatistics.h [new file with mode: 0644]
runtime/NativeErrorConstructor.cpp
runtime/NativeErrorConstructor.h
runtime/NativeErrorPrototype.cpp
runtime/NativeErrorPrototype.h
runtime/NativeFunctionWrapper.h [deleted file]
runtime/NumberConstructor.cpp
runtime/NumberConstructor.h
runtime/NumberObject.cpp
runtime/NumberObject.h
runtime/NumberPrototype.cpp
runtime/NumberPrototype.h
runtime/NumericStrings.h
runtime/ObjectConstructor.cpp
runtime/ObjectConstructor.h
runtime/ObjectPrototype.cpp
runtime/ObjectPrototype.h
runtime/Operations.cpp
runtime/Operations.h
runtime/PropertyMapHashTable.h
runtime/PropertyNameArray.cpp
runtime/PropertyNameArray.h
runtime/PropertySlot.cpp
runtime/PropertySlot.h
runtime/Protect.h
runtime/PrototypeFunction.cpp [deleted file]
runtime/PrototypeFunction.h [deleted file]
runtime/PutPropertySlot.h
runtime/RegExp.cpp
runtime/RegExp.h
runtime/RegExpCache.cpp
runtime/RegExpCache.h
runtime/RegExpConstructor.cpp
runtime/RegExpConstructor.h
runtime/RegExpKey.h
runtime/RegExpObject.cpp
runtime/RegExpObject.h
runtime/RegExpPrototype.cpp
runtime/RegExpPrototype.h
runtime/RopeImpl.cpp
runtime/RopeImpl.h
runtime/ScopeChain.cpp
runtime/ScopeChain.h
runtime/ScopeChainMark.h
runtime/SmallStrings.cpp
runtime/SmallStrings.h
runtime/StrictEvalActivation.cpp [new file with mode: 0644]
runtime/StrictEvalActivation.h [new file with mode: 0644]
runtime/StringBuilder.h [deleted file]
runtime/StringConstructor.cpp
runtime/StringConstructor.h
runtime/StringObject.cpp
runtime/StringObject.h
runtime/StringObjectThatMasqueradesAsUndefined.h
runtime/StringPrototype.cpp
runtime/StringPrototype.h
runtime/StringRecursionChecker.cpp [new file with mode: 0644]
runtime/StringRecursionChecker.h [new file with mode: 0644]
runtime/Structure.cpp
runtime/Structure.h
runtime/StructureChain.cpp
runtime/StructureChain.h
runtime/StructureTransitionTable.h
runtime/SymbolTable.h
runtime/TimeoutChecker.cpp
runtime/TimeoutChecker.h
runtime/UString.cpp
runtime/UString.h
runtime/UStringBuilder.h [new file with mode: 0644]
runtime/UStringConcatenate.h [new file with mode: 0644]
runtime/UStringImpl.h [deleted file]
runtime/WeakGCMap.h
runtime/WeakGCPtr.h [deleted file]
runtime/WeakRandom.h
runtime/WriteBarrier.h [new file with mode: 0644]
shell/CMakeLists.txt [new file with mode: 0644]
shell/CMakeListsEfl.txt [new file with mode: 0644]
shell/CMakeListsWinCE.txt [new file with mode: 0644]
tests/mozilla/expected.html
tests/mozilla/js1_2/regexp/RegExp_input.js
tests/mozilla/js1_2/regexp/RegExp_input_as_array.js
wscript
wtf/ASCIICType.h
wtf/AVLTree.h
wtf/Alignment.h [new file with mode: 0644]
wtf/AlwaysInline.h
wtf/Assertions.cpp
wtf/Assertions.h
wtf/Atomics.h
wtf/Bitmap.h [new file with mode: 0644]
wtf/BlockStack.h [new file with mode: 0644]
wtf/BloomFilter.h [new file with mode: 0644]
wtf/BumpPointerAllocator.h [new file with mode: 0644]
wtf/ByteArray.cpp
wtf/ByteArray.h
wtf/CMakeLists.txt [new file with mode: 0644]
wtf/CMakeListsEfl.txt [new file with mode: 0644]
wtf/CMakeListsWinCE.txt [new file with mode: 0644]
wtf/Complex.h
wtf/CrossThreadRefCounted.h
wtf/CryptographicallyRandomNumber.cpp [new file with mode: 0644]
wtf/CryptographicallyRandomNumber.h [new file with mode: 0644]
wtf/CurrentTime.cpp
wtf/CurrentTime.h
wtf/DateMath.cpp
wtf/DateMath.h
wtf/DecimalNumber.cpp [new file with mode: 0644]
wtf/DecimalNumber.h [new file with mode: 0644]
wtf/Decoder.h [new file with mode: 0644]
wtf/Deque.h
wtf/DoublyLinkedList.h [new file with mode: 0644]
wtf/DynamicAnnotations.cpp [new file with mode: 0644]
wtf/DynamicAnnotations.h [new file with mode: 0644]
wtf/Encoder.h [new file with mode: 0644]
wtf/ExportMacros.h [new file with mode: 0644]
wtf/FastAllocBase.h
wtf/FastMalloc.cpp
wtf/FastMalloc.h
wtf/FixedArray.h [new file with mode: 0644]
wtf/Forward.h
wtf/HashCountedSet.h
wtf/HashIterators.h
wtf/HashMap.h
wtf/HashSet.h
wtf/HashTable.h
wtf/HashTraits.h
wtf/HexNumber.h [new file with mode: 0644]
wtf/ListHashSet.h
wtf/Locker.h
wtf/MD5.cpp
wtf/MD5.h
wtf/MainThread.cpp
wtf/MallocZoneSupport.h
wtf/MathExtras.h
wtf/MessageQueue.h
wtf/NonCopyingSort.h [new file with mode: 0644]
wtf/Noncopyable.h
wtf/NullPtr.cpp [new file with mode: 0644]
wtf/NullPtr.h [new file with mode: 0644]
wtf/OSAllocator.h [new file with mode: 0644]
wtf/OSAllocatorPosix.cpp [new file with mode: 0644]
wtf/OSAllocatorSymbian.cpp [new file with mode: 0644]
wtf/OSAllocatorWin.cpp [new file with mode: 0644]
wtf/OSRandomSource.cpp [new file with mode: 0644]
wtf/OSRandomSource.h [new file with mode: 0644]
wtf/OwnArrayPtr.h
wtf/OwnFastMallocPtr.h
wtf/OwnPtr.h
wtf/OwnPtrCommon.h
wtf/PageAllocation.h [new file with mode: 0644]
wtf/PageAllocationAligned.cpp [new file with mode: 0644]
wtf/PageAllocationAligned.h [new file with mode: 0644]
wtf/PageAllocatorSymbian.h [new file with mode: 0644]
wtf/PageBlock.cpp [new file with mode: 0644]
wtf/PageBlock.h [new file with mode: 0644]
wtf/PageReservation.h [new file with mode: 0644]
wtf/ParallelJobs.h [new file with mode: 0644]
wtf/ParallelJobsGeneric.cpp [new file with mode: 0644]
wtf/ParallelJobsGeneric.h [new file with mode: 0644]
wtf/ParallelJobsLibdispatch.h [new file with mode: 0644]
wtf/ParallelJobsOpenMP.h [new file with mode: 0644]
wtf/PassOwnArrayPtr.h [new file with mode: 0644]
wtf/PassOwnPtr.h
wtf/PassRefPtr.h
wtf/PassTraits.h [new file with mode: 0644]
wtf/Platform.h
wtf/RandomNumber.cpp
wtf/RandomNumber.h
wtf/RandomNumberSeed.h
wtf/RefCounted.h
wtf/RefCountedLeakCounter.cpp
wtf/RefPtr.h
wtf/RefPtrHashMap.h
wtf/RetainPtr.h
wtf/SHA1.cpp [new file with mode: 0644]
wtf/SHA1.h [new file with mode: 0644]
wtf/SentinelLinkedList.h [new file with mode: 0644]
wtf/SinglyLinkedList.h [new file with mode: 0644]
wtf/SizeLimits.cpp [new file with mode: 0644]
wtf/StackBounds.cpp [new file with mode: 0644]
wtf/StackBounds.h [new file with mode: 0644]
wtf/StdLibExtras.h
wtf/StringExtras.h
wtf/StringHashFunctions.h [deleted file]
wtf/StringHasher.h [new file with mode: 0644]
wtf/TCPageMap.h
wtf/TCSpinLock.h
wtf/TCSystemAlloc.cpp
wtf/ThreadFunctionInvocation.h [new file with mode: 0644]
wtf/ThreadIdentifierDataPthreads.h
wtf/ThreadSafeRefCounted.h [new file with mode: 0644]
wtf/ThreadSafeShared.h [deleted file]
wtf/ThreadSpecific.h
wtf/ThreadSpecificWin.cpp
wtf/Threading.cpp
wtf/Threading.h
wtf/ThreadingPrimitives.h
wtf/ThreadingPthreads.cpp
wtf/ThreadingWin.cpp
wtf/TypeTraits.cpp
wtf/TypeTraits.h
wtf/UnusedParam.h
wtf/VMTags.h
wtf/Vector.h
wtf/Vector3.h [deleted file]
wtf/VectorTraits.h
wtf/WTFThreadData.cpp
wtf/WTFThreadData.h
wtf/brew/OwnPtrBrew.cpp
wtf/brew/RefPtrBrew.h [new file with mode: 0644]
wtf/brew/ShellBrew.h
wtf/brew/StringBrew.cpp [new file with mode: 0644]
wtf/dtoa.cpp
wtf/dtoa.h
wtf/efl/MainThreadEfl.cpp
wtf/gobject/GOwnPtr.cpp
wtf/gobject/GOwnPtr.h
wtf/gobject/GRefPtr.cpp
wtf/gobject/GRefPtr.h
wtf/gobject/GTypedefs.h [new file with mode: 0644]
wtf/gtk/ThreadingGtk.cpp
wtf/haiku/StringHaiku.cpp [new file with mode: 0644]
wtf/mac/MainThreadMac.mm
wtf/qt/StringQt.cpp
wtf/qt/ThreadingQt.cpp
wtf/symbian/BlockAllocatorSymbian.cpp [deleted file]
wtf/symbian/BlockAllocatorSymbian.h [deleted file]
wtf/text/AtomicString.cpp
wtf/text/AtomicString.h
wtf/text/AtomicStringHash.h [new file with mode: 0644]
wtf/text/AtomicStringImpl.h
wtf/text/CString.cpp
wtf/text/CString.h
wtf/text/StringBuffer.h
wtf/text/StringBuilder.cpp [new file with mode: 0644]
wtf/text/StringBuilder.h [new file with mode: 0644]
wtf/text/StringConcatenate.h [new file with mode: 0644]
wtf/text/StringHash.h
wtf/text/StringImpl.cpp
wtf/text/StringImpl.h
wtf/text/StringImplBase.h
wtf/text/StringOperators.h [new file with mode: 0644]
wtf/text/StringStatics.cpp
wtf/text/TextPosition.h [new file with mode: 0644]
wtf/text/WTFString.cpp
wtf/text/WTFString.h
wtf/unicode/CharacterNames.h [new file with mode: 0644]
wtf/unicode/Collator.h
wtf/unicode/CollatorDefault.cpp
wtf/unicode/UTF8.cpp
wtf/unicode/UTF8.h
wtf/unicode/Unicode.h
wtf/unicode/UnicodeMacrosFromICU.h [new file with mode: 0644]
wtf/unicode/brew/UnicodeBrew.cpp [new file with mode: 0644]
wtf/unicode/brew/UnicodeBrew.h [new file with mode: 0644]
wtf/unicode/glib/UnicodeGLib.cpp
wtf/unicode/glib/UnicodeMacrosFromICU.h [deleted file]
wtf/unicode/icu/CollatorICU.cpp
wtf/unicode/qt4/UnicodeQt4.h
wtf/unicode/wince/UnicodeWinCE.cpp [new file with mode: 0644]
wtf/unicode/wince/UnicodeWinCE.h [new file with mode: 0644]
wtf/unicode/wince/UnicodeWince.cpp [deleted file]
wtf/unicode/wince/UnicodeWince.h [deleted file]
wtf/url/api/ParsedURL.cpp [new file with mode: 0644]
wtf/url/api/ParsedURL.h [new file with mode: 0644]
wtf/url/api/URLString.h [new file with mode: 0644]
wtf/url/src/RawURLBuffer.h [new file with mode: 0644]
wtf/url/src/URLBuffer.h [new file with mode: 0644]
wtf/url/src/URLCharacterTypes.cpp [new file with mode: 0644]
wtf/url/src/URLCharacterTypes.h [new file with mode: 0644]
wtf/url/src/URLComponent.h
wtf/url/src/URLEscape.cpp [new file with mode: 0644]
wtf/url/src/URLEscape.h [new file with mode: 0644]
wtf/url/src/URLParser.h [new file with mode: 0644]
wtf/url/src/URLQueryCanonicalizer.h [new file with mode: 0644]
wtf/wince/FastMallocWinCE.h [new file with mode: 0644]
wtf/wince/FastMallocWince.h [deleted file]
wtf/wince/mt19937ar.c [deleted file]
wtf/wtf.pri [new file with mode: 0644]
wtf/wx/StringWx.cpp [new file with mode: 0644]
yarr/RegexCompiler.cpp [deleted file]
yarr/RegexCompiler.h [deleted file]
yarr/RegexInterpreter.cpp [deleted file]
yarr/RegexInterpreter.h [deleted file]
yarr/RegexJIT.cpp [deleted file]
yarr/RegexJIT.h [deleted file]
yarr/RegexParser.h [deleted file]
yarr/RegexPattern.h [deleted file]
yarr/Yarr.h [new file with mode: 0644]
yarr/YarrInterpreter.cpp [new file with mode: 0644]
yarr/YarrInterpreter.h [new file with mode: 0644]
yarr/YarrJIT.cpp [new file with mode: 0644]
yarr/YarrJIT.h [new file with mode: 0644]
yarr/YarrParser.h [new file with mode: 0644]
yarr/YarrPattern.cpp [new file with mode: 0644]
yarr/YarrPattern.h [new file with mode: 0644]
yarr/YarrSyntaxChecker.cpp [new file with mode: 0644]
yarr/YarrSyntaxChecker.h [new file with mode: 0644]
yarr/yarr.pri [new file with mode: 0644]

index ba00d02e1071888e34422544356ae3d6644a5eff..4294d3d682a816bb0467d27de6599b0f78325026 100644 (file)
@@ -111,8 +111,8 @@ inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v)
     if (!v)
         return 0;
     if (!v.isCell())
-        return reinterpret_cast<JSValueRef>(asCell(JSC::jsAPIValueWrapper(exec, v)));
-    return reinterpret_cast<JSValueRef>(asCell(v));
+        return reinterpret_cast<JSValueRef>(JSC::jsAPIValueWrapper(exec, v).asCell());
+    return reinterpret_cast<JSValueRef>(v.asCell());
 #else
     UNUSED_PARAM(exec);
     return reinterpret_cast<JSValueRef>(JSC::JSValue::encode(v));
index 892068d916746d6788de63cbecd4a205f37f2db0..2e13851417044b463b9941a9a5ec87d19ce63b4b 100644 (file)
@@ -27,6 +27,7 @@
 #define APIShims_h
 
 #include "CallFrame.h"
+#include "GCActivityCallback.h"
 #include "JSLock.h"
 #include <wtf/WTFThreadData.h>
 
@@ -38,8 +39,12 @@ protected:
         : m_globalData(globalData)
         , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
     {
+        UNUSED_PARAM(registerThread);
+#if ENABLE(JSC_MULTIPLE_THREADS)
         if (registerThread)
-            globalData->heap.registerThread();
+            globalData->heap.machineThreads().addCurrentThread();
+#endif
+        m_globalData->heap.activityCallback()->synchronize();
         m_globalData->timeoutChecker.start();
     }
 
@@ -85,6 +90,7 @@ public:
 
     ~APICallbackShim()
     {
+        m_globalData->heap.activityCallback()->synchronize();
         wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable);
     }
 
index 2e16720cebb18a822179b9ae3fded3d069161315..fed54fe23ef340594b8d17eaf668c11e18675cae 100644 (file)
@@ -63,20 +63,26 @@ typedef const struct OpaqueJSValue* JSValueRef;
 typedef struct OpaqueJSValue* JSObjectRef;
 
 /* JavaScript symbol exports */
+/* These rules should stay the same as in WebKit2/Shared/API/c/WKBase.h */
 
 #undef JS_EXPORT
 #if defined(JS_NO_EXPORT)
-    #define JS_EXPORT
+#define JS_EXPORT
 #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__)
-    #define JS_EXPORT __attribute__((visibility("default")))
-#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE)
-    #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
-        #define JS_EXPORT __declspec(dllexport)
-    #else
-        #define JS_EXPORT __declspec(dllimport)
-    #endif
+#define JS_EXPORT __attribute__((visibility("default")))
+#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) || defined(__CC_ARM) || defined(__ARMCC__)
+#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
+#define JS_EXPORT __declspec(dllexport)
 #else
-    #define JS_EXPORT
+#define JS_EXPORT __declspec(dllimport)
+#endif
+#else /* !defined(JS_NO_EXPORT) */
+#define JS_EXPORT
+#endif /* defined(JS_NO_EXPORT) */
+
+/* JS tests uses WTF but has no config.h, so we need to set the export defines here. */
+#ifndef WTF_EXPORT_PRIVATE
+#define WTF_EXPORT_PRIVATE JS_EXPORT
 #endif
 
 #ifdef __cplusplus
index 9c5f6d73e6e1ab66503fd177f6817400a399335b..fa9d216dd11250127ee685fe1ec8d59ff268c99e 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "APIShims.h"
 #include "APICast.h"
+#include <runtime/Error.h>
 #include <runtime/JSGlobalObject.h>
 #include <runtime/JSLock.h>
 #include <runtime/ObjectPrototype.h>
 
 namespace JSC {
 
-const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 };
+const ClassInfo JSCallbackConstructor::s_info = { "CallbackConstructor", &JSObjectWithGlobalObject::s_info, 0, 0 };
 
-JSCallbackConstructor::JSCallbackConstructor(NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
-    : JSObject(structure)
+JSCallbackConstructor::JSCallbackConstructor(JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback)
+    : JSObjectWithGlobalObject(globalObject, structure)
     , m_class(jsClass)
     , m_callback(callback)
 {
+    ASSERT(inherits(&s_info));
     if (m_class)
         JSClassRetain(jsClass);
 }
@@ -52,17 +54,18 @@ JSCallbackConstructor::~JSCallbackConstructor()
         JSClassRelease(m_class);
 }
 
-static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec)
 {
+    JSObject* constructor = exec->callee();
     JSContextRef ctx = toRef(exec);
     JSObjectRef constructorRef = toRef(constructor);
 
     JSObjectCallAsConstructorCallback callback = static_cast<JSCallbackConstructor*>(constructor)->callback();
     if (callback) {
-        int argumentCount = static_cast<int>(args.size());
+        int argumentCount = static_cast<int>(exec->argumentCount());
         Vector<JSValueRef, 16> arguments(argumentCount);
         for (int i = 0; i < argumentCount; i++)
-            arguments[i] = toRef(exec, args.at(i));
+            arguments[i] = toRef(exec, exec->argument(i));
 
         JSValueRef exception = 0;
         JSObjectRef result;
@@ -71,11 +74,11 @@ static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, con
             result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception);
         }
         if (exception)
-            exec->setException(toJS(exec, exception));
-        return toJS(result);
+            throwError(exec, toJS(exec, exception));
+        return JSValue::encode(toJS(result));
     }
     
-    return toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0));
+    return JSValue::encode(toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0)));
 }
 
 ConstructType JSCallbackConstructor::getConstructData(ConstructData& constructData)
index e52994724e2fd0d4b9c290c5890bceccaeb2e923..64b237dfd3d8baacc8a99389380f05edea69212d 100644 (file)
 #define JSCallbackConstructor_h
 
 #include "JSObjectRef.h"
-#include <runtime/JSObject.h>
+#include <runtime/JSObjectWithGlobalObject.h>
 
 namespace JSC {
 
-class JSCallbackConstructor : public JSObject {
+class JSCallbackConstructor : public JSObjectWithGlobalObject {
 public:
-    JSCallbackConstructor(NonNullPassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback);
+    JSCallbackConstructor(JSGlobalObject*, Structure*, JSClassRef, JSObjectCallAsConstructorCallback);
     virtual ~JSCallbackConstructor();
     JSClassRef classRef() const { return m_class; }
     JSObjectCallAsConstructorCallback callback() const { return m_callback; }
-    static const ClassInfo info;
-    
-    static PassRefPtr<Structure> createStructure(JSValue proto) 
-    { 
-        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+    static const ClassInfo s_info;
+
+    static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
+    {
+        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
     }
 
 protected:
@@ -49,7 +49,6 @@ protected:
 
 private:
     virtual ConstructType getConstructData(ConstructData&);
-    virtual const ClassInfo* classInfo() const { return &info; }
 
     JSClassRef m_class;
     JSObjectCallAsConstructorCallback m_callback;
index 63c8add854cd59e52213b8706b2bab6773f476fc..28b341923dc350e43f88ec9720dce5b343dbc4a7 100644 (file)
@@ -29,6 +29,7 @@
 #include "APIShims.h"
 #include "APICast.h"
 #include "CodeBlock.h"
+#include "ExceptionHelpers.h"
 #include "JSFunction.h"
 #include "FunctionPrototype.h"
 #include <runtime/JSGlobalObject.h>
@@ -39,35 +40,36 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction);
 
-const ClassInfo JSCallbackFunction::info = { "CallbackFunction", &InternalFunction::info, 0, 0 };
+const ClassInfo JSCallbackFunction::s_info = { "CallbackFunction", &InternalFunction::s_info, 0, 0 };
 
-JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSObjectCallAsFunctionCallback callback, const Identifier& name)
-    : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject()->callbackFunctionStructure(), name)
+JSCallbackFunction::JSCallbackFunction(ExecState* exec, JSGlobalObject* globalObject, JSObjectCallAsFunctionCallback callback, const Identifier& name)
+    : InternalFunction(&exec->globalData(), globalObject, globalObject->callbackFunctionStructure(), name)
     , m_callback(callback)
 {
+    ASSERT(inherits(&s_info));
 }
 
-JSValue JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSCallbackFunction::call(ExecState* exec)
 {
     JSContextRef execRef = toRef(exec);
-    JSObjectRef functionRef = toRef(functionObject);
-    JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec));
+    JSObjectRef functionRef = toRef(exec->callee());
+    JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec));
 
-    int argumentCount = static_cast<int>(args.size());
+    int argumentCount = static_cast<int>(exec->argumentCount());
     Vector<JSValueRef, 16> arguments(argumentCount);
     for (int i = 0; i < argumentCount; i++)
-        arguments[i] = toRef(exec, args.at(i));
+        arguments[i] = toRef(exec, exec->argument(i));
 
     JSValueRef exception = 0;
     JSValueRef result;
     {
         APICallbackShim callbackShim(exec);
-        result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
+        result = static_cast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception);
     }
     if (exception)
-        exec->setException(toJS(exec, exception));
+        throwError(exec, toJS(exec, exception));
 
-    return toJS(exec, result);
+    return JSValue::encode(toJS(exec, result));
 }
 
 CallType JSCallbackFunction::getCallData(CallData& callData)
index 10dae6b73f0437c8a68f743573deaf601e6fca8c..55c9ed4ae87c2290efb480446e98065d9c1849ef 100644 (file)
@@ -33,22 +33,21 @@ namespace JSC {
 
 class JSCallbackFunction : public InternalFunction {
 public:
-    JSCallbackFunction(ExecState*, JSObjectCallAsFunctionCallback, const Identifier& name);
+    JSCallbackFunction(ExecState*, JSGlobalObject*, JSObjectCallAsFunctionCallback, const Identifier& name);
 
-    static const ClassInfo info;
+    static const ClassInfo s_info;
     
     // InternalFunction mish-mashes constructor and function behavior -- we should 
     // refactor the code so this override isn't necessary
-    static PassRefPtr<Structure> createStructure(JSValue proto) 
+    static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
     { 
-        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
     }
 
 private:
     virtual CallType getCallData(CallData&);
-    virtual const ClassInfo* classInfo() const { return &info; }
 
-    static JSValue JSC_HOST_CALL call(ExecState*, JSObject*, JSValue, const ArgList&);
+    static EncodedJSValue JSC_HOST_CALL call(ExecState*);
 
     JSObjectCallAsFunctionCallback m_callback;
 };
index b36c19414473121bce973eab757dd36a1da995b0..6a7462a9040f8ca1d7fb24ab959fd6003587cb64 100644 (file)
 #include "config.h"
 #include "JSCallbackObject.h"
 
-#include "Collector.h"
+#include "Heap.h"
 #include <wtf/text/StringHash.h>
 
 namespace JSC {
 
-ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSObject>);
+ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSObjectWithGlobalObject>);
 ASSERT_CLASS_FITS_IN_CELL(JSCallbackObject<JSGlobalObject>);
 
 // Define the two types of JSCallbackObjects we support.
-template <> const ClassInfo JSCallbackObject<JSObject>::info = { "CallbackObject", 0, 0, 0 };
-template <> const ClassInfo JSCallbackObject<JSGlobalObject>::info = { "CallbackGlobalObject", 0, 0, 0 };
+template <> const ClassInfo JSCallbackObject<JSObjectWithGlobalObject>::s_info = { "CallbackObject", &JSObjectWithGlobalObject::s_info, 0, 0 };
+template <> const ClassInfo JSCallbackObject<JSGlobalObject>::s_info = { "CallbackGlobalObject", &JSGlobalObject::s_info, 0, 0 };
 
+void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context)
+{
+    JSClassRef jsClass = static_cast<JSClassRef>(context);
+    JSObjectRef thisRef = toRef(asObject(handle.get()));
+    
+    for (; jsClass; jsClass = jsClass->parentClass)
+        if (JSObjectFinalizeCallback finalize = jsClass->finalize)
+            finalize(thisRef);
+    HandleSlot slot = handle.slot();
+    HandleHeap::heapFor(slot)->deallocate(slot);
+}
+    
 } // namespace JSC
index 1cf7a02b256e11521d8a699ec04f462d47bd81cb..2b322e7cf2c8386dc58c12d2fa7235496c5633bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
 #include "JSObjectRef.h"
 #include "JSValueRef.h"
 #include "JSObject.h"
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
-struct JSCallbackObjectData {
+struct JSCallbackObjectData : WeakHandleOwner {
     JSCallbackObjectData(void* privateData, JSClassRef jsClass)
         : privateData(privateData)
         , jsClass(jsClass)
@@ -53,11 +54,11 @@ struct JSCallbackObjectData {
         return m_privateProperties->getPrivateProperty(propertyName);
     }
     
-    void setPrivateProperty(const Identifier& propertyName, JSValue value)
+    void setPrivateProperty(JSGlobalData& globalData, JSCell* owner, const Identifier& propertyName, JSValue value)
     {
         if (!m_privateProperties)
-            m_privateProperties.set(new JSPrivatePropertyMap);
-        m_privateProperties->setPrivateProperty(propertyName, value);
+            m_privateProperties = adoptPtr(new JSPrivatePropertyMap);
+        m_privateProperties->setPrivateProperty(globalData, owner, propertyName, value);
     }
     
     void deletePrivateProperty(const Identifier& propertyName)
@@ -67,11 +68,11 @@ struct JSCallbackObjectData {
         m_privateProperties->deletePrivateProperty(propertyName);
     }
 
-    void markChildren(MarkStack& markStack)
+    void visitChildren(SlotVisitor& visitor)
     {
         if (!m_privateProperties)
             return;
-        m_privateProperties->markChildren(markStack);
+        m_privateProperties->visitChildren(visitor);
     }
 
     void* privateData;
@@ -79,56 +80,57 @@ struct JSCallbackObjectData {
     struct JSPrivatePropertyMap {
         JSValue getPrivateProperty(const Identifier& propertyName) const
         {
-            PrivatePropertyMap::const_iterator location = m_propertyMap.find(propertyName.ustring().rep());
+            PrivatePropertyMap::const_iterator location = m_propertyMap.find(propertyName.impl());
             if (location == m_propertyMap.end())
                 return JSValue();
-            return location->second;
+            return location->second.get();
         }
         
-        void setPrivateProperty(const Identifier& propertyName, JSValue value)
+        void setPrivateProperty(JSGlobalData& globalData, JSCell* owner, const Identifier& propertyName, JSValue value)
         {
-            m_propertyMap.set(propertyName.ustring().rep(), value);
+            WriteBarrier<Unknown> empty;
+            m_propertyMap.add(propertyName.impl(), empty).first->second.set(globalData, owner, value);
         }
         
         void deletePrivateProperty(const Identifier& propertyName)
         {
-            m_propertyMap.remove(propertyName.ustring().rep());
+            m_propertyMap.remove(propertyName.impl());
         }
 
-        void markChildren(MarkStack& markStack)
+        void visitChildren(SlotVisitor& visitor)
         {
             for (PrivatePropertyMap::iterator ptr = m_propertyMap.begin(); ptr != m_propertyMap.end(); ++ptr) {
                 if (ptr->second)
-                    markStack.append(ptr->second);
+                    visitor.append(&ptr->second);
             }
         }
 
     private:
-        typedef HashMap<RefPtr<UString::Rep>, JSValue, IdentifierRepHash> PrivatePropertyMap;
+        typedef HashMap<RefPtr<StringImpl>, WriteBarrier<Unknown>, IdentifierRepHash> PrivatePropertyMap;
         PrivatePropertyMap m_propertyMap;
     };
     OwnPtr<JSPrivatePropertyMap> m_privateProperties;
+    virtual void finalize(Handle<Unknown>, void*);
 };
 
     
 template <class Base>
 class JSCallbackObject : public Base {
 public:
-    JSCallbackObject(ExecState*, NonNullPassRefPtr<Structure>, JSClassRef, void* data);
-    JSCallbackObject(JSClassRef);
-    virtual ~JSCallbackObject();
+    JSCallbackObject(ExecState*, JSGlobalObject*, Structure*, JSClassRef, void* data);
+    JSCallbackObject(JSGlobalData&, JSClassRef, Structure*);
 
     void setPrivate(void* data);
     void* getPrivate();
 
-    static const ClassInfo info;
+    static const ClassInfo s_info;
 
     JSClassRef classRef() const { return m_callbackObjectData->jsClass; }
     bool inherits(JSClassRef) const;
 
-    static PassRefPtr<Structure> createStructure(JSValue proto) 
+    static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
     { 
-        return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount); 
+        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount, &s_info); 
     }
     
     JSValue getPrivateProperty(const Identifier& propertyName) const
@@ -136,9 +138,9 @@ public:
         return m_callbackObjectData->getPrivateProperty(propertyName);
     }
     
-    void setPrivateProperty(const Identifier& propertyName, JSValue value)
+    void setPrivateProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
     {
-        m_callbackObjectData->setPrivateProperty(propertyName, value);
+        m_callbackObjectData->setPrivateProperty(globalData, this, propertyName, value);
     }
     
     void deletePrivateProperty(const Identifier& propertyName)
@@ -147,13 +149,12 @@ public:
     }
 
 protected:
-    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | Base::StructureFlags;
+    static const unsigned StructureFlags = ProhibitsPropertyCaching | OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
 
 private:
     virtual UString className() const;
 
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-    virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&);
     virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     
     virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
@@ -170,22 +171,21 @@ private:
 
     virtual ConstructType getConstructData(ConstructData&);
     virtual CallType getCallData(CallData&);
-    virtual const ClassInfo* classInfo() const { return &info; }
 
-    virtual void markChildren(MarkStack& markStack)
+    virtual void visitChildren(SlotVisitor& visitor)
     {
-        Base::markChildren(markStack);
-        m_callbackObjectData->markChildren(markStack);
+        Base::visitChildren(visitor);
+        m_callbackObjectData->visitChildren(visitor);
     }
 
     void init(ExecState*);
  
     static JSCallbackObject* asCallbackObject(JSValue);
  
-    static JSValue JSC_HOST_CALL call(ExecState*, JSObject* functionObject, JSValue thisValue, const ArgList&);
-    static JSObject* construct(ExecState*, JSObject* constructor, const ArgList&);
+    static EncodedJSValue JSC_HOST_CALL call(ExecState*);
+    static EncodedJSValue JSC_HOST_CALL construct(ExecState*);
    
-    static JSValue staticValueGetter(ExecState*, JSValue, const Identifier&);
+    JSValue getStaticValue(ExecState*, const Identifier&);
     static JSValue staticFunctionGetter(ExecState*, JSValue, const Identifier&);
     static JSValue callbackGetter(ExecState*, JSValue, const Identifier&);
 
index 6c83eb4e7e83385e156d06bcd58f397c85a49a90..cc8f3a870afc77c95d58a2e9e63d87ebd7d65317 100644 (file)
 #include "APIShims.h"
 #include "APICast.h"
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSCallbackFunction.h"
 #include "JSClassRef.h"
+#include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSObjectRef.h"
@@ -43,25 +45,27 @@ namespace JSC {
 template <class Base>
 inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue value)
 {
-    ASSERT(asObject(value)->inherits(&info));
+    ASSERT(asObject(value)->inherits(&s_info));
     return static_cast<JSCallbackObject*>(asObject(value));
 }
 
 template <class Base>
-JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, void* data)
-    : Base(structure)
-    , m_callbackObjectData(new JSCallbackObjectData(data, jsClass))
+JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, JSClassRef jsClass, void* data)
+    : Base(globalObject, structure)
+    , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(data, jsClass)))
 {
+    ASSERT(Base::inherits(&s_info));
     init(exec);
 }
 
 // Global object constructor.
 // FIXME: Move this into a separate JSGlobalCallbackObject class derived from this one.
 template <class Base>
-JSCallbackObject<Base>::JSCallbackObject(JSClassRef jsClass)
-    : Base()
-    , m_callbackObjectData(new JSCallbackObjectData(0, jsClass))
+JSCallbackObject<Base>::JSCallbackObject(JSGlobalData& globalData, JSClassRef jsClass, Structure* structure)
+    : Base(globalData, structure)
+    , m_callbackObjectData(adoptPtr(new JSCallbackObjectData(0, jsClass)))
 {
+    ASSERT(Base::inherits(&s_info));
     ASSERT(Base::isGlobalObject());
     init(static_cast<JSGlobalObject*>(this)->globalExec());
 }
@@ -84,16 +88,16 @@ void JSCallbackObject<Base>::init(ExecState* exec)
         JSObjectInitializeCallback initialize = initRoutines[i];
         initialize(toRef(exec), toRef(this));
     }
-}
 
-template <class Base>
-JSCallbackObject<Base>::~JSCallbackObject()
-{
-    JSObjectRef thisRef = toRef(this);
-    
-    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
-        if (JSObjectFinalizeCallback finalize = jsClass->finalize)
-            finalize(thisRef);
+    bool needsFinalizer = false;
+    for (JSClassRef jsClassPtr = classRef(); jsClassPtr && !needsFinalizer; jsClassPtr = jsClassPtr->parentClass)
+        needsFinalizer = jsClassPtr->finalize;
+    if (needsFinalizer) {
+        HandleSlot slot = exec->globalData().allocateGlobalHandle();
+        HandleHeap::heapFor(slot)->makeWeak(slot, m_callbackObjectData.get(), classRef());
+        HandleHeap::heapFor(slot)->writeBarrier(slot, this);
+        *slot = this;
+    }
 }
 
 template <class Base>
@@ -133,7 +137,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
                 value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 slot.setValue(jsUndefined());
                 return true;
             }
@@ -144,14 +148,17 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
         }
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
-            if (staticValues->contains(propertyName.ustring().rep())) {
-                slot.setCustom(this, staticValueGetter);
-                return true;
+            if (staticValues->contains(propertyName.impl())) {
+                JSValue value = getStaticValue(exec, propertyName);
+                if (value) {
+                    slot.setValue(value);
+                    return true;
+                }
             }
         }
         
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
-            if (staticFunctions->contains(propertyName.ustring().rep())) {
+            if (staticFunctions->contains(propertyName.impl())) {
                 slot.setCustom(this, staticFunctionGetter);
                 return true;
             }
@@ -161,12 +168,6 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
     return Base::getOwnPropertySlot(exec, propertyName, slot);
 }
 
-template <class Base>
-bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
-{
-    return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
-}
-
 template <class Base>
 bool JSCallbackObject<Base>::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
@@ -205,13 +206,13 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName
                 result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
             }
             if (exception)
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
             if (result || exception)
                 return;
         }
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
-            if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
+            if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) {
                 if (entry->attributes & kJSPropertyAttributeReadOnly)
                     return;
                 if (JSObjectSetPropertyCallback setProperty = entry->setProperty) {
@@ -224,19 +225,18 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName
                         result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception);
                     }
                     if (exception)
-                        exec->setException(toJS(exec, exception));
+                        throwError(exec, toJS(exec, exception));
                     if (result || exception)
                         return;
-                } else
-                    throwError(exec, ReferenceError, "Attempt to set a property that is not settable.");
+                }
             }
         }
         
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
-            if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
+            if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (entry->attributes & kJSPropertyAttributeReadOnly)
                     return;
-                JSCallbackObject<Base>::putDirect(propertyName, value); // put as override property
+                JSCallbackObject<Base>::putDirect(exec->globalData(), propertyName, value); // put as override property
                 return;
             }
         }
@@ -263,13 +263,13 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p
                 result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
             if (exception)
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
             if (result || exception)
                 return true;
         }
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
-            if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep())) {
+            if (StaticValueEntry* entry = staticValues->get(propertyName.impl())) {
                 if (entry->attributes & kJSPropertyAttributeDontDelete)
                     return false;
                 return true;
@@ -277,7 +277,7 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p
         }
         
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
-            if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
+            if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (entry->attributes & kJSPropertyAttributeDontDelete)
                     return false;
                 return true;
@@ -307,17 +307,18 @@ ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructD
 }
 
 template <class Base>
-JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* constructor, const ArgList& args)
+EncodedJSValue JSCallbackObject<Base>::construct(ExecState* exec)
 {
+    JSObject* constructor = exec->callee();
     JSContextRef execRef = toRef(exec);
     JSObjectRef constructorRef = toRef(constructor);
     
     for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) {
-            int argumentCount = static_cast<int>(args.size());
+            int argumentCount = static_cast<int>(exec->argumentCount());
             Vector<JSValueRef, 16> arguments(argumentCount);
             for (int i = 0; i < argumentCount; i++)
-                arguments[i] = toRef(exec, args.at(i));
+                arguments[i] = toRef(exec, exec->argument(i));
             JSValueRef exception = 0;
             JSObject* result;
             {
@@ -325,13 +326,13 @@ JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* construct
                 result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception));
             }
             if (exception)
-                exec->setException(toJS(exec, exception));
-            return result;
+                throwError(exec, toJS(exec, exception));
+            return JSValue::encode(result);
         }
     }
     
     ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
-    return 0;
+    return JSValue::encode(JSValue());
 }
 
 template <class Base>
@@ -350,7 +351,7 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue
                 result = hasInstance(execRef, thisRef, valueRef, &exception);
             }
             if (exception)
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
             return result;
         }
     }
@@ -370,18 +371,18 @@ CallType JSCallbackObject<Base>::getCallData(CallData& callData)
 }
 
 template <class Base>
-JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSCallbackObject<Base>::call(ExecState* exec)
 {
     JSContextRef execRef = toRef(exec);
-    JSObjectRef functionRef = toRef(functionObject);
-    JSObjectRef thisObjRef = toRef(thisValue.toThisObject(exec));
+    JSObjectRef functionRef = toRef(exec->callee());
+    JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec));
     
-    for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(functionObject)->classRef(); jsClass; jsClass = jsClass->parentClass) {
+    for (JSClassRef jsClass = static_cast<JSCallbackObject<Base>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) {
-            int argumentCount = static_cast<int>(args.size());
+            int argumentCount = static_cast<int>(exec->argumentCount());
             Vector<JSValueRef, 16> arguments(argumentCount);
             for (int i = 0; i < argumentCount; i++)
-                arguments[i] = toRef(exec, args.at(i));
+                arguments[i] = toRef(exec, exec->argument(i));
             JSValueRef exception = 0;
             JSValue result;
             {
@@ -389,13 +390,13 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject,
                 result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception));
             }
             if (exception)
-                exec->setException(toJS(exec, exception));
-            return result;
+                throwError(exec, toJS(exec, exception));
+            return JSValue::encode(result);
         }
     }
     
     ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
-    return JSValue();
+    return JSValue::encode(JSValue());
 }
 
 template <class Base>
@@ -414,7 +415,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr
             typedef OpaqueJSClassStaticValuesTable::const_iterator iterator;
             iterator end = staticValues->end();
             for (iterator it = staticValues->begin(); it != end; ++it) {
-                UString::Rep* name = it->first.get();
+                StringImpl* name = it->first.get();
                 StaticValueEntry* entry = it->second;
                 if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
                     propertyNames.add(Identifier(exec, name));
@@ -425,7 +426,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr
             typedef OpaqueJSClassStaticFunctionsTable::const_iterator iterator;
             iterator end = staticFunctions->end();
             for (iterator it = staticFunctions->begin(); it != end; ++it) {
-                UString::Rep* name = it->first.get();
+                StringImpl* name = it->first.get();
                 StaticFunctionEntry* entry = it->second;
                 if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
                     propertyNames.add(Identifier(exec, name));
@@ -456,7 +457,7 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const
                 value = convertToType(ctx, thisRef, kJSTypeNumber, &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 return 0;
             }
 
@@ -483,7 +484,7 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const
                 value = convertToType(ctx, thisRef, kJSTypeString, &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 return "";
             }
             if (value)
@@ -516,16 +517,14 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const
 }
 
 template <class Base>
-JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
+JSValue JSCallbackObject<Base>::getStaticValue(ExecState* exec, const Identifier& propertyName)
 {
-    JSCallbackObject* thisObj = asCallbackObject(slotBase);
-    
-    JSObjectRef thisRef = toRef(thisObj);
+    JSObjectRef thisRef = toRef(this);
     RefPtr<OpaqueJSString> propertyNameRef;
     
-    for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass)
+    for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass)
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec))
-            if (StaticValueEntry* entry = staticValues->get(propertyName.ustring().rep()))
+            if (StaticValueEntry* entry = staticValues->get(propertyName.impl()))
                 if (JSObjectGetPropertyCallback getProperty = entry->getProperty) {
                     if (!propertyNameRef)
                         propertyNameRef = OpaqueJSString::create(propertyName.ustring());
@@ -536,14 +535,14 @@ JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSValue slotB
                         value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
                     }
                     if (exception) {
-                        exec->setException(toJS(exec, exception));
+                        throwError(exec, toJS(exec, exception));
                         return jsUndefined();
                     }
                     if (value)
                         return toJS(exec, value);
                 }
 
-    return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
+    return JSValue();
 }
 
 template <class Base>
@@ -558,17 +557,18 @@ JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSValue sl
     
     for (JSClassRef jsClass = thisObj->classRef(); jsClass; jsClass = jsClass->parentClass) {
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
-            if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.ustring().rep())) {
+            if (StaticFunctionEntry* entry = staticFunctions->get(propertyName.impl())) {
                 if (JSObjectCallAsFunctionCallback callAsFunction = entry->callAsFunction) {
-                    JSObject* o = new (exec) JSCallbackFunction(exec, callAsFunction, propertyName);
-                    thisObj->putDirect(propertyName, o, entry->attributes);
+                    
+                    JSObject* o = new (exec) JSCallbackFunction(exec, asGlobalObject(thisObj->getAnonymousValue(0)), callAsFunction, propertyName);
+                    thisObj->putDirect(exec->globalData(), propertyName, o, entry->attributes);
                     return o;
                 }
             }
         }
     }
     
-    return throwError(exec, ReferenceError, "Static function property defined with NULL callAsFunction callback.");
+    return throwError(exec, createReferenceError(exec, "Static function property defined with NULL callAsFunction callback."));
 }
 
 template <class Base>
@@ -590,14 +590,14 @@ JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSValue slotBase
                 value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 return jsUndefined();
             }
             if (value)
                 return toJS(exec, value);
         }
             
-    return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist.");
+    return throwError(exec, createReferenceError(exec, "hasProperty callback returned true for a property that doesn't exist."));
 }
 
 } // namespace JSC
index 3e65b753feff3a8a31ba5e65553db028773f8e74..08dc7211b2f301536e71a36081e109bbc04d6c30 100644 (file)
@@ -45,13 +45,13 @@ const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 static inline UString tryCreateStringFromUTF8(const char* string)
 {
     if (!string)
-        return UString::null();
+        return UString();
 
     size_t length = strlen(string);
     Vector<UChar, 1024> buffer(length);
     UChar* p = buffer.data();
     if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length))
-        return UString::null();
+        return UString();
 
     return UString(buffer.data(), p - buffer.data());
 }
@@ -83,9 +83,10 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
             if (!valueName.isNull()) {
                 // Use a local variable here to sidestep an RVCT compiler bug.
                 StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes);
-                UStringImpl* impl = valueName.rep();
-                impl->ref();
-                m_staticValues->add(impl, entry);
+                StringImpl* impl = valueName.impl();
+                StaticValueEntry* existingEntry = m_staticValues->get(impl);
+                m_staticValues->set(impl, entry);
+                delete existingEntry;
             }
             ++staticValue;
         }
@@ -98,9 +99,10 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
             if (!functionName.isNull()) {
                 // Use a local variable here to sidestep an RVCT compiler bug.
                 StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes);
-                UStringImpl* impl = functionName.rep();
-                impl->ref();
-                m_staticFunctions->add(impl, entry);
+                StringImpl* impl = functionName.impl();
+                StaticFunctionEntry* existingEntry = m_staticFunctions->get(impl);
+                m_staticFunctions->set(impl, entry);
+                delete existingEntry;
             }
             ++staticFunction;
         }
@@ -113,7 +115,7 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass*
 OpaqueJSClass::~OpaqueJSClass()
 {
     // The empty string is shared across threads & is an identifier, in all other cases we should have done a deep copy in className(), below. 
-    ASSERT(!m_className.size() || !m_className.rep()->isIdentifier());
+    ASSERT(!m_className.length() || !m_className.impl()->isIdentifier());
 
     if (m_staticValues) {
         OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end();
@@ -142,19 +144,12 @@ PassRefPtr<OpaqueJSClass> OpaqueJSClass::createNoAutomaticPrototype(const JSClas
     return adoptRef(new OpaqueJSClass(definition, 0));
 }
 
-static void clearReferenceToPrototype(JSObjectRef prototype)
-{
-    OpaqueJSClassContextData* jsClassData = static_cast<OpaqueJSClassContextData*>(JSObjectGetPrivate(prototype));
-    ASSERT(jsClassData);
-    jsClassData->cachedPrototype.clear(toJS(prototype));
-}
-
 PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition)
 {
     JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy.
 
     JSClassDefinition protoDefinition = kJSClassDefinitionEmpty;
-    protoDefinition.finalize = clearReferenceToPrototype;
+    protoDefinition.finalize = 0;
     swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype.
     
     // We are supposed to use JSClassRetain/Release but since we know that we currently have
@@ -163,7 +158,7 @@ PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientD
     return adoptRef(new OpaqueJSClass(&definition, protoClass.get()));
 }
 
-OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
+OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSClass* jsClass)
     : m_class(jsClass)
 {
     if (jsClass->m_staticValues) {
@@ -173,7 +168,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
             ASSERT(!it->first->isIdentifier());
             // Use a local variable here to sidestep an RVCT compiler bug.
             StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes);
-            staticValues->add(UString::Rep::create(it->first->characters(), it->first->length()), entry);
+            staticValues->add(StringImpl::create(it->first->characters(), it->first->length()), entry);
         }
     } else
         staticValues = 0;
@@ -185,7 +180,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
             ASSERT(!it->first->isIdentifier());
             // Use a local variable here to sidestep an RVCT compiler bug.
             StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes);
-            staticFunctions->add(UString::Rep::create(it->first->characters(), it->first->length()), entry);
+            staticFunctions->add(StringImpl::create(it->first->characters(), it->first->length()), entry);
         }
             
     } else
@@ -209,14 +204,14 @@ OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
 {
     OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
     if (!contextData)
-        contextData = new OpaqueJSClassContextData(this);
+        contextData = new OpaqueJSClassContextData(exec->globalData(), this);
     return *contextData;
 }
 
 UString OpaqueJSClass::className()
 {
     // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable.
-    return UString(m_className.data(), m_className.size());
+    return UString(m_className.characters(), m_className.length());
 }
 
 OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec)
@@ -256,10 +251,10 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec)
 
     if (!jsClassData.cachedPrototype) {
         // Recursive, but should be good enough for our purposes
-        jsClassData.cachedPrototype = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction
+        jsClassData.cachedPrototype.set(exec->globalData(), new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction
         if (parentClass) {
             if (JSObject* prototype = parentClass->prototype(exec))
-                jsClassData.cachedPrototype->setPrototype(prototype);
+                jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype);
         }
     }
     return jsClassData.cachedPrototype.get();
index ae60aadef91baa47b8e345f7ed4fb8263834457b..d346cc5dfcb036508e3915f790f11b71a1e378c8 100644 (file)
 
 #include "JSObjectRef.h"
 
-#include <runtime/JSObject.h>
-#include <runtime/Protect.h>
-#include <runtime/UString.h>
-#include <runtime/WeakGCPtr.h>
+#include "Weak.h"
+#include "JSObject.h"
+#include "Protect.h"
+#include "UString.h"
 #include <wtf/HashMap.h>
-#include <wtf/RefCounted.h>
 
-struct StaticValueEntry : FastAllocBase {
+struct StaticValueEntry {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes)
         : getProperty(_getProperty), setProperty(_setProperty), attributes(_attributes)
     {
@@ -46,7 +47,9 @@ struct StaticValueEntry : FastAllocBase {
     JSPropertyAttributes attributes;
 };
 
-struct StaticFunctionEntry : FastAllocBase {
+struct StaticFunctionEntry {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes)
         : callAsFunction(_callAsFunction), attributes(_attributes)
     {
@@ -56,15 +59,17 @@ struct StaticFunctionEntry : FastAllocBase {
     JSPropertyAttributes attributes;
 };
 
-typedef HashMap<RefPtr<JSC::UString::Rep>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
-typedef HashMap<RefPtr<JSC::UString::Rep>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
+typedef HashMap<RefPtr<StringImpl>, StaticValueEntry*> OpaqueJSClassStaticValuesTable;
+typedef HashMap<RefPtr<StringImpl>, StaticFunctionEntry*> OpaqueJSClassStaticFunctionsTable;
 
 struct OpaqueJSClass;
 
 // An OpaqueJSClass (JSClass) is created without a context, so it can be used with any context, even across context groups.
 // This structure holds data members that vary across context groups.
-struct OpaqueJSClassContextData : Noncopyable {
-    OpaqueJSClassContextData(OpaqueJSClass*);
+struct OpaqueJSClassContextData {
+    WTF_MAKE_NONCOPYABLE(OpaqueJSClassContextData); WTF_MAKE_FAST_ALLOCATED;
+public:
+    OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSClass*);
     ~OpaqueJSClassContextData();
 
     // It is necessary to keep OpaqueJSClass alive because of the following rare scenario:
@@ -77,10 +82,10 @@ struct OpaqueJSClassContextData : Noncopyable {
 
     OpaqueJSClassStaticValuesTable* staticValues;
     OpaqueJSClassStaticFunctionsTable* staticFunctions;
-    JSC::WeakGCPtr<JSC::JSObject> cachedPrototype;
+    JSC::Weak<JSC::JSObject> cachedPrototype;
 };
 
-struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> {
+struct OpaqueJSClass : public ThreadSafeRefCounted<OpaqueJSClass> {
     static PassRefPtr<OpaqueJSClass> create(const JSClassDefinition*);
     static PassRefPtr<OpaqueJSClass> createNoAutomaticPrototype(const JSClassDefinition*);
     ~OpaqueJSClass();
index b97ceda6799a66e823379a414421239a3c4bac2c..9c15b22f1deb481cca7f7ea83d1983599abb7cf1 100644 (file)
 
 #include "APICast.h"
 #include "InitializeThreading.h"
+#include <interpreter/CallFrame.h>
+#include <interpreter/Interpreter.h>
 #include "JSCallbackObject.h"
 #include "JSClassRef.h"
 #include "JSGlobalObject.h"
 #include "JSObject.h"
+#include "UStringBuilder.h"
 #include <wtf/text/StringHash.h>
 
+
 #if OS(DARWIN)
 #include <mach-o/dyld.h>
 
@@ -46,7 +50,7 @@ using namespace JSC;
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
-    return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).releaseRef());
+    return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).leakRef());
 }
 
 JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
@@ -66,7 +70,7 @@ JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
 #if OS(DARWIN)
     // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
     // to use a unique JSGlobalData, we use a shared one for compatibility.
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#ifndef BUILDING_ON_LEOPARD
     if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
 #else
     {
@@ -93,16 +97,16 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
 #endif
 
     if (!globalObjectClass) {
-        JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject;
+        JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject(*globalData, JSGlobalObject::createStructure(*globalData, jsNull()));
         return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
     }
 
-    JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass);
+    JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(*globalData, globalObjectClass, JSCallbackObject<JSGlobalObject>::createStructure(*globalData, jsNull()));
     ExecState* exec = globalObject->globalExec();
     JSValue prototype = globalObjectClass->prototype(exec);
     if (!prototype)
         prototype = jsNull();
-    globalObject->resetPrototype(prototype);
+    globalObject->resetPrototype(*globalData, prototype);
     return JSGlobalContextRetain(toGlobalRef(exec));
 }
 
@@ -138,13 +142,17 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx)
     // * If this is the last reference to any contexts in the given context group,
     //   call destroy on the heap (the global data is being  freed).
     // * If this was the last reference to the global object, then unprotecting
-    //   it may  release a lot of GC memory - run the garbage collector now.
+    //   it may release a lot of GC memory - tickle the activity callback to
+    //   garbage collect soon.
     // * If there are more references remaining the the global object, then do nothing
     //   (specifically that is more protects, which we assume come from other JSGlobalContextRefs).
-    if (releasingContextGroup)
+    if (releasingContextGroup) {
+        globalData.clearBuiltinStructures();
         globalData.heap.destroy();
-    else if (releasingGlobalObject)
-        globalData.heap.collectAllGarbage();
+    } else if (releasingGlobalObject) {
+        globalData.heap.activityCallback()->synchronize();
+        (*globalData.heap.activityCallback())();
+    }
 
     globalData.deref();
 
@@ -173,3 +181,60 @@ JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
 
     return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
 }
+    
+JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
+{
+    ExecState* exec = toJS(ctx);
+    JSLock lock(exec);
+
+    unsigned count = 0;
+    UStringBuilder builder;
+    CallFrame* callFrame = exec;
+    UString functionName;
+    if (exec->callee()) {
+        if (asObject(exec->callee())->inherits(&InternalFunction::s_info)) {
+            functionName = asInternalFunction(exec->callee())->name(exec);
+            builder.append("#0 ");
+            builder.append(functionName);
+            builder.append("() ");
+            count++;
+        }
+    }
+    while (true) {
+        ASSERT(callFrame);
+        int signedLineNumber;
+        intptr_t sourceID;
+        UString urlString;
+        JSValue function;
+        
+        UString levelStr = UString::number(count);
+        
+        exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function);
+
+        if (function)
+            functionName = asFunction(function)->name(exec);
+        else {
+            // Caller is unknown, but if frame is empty we should still add the frame, because
+            // something called us, and gave us arguments.
+            if (count)
+                break;
+        }
+        unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0;
+        if (!builder.isEmpty())
+            builder.append("\n");
+        builder.append("#");
+        builder.append(levelStr);
+        builder.append(" ");
+        builder.append(functionName);
+        builder.append("() at ");
+        builder.append(urlString);
+        builder.append(":");
+        builder.append(UString::number(lineNumber));
+        if (!function || ++count == maxStackSize)
+            break;
+        callFrame = callFrame->callerFrame();
+    }
+    return OpaqueJSString::create(builder.toUString()).leakRef();
+}
+
+
index ff014ec64eca5d9e46b6a439bbe3157a6c956810..4f77aeadadde4a7e75a72a95a8f8124a95e5459d 100644 (file)
@@ -46,6 +46,15 @@ extern "C" {
 */
 JS_EXPORT JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx);
 
+    
+/*!
+@function
+@abstract Gets a Backtrace for the existing context
+@param ctx The JSContext whose backtrace you want to get
+@result A string containing the backtrace
+*/
+JS_EXPORT JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) AVAILABLE_IN_WEBKIT_VERSION_4_0;
+    
 #ifdef __cplusplus
 }
 #endif
index 8fdbdab9059300a8af7fa22f428dd3bc0eb987d5..2df010a5189f7c6ed2c9aef9c18e31f37089543b 100644 (file)
@@ -59,7 +59,7 @@ JSClassRef JSClassCreate(const JSClassDefinition* definition)
         ? OpaqueJSClass::createNoAutomaticPrototype(definition)
         : OpaqueJSClass::create(definition);
     
-    return jsClass.release().releaseRef();
+    return jsClass.release().leakRef();
 }
 
 JSClassRef JSClassRetain(JSClassRef jsClass)
@@ -79,11 +79,11 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
     APIEntryShim entryShim(exec);
 
     if (!jsClass)
-        return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
+        return toRef(constructEmptyObject(exec));
 
-    JSCallbackObject<JSObject>* object = new (exec) JSCallbackObject<JSObject>(exec, exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
+    JSCallbackObject<JSObjectWithGlobalObject>* object = new (exec) JSCallbackObject<JSObjectWithGlobalObject>(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
     if (JSObject* prototype = jsClass->prototype(exec))
-        object->setPrototype(prototype);
+        object->setPrototype(exec->globalData(), prototype);
 
     return toRef(object);
 }
@@ -95,7 +95,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name,
 
     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
     
-    return toRef(new (exec) JSCallbackFunction(exec, callAsFunction, nameID));
+    return toRef(new (exec) JSCallbackFunction(exec, exec->lexicalGlobalObject(), callAsFunction, nameID));
 }
 
 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
@@ -107,8 +107,8 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje
     if (!jsPrototype)
         jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
 
-    JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
-    constructor->putDirect(exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
+    JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
+    constructor->putDirect(exec->globalData(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
     return toRef(constructor);
 }
 
@@ -124,7 +124,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa
         args.append(jsString(exec, parameterNames[i]->ustring()));
     args.append(jsString(exec, body->ustring()));
 
-    JSObject* result = constructFunction(exec, args, nameID, sourceURL->ustring(), startingLineNumber);
+    JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->ustring(), startingLineNumber);
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -168,7 +168,7 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal
     for (size_t i = 0; i < argumentCount; ++i)
         argList.append(toJS(exec, arguments[i]));
 
-    JSObject* result = constructDate(exec, argList);
+    JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -184,11 +184,10 @@ JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSVa
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
 
-    MarkedArgumentBuffer argList;
-    for (size_t i = 0; i < argumentCount; ++i)
-        argList.append(toJS(exec, arguments[i]));
+    JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined();
+    Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
+    JSObject* result = ErrorInstance::create(exec, errorStructure, message);
 
-    JSObject* result = constructError(exec, argList);
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -208,7 +207,7 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV
     for (size_t i = 0; i < argumentCount; ++i)
         argList.append(toJS(exec, arguments[i]));
 
-    JSObject* result = constructRegExp(exec, argList);
+    JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(),  argList);
     if (exec->hadException()) {
         if (exception)
             *exception = toRef(exec, exec->exception());
@@ -236,7 +235,7 @@ void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value
     JSObject* jsObject = toJS(object);
     JSValue jsValue = toJS(exec, value);
 
-    jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull());
+    jsObject->setPrototypeWithCycleCheck(exec->globalData(), jsValue.isObject() ? jsValue : jsNull());
 }
 
 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
@@ -341,10 +340,10 @@ void* JSObjectGetPrivate(JSObjectRef object)
 {
     JSObject* jsObject = toJS(object);
     
-    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info))
+    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
         return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
-    else if (jsObject->inherits(&JSCallbackObject<JSObject>::info))
-        return static_cast<JSCallbackObject<JSObject>*>(jsObject)->getPrivate();
+    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info))
+        return static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->getPrivate();
     
     return 0;
 }
@@ -353,11 +352,12 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data)
 {
     JSObject* jsObject = toJS(object);
     
-    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) {
+    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
         static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
         return true;
-    } else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) {
-        static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivate(data);
+    }
+    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info)) {
+        static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->setPrivate(data);
         return true;
     }
         
@@ -371,10 +371,10 @@ JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSSt
     JSObject* jsObject = toJS(object);
     JSValue result;
     Identifier name(propertyName->identifier(&exec->globalData()));
-    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info))
+    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
         result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
-    else if (jsObject->inherits(&JSCallbackObject<JSObject>::info))
-        result = static_cast<JSCallbackObject<JSObject>*>(jsObject)->getPrivateProperty(name);
+    else if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info))
+        result = static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->getPrivateProperty(name);
     return toRef(exec, result);
 }
 
@@ -383,14 +383,14 @@ bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRe
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
     JSObject* jsObject = toJS(object);
-    JSValue jsValue = toJS(exec, value);
+    JSValue jsValue = value ? toJS(exec, value) : JSValue();
     Identifier name(propertyName->identifier(&exec->globalData()));
-    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) {
-        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(name, jsValue);
+    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
+        static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
         return true;
     }
-    if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) {
-        static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivateProperty(name, jsValue);
+    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info)) {
+        static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
         return true;
     }
     return false;
@@ -402,12 +402,12 @@ bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStrin
     APIEntryShim entryShim(exec);
     JSObject* jsObject = toJS(object);
     Identifier name(propertyName->identifier(&exec->globalData()));
-    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) {
+    if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
         static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
-    if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) {
-        static_cast<JSCallbackObject<JSObject>*>(jsObject)->deletePrivateProperty(name);
+    if (jsObject->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info)) {
+        static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
     return false;
@@ -481,7 +481,9 @@ JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size
     return result;
 }
 
-struct OpaqueJSPropertyNameArray : FastAllocBase {
+struct OpaqueJSPropertyNameArray {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     OpaqueJSPropertyNameArray(JSGlobalData* globalData)
         : refCount(0)
         , globalData(globalData)
@@ -508,7 +510,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o
     size_t size = array.size();
     propertyNames->array.reserveInitialCapacity(size);
     for (size_t i = 0; i < size; ++i)
-        propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).releaseRef()));
+        propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).leakRef()));
     
     return JSPropertyNameArrayRetain(propertyNames);
 }
index 69c6de19c92d172c86d9bbc7641ccb5baeb4dce1..08ef57c31f7f61c4f023ab64f7321555609ab744 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef JSRetainPtr_h
 #define JSRetainPtr_h
 
+#include <JavaScriptCore/JSContextRef.h>
 #include <JavaScriptCore/JSStringRef.h>
 #include <algorithm>
 
 inline void JSRetain(JSStringRef string) { JSStringRetain(string); }
 inline void JSRelease(JSStringRef string) { JSStringRelease(string); }
+inline void JSRetain(JSGlobalContextRef context) { JSGlobalContextRetain(context); }
+inline void JSRelease(JSGlobalContextRef context) { JSGlobalContextRelease(context); }
 
 enum AdoptTag { Adopt };
 
-template <typename T> class JSRetainPtr {
+template<typename T> class JSRetainPtr {
 public:
-    JSRetainPtr() : m_ptr(0) {}
+    JSRetainPtr() : m_ptr(0) { }
     JSRetainPtr(T ptr) : m_ptr(ptr) { if (ptr) JSRetain(ptr); }
-
     JSRetainPtr(AdoptTag, T ptr) : m_ptr(ptr) { }
-    
-    JSRetainPtr(const JSRetainPtr& o) : m_ptr(o.m_ptr) { if (T ptr = m_ptr) JSRetain(ptr); }
-
-    ~JSRetainPtr() { if (T ptr = m_ptr) JSRelease(ptr); }
-    
-    template <typename U> JSRetainPtr(const JSRetainPtr<U>& o) : m_ptr(o.get()) { if (T ptr = m_ptr) JSRetain(ptr); }
+    JSRetainPtr(const JSRetainPtr&);
+    template<typename U> JSRetainPtr(const JSRetainPtr<U>&);
+    ~JSRetainPtr();
     
     T get() const { return m_ptr; }
     
-    T releaseRef() { T tmp = m_ptr; m_ptr = 0; return tmp; }
-    
+    void clear();
+    T leakRef();
+
     T operator->() const { return m_ptr; }
     
     bool operator!() const { return !m_ptr; }
@@ -63,19 +63,57 @@ public:
     operator UnspecifiedBoolType() const { return m_ptr ? &JSRetainPtr::m_ptr : 0; }
     
     JSRetainPtr& operator=(const JSRetainPtr&);
-    template <typename U> JSRetainPtr& operator=(const JSRetainPtr<U>&);
+    template<typename U> JSRetainPtr& operator=(const JSRetainPtr<U>&);
     JSRetainPtr& operator=(T);
-    template <typename U> JSRetainPtr& operator=(U*);
+    template<typename U> JSRetainPtr& operator=(U*);
 
     void adopt(T);
     
     void swap(JSRetainPtr&);
 
+    // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
+    T releaseRef() { return leakRef(); }
+
 private:
     T m_ptr;
 };
 
-template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<T>& o)
+template<typename T> inline JSRetainPtr<T>::JSRetainPtr(const JSRetainPtr& o)
+    : m_ptr(o.m_ptr)
+{
+    if (m_ptr)
+        JSRetain(m_ptr);
+}
+
+template<typename T> template<typename U> inline JSRetainPtr<T>::JSRetainPtr(const JSRetainPtr<U>& o)
+    : m_ptr(o.get())
+{
+    if (m_ptr)
+        JSRetain(m_ptr);
+}
+
+template<typename T> inline JSRetainPtr<T>::~JSRetainPtr()
+{
+    if (m_ptr)
+        JSRelease(m_ptr);
+}
+
+template<typename T> inline void JSRetainPtr<T>::clear()
+{
+    if (T ptr = m_ptr) {
+        m_ptr = 0;
+        JSRelease(ptr);
+    }
+}
+
+template<typename T> inline T JSRetainPtr<T>::leakRef()
+{
+    T ptr = m_ptr;
+    m_ptr = 0;
+    return ptr;
+}
+
+template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<T>& o)
 {
     T optr = o.get();
     if (optr)
@@ -87,7 +125,7 @@ template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSR
     return *this;
 }
 
-template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<U>& o)
+template<typename T> template<typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSRetainPtr<U>& o)
 {
     T optr = o.get();
     if (optr)
@@ -99,7 +137,7 @@ template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T
     return *this;
 }
 
-template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr)
+template<typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr)
 {
     if (optr)
         JSRetain(optr);
@@ -110,7 +148,7 @@ template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr)
     return *this;
 }
 
-template <typename T> inline void JSRetainPtr<T>::adopt(T optr)
+template<typename T> inline void JSRetainPtr<T>::adopt(T optr)
 {
     T ptr = m_ptr;
     m_ptr = optr;
@@ -118,7 +156,7 @@ template <typename T> inline void JSRetainPtr<T>::adopt(T optr)
         JSRelease(ptr);
 }
 
-template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(U* optr)
+template<typename T> template<typename U> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(U* optr)
 {
     if (optr)
         JSRetain(optr);
@@ -129,42 +167,42 @@ template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T
     return *this;
 }
 
-template <class T> inline void JSRetainPtr<T>::swap(JSRetainPtr<T>& o)
+template<typename T> inline void JSRetainPtr<T>::swap(JSRetainPtr<T>& o)
 {
     std::swap(m_ptr, o.m_ptr);
 }
 
-template <class T> inline void swap(JSRetainPtr<T>& a, JSRetainPtr<T>& b)
+template<typename T> inline void swap(JSRetainPtr<T>& a, JSRetainPtr<T>& b)
 {
     a.swap(b);
 }
 
-template <typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b)
+template<typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b)
 { 
     return a.get() == b.get(); 
 }
 
-template <typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, U* b)
+template<typename T, typename U> inline bool operator==(const JSRetainPtr<T>& a, U* b)
 { 
     return a.get() == b; 
 }
 
-template <typename T, typename U> inline bool operator==(T* a, const JSRetainPtr<U>& b) 
+template<typename T, typename U> inline bool operator==(T* a, const JSRetainPtr<U>& b) 
 {
     return a == b.get(); 
 }
 
-template <typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b)
+template<typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, const JSRetainPtr<U>& b)
 { 
     return a.get() != b.get(); 
 }
 
-template <typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, U* b)
+template<typename T, typename U> inline bool operator!=(const JSRetainPtr<T>& a, U* b)
 {
     return a.get() != b; 
 }
 
-template <typename T, typename U> inline bool operator!=(T* a, const JSRetainPtr<U>& b)
+template<typename T, typename U> inline bool operator!=(T* a, const JSRetainPtr<U>& b)
 { 
     return a != b.get(); 
 }
index 8e236e45826e2e182ac959529645f303c7650061..ea31da66bb940d7edf5639fb21c22ad4bd55c0bd 100644 (file)
@@ -36,7 +36,7 @@ using namespace WTF::Unicode;
 JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars)
 {
     initializeThreading();
-    return OpaqueJSString::create(chars, numChars).releaseRef();
+    return OpaqueJSString::create(chars, numChars).leakRef();
 }
 
 JSStringRef JSStringCreateWithUTF8CString(const char* string)
@@ -47,11 +47,11 @@ JSStringRef JSStringCreateWithUTF8CString(const char* string)
         Vector<UChar, 1024> buffer(length);
         UChar* p = buffer.data();
         if (conversionOK == convertUTF8ToUTF16(&string, string + length, &p, p + length))
-            return OpaqueJSString::create(buffer.data(), p - buffer.data()).releaseRef();
+            return OpaqueJSString::create(buffer.data(), p - buffer.data()).leakRef();
     }
 
     // Null string.
-    return OpaqueJSString::create().releaseRef();
+    return OpaqueJSString::create().leakRef();
 }
 
 JSStringRef JSStringRetain(JSStringRef string)
index 51871b121dbc5107ade79a319eed1660e704186a..c5c154402cb558154d5b2a82289405a428d94a3b 100644 (file)
@@ -38,7 +38,7 @@ extern "C" {
 #endif
 
 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) \
-    && !((defined(__CC_ARM) || defined(__ARMCC__)) && defined(__SYMBIAN32__)) /* RVCT */
+    && !((defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__linux__)) /* RVCT */
 /*!
 @typedef JSChar
 @abstract A Unicode character.
index a7d3e9923db5b72babd1db12ae2dead78f333403..70f42540bf75bdda6f12b048df4286f347bc35e5 100644 (file)
@@ -24,7 +24,7 @@
  * 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.
- */
+ */ 
 
 #include "config.h"
 #include "JSStringRefBSTR.h"
index d1f6fe33032a11a25284da3351cbdb292dfbd169..0877a13e60b2786680b6d9cd8537c591e0b2ef58 100644 (file)
@@ -42,12 +42,12 @@ JSStringRef JSStringCreateWithCFString(CFStringRef string)
     // it can hold.  (<rdar://problem/6806478>)
     size_t length = CFStringGetLength(string);
     if (length) {
-        OwnArrayPtr<UniChar> buffer(new UniChar[length]);
+        OwnArrayPtr<UniChar> buffer = adoptArrayPtr(new UniChar[length]);
         CFStringGetCharacters(string, CFRangeMake(0, length), buffer.get());
         COMPILE_ASSERT(sizeof(UniChar) == sizeof(UChar), unichar_and_uchar_must_be_same_size);
-        return OpaqueJSString::create(reinterpret_cast<UChar*>(buffer.get()), length).releaseRef();
+        return OpaqueJSString::create(reinterpret_cast<UChar*>(buffer.get()), length).leakRef();
     } else {
-        return OpaqueJSString::create(0, 0).releaseRef();
+        return OpaqueJSString::create(0, 0).leakRef();
     }
 }
 
index 905dcbf34e4d5b0745977f7eeb36fe164bd339cb..d1603e2210404cf3f6e0050d99c4510e9ecad2d4 100644 (file)
@@ -129,10 +129,10 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla
     JSValue jsValue = toJS(exec, value);
     
     if (JSObject* o = jsValue.getObject()) {
-        if (o->inherits(&JSCallbackObject<JSGlobalObject>::info))
+        if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
             return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
-        else if (o->inherits(&JSCallbackObject<JSObject>::info))
-            return static_cast<JSCallbackObject<JSObject>*>(o)->inherits(jsClass);
+        if (o->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info))
+            return static_cast<JSCallbackObject<JSObjectWithGlobalObject>*>(o)->inherits(jsClass);
     }
     return false;
 }
@@ -219,7 +219,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
     if (isnan(value))
         value = NaN;
 
-    return toRef(exec, jsNumber(exec, value));
+    return toRef(exec, jsNumber(value));
 }
 
 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
@@ -234,7 +234,8 @@ JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)
 {
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
-    LiteralParser parser(exec, string->ustring(), LiteralParser::StrictJSON);
+    UString str = string->ustring();
+    LiteralParser parser(exec, str.characters(), str.length(), LiteralParser::StrictJSON);
     return toRef(exec, parser.tryLiteralParse());
 }
 
@@ -252,7 +253,7 @@ JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsig
         exec->clearException();
         return 0;
     }
-    return OpaqueJSString::create(result).releaseRef();
+    return OpaqueJSString::create(result).leakRef();
 }
 
 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
@@ -295,7 +296,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef*
         exec->clearException();
         stringRef.clear();
     }
-    return stringRef.release().releaseRef();
+    return stringRef.release().leakRef();
 }
 
 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
index 64e1f4d53b7e8b18395246ee82bb8409bc07200e..f7b91da51d326db2a45f677ebfef6f7f0ec5b770 100644 (file)
@@ -37,7 +37,7 @@ class JSObject;
 
 typedef void (*JSWeakMapDestroyedCallback)(struct OpaqueJSWeakObjectMap*, void*);
 
-typedef JSC::WeakGCMap<void*, JSC::JSObject*> WeakMapType;
+typedef JSC::WeakGCMap<void*, JSC::JSObject> WeakMapType;
 
 struct OpaqueJSWeakObjectMap : public RefCounted<OpaqueJSWeakObjectMap> {
 public:
index 7e6bb632889eefd6964c93b1db521e99bf68848c..13900cf8327b4f026e203f4a12cb58464c203a14 100644 (file)
@@ -32,7 +32,6 @@
 #include "JSValue.h"
 #include "JSWeakObjectMapRefInternal.h"
 #include <wtf/HashMap.h>
-#include <wtf/RefCounted.h>
 #include <wtf/text/StringHash.h>
 
 using namespace WTF;
@@ -58,8 +57,8 @@ void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSO
     JSObject* obj = toJS(object);
     if (!obj)
         return;
-    ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::info) || obj->inherits(&JSCallbackObject<JSObject>::info));
-    map->map().set(key, obj);
+    ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::s_info) || obj->inherits(&JSCallbackObject<JSObjectWithGlobalObject>::s_info));
+    map->map().set(exec->globalData(), key, obj);
 }
 
 JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key)
@@ -69,14 +68,18 @@ JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* k
     return toRef(static_cast<JSObject*>(map->map().get(key)));
 }
 
-bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object)
+void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key)
 {
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
-    JSObject* obj = toJS(object);
-    if (map->map().uncheckedRemove(key, obj))
-        return true;
-    return false;
+    map->map().take(key);
+}
+
+// We need to keep this function in the build to keep the nightlies running.
+JS_EXPORT bool JSWeakObjectMapClear(JSContextRef, JSWeakObjectMapRef, void*, JSObjectRef);
+bool JSWeakObjectMapClear(JSContextRef, JSWeakObjectMapRef, void*, JSObjectRef)
+{
+    return true;
 }
 
 #ifdef __cplusplus
index d36111c5c496b0a86f0488d254a0c32c5f9cf652..5a07cf7c41182378c13e9028fb2461ee67a2c9e1 100644 (file)
@@ -52,8 +52,7 @@ typedef void (*JSWeakMapDestroyedCallback)(JSWeakObjectMapRef map, void* data);
  @param destructor A function to call when the weak map is destroyed.
  @result A JSWeakObjectMapRef bound to the given context, data and destructor.
  @discussion The JSWeakObjectMapRef can be used as a storage mechanism to hold custom JS objects without forcing those objects to
- remain live as JSValueProtect would.  Any objects that are intended to be stored in a weak map must be user defined objects that
- remove themselves from the map in their finalizer.
+ remain live as JSValueProtect would.
  */
 JS_EXPORT JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef ctx, void* data, JSWeakMapDestroyedCallback destructor);
 
@@ -79,14 +78,12 @@ JS_EXPORT JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef ma
 
 /*!
  @function
- @abstract Clears the association between a key and an object in a JSWeakObjectMapRef
+ @abstract Removes the entry for the given key if the key is present, otherwise it has no effect.
  @param ctx The execution context to use.
- @param map The map to clear the key association from.
- @param key The key to use.
- @param object The old object value.
- @result Returns true if the key/object association was present in map, and has been removed.
+ @param map The map to use.
+ @param key The key to remove.
  */
-JS_EXPORT bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object);
+JS_EXPORT void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key);
 
 #ifdef __cplusplus
 }
index f740abe3b135c36d24aaba853387b1ffdb825275..9a116e6b2f63937d0d02d088c61a554c9fc23b86 100644 (file)
@@ -35,7 +35,7 @@ using namespace JSC;
 PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring)
 {
     if (!ustring.isNull())
-        return adoptRef(new OpaqueJSString(ustring.data(), ustring.size()));
+        return adoptRef(new OpaqueJSString(ustring.characters(), ustring.length()));
     return 0;
 }
 
@@ -43,7 +43,7 @@ UString OpaqueJSString::ustring() const
 {
     if (this && m_characters)
         return UString(m_characters, m_length);
-    return UString::null();
+    return UString();
 }
 
 Identifier OpaqueJSString::identifier(JSGlobalData* globalData) const
index 473c815069189f57b77be0f46f724777fba7ab49..69c0962a66703b57b3384e5b1ead7bc467364caf 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
     class JSGlobalData;
 }
 
-struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> {
+struct OpaqueJSString : public ThreadSafeRefCounted<OpaqueJSString> {
 
     static PassRefPtr<OpaqueJSString> create() // null
     {
@@ -54,7 +54,7 @@ struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> {
     JSC::Identifier identifier(JSC::JSGlobalData*) const;
 
 private:
-    friend class WTF::ThreadSafeShared<OpaqueJSString>;
+    friend class WTF::ThreadSafeRefCounted<OpaqueJSString>;
 
     OpaqueJSString()
         : m_characters(0)
index 28b4ec8137fcb0eff0c0c0d52772333eeac51aec..e82d41d77b9b62a36049a499910f7c380a75f3c4 100644 (file)
 #include <wtf/Assertions.h>
 #include <wtf/UnusedParam.h>
 
+#if OS(WINDOWS)
+#include <windows.h>
+#endif
+
 #if COMPILER(MSVC)
 
 #include <wtf/MathExtras.h>
@@ -307,8 +311,19 @@ static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef objec
     return JSValueMakeNull(context);
 }
 
+static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+    UNUSED_PARAM(ctx);
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(propertyName);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(exception);
+    return false; // Forward to parent class.
+}
+
 static JSStaticValue evilStaticValues[] = {
     { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
+    { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet, kJSPropertyAttributeNone },
     { 0, 0, 0, 0 }
 };
 
@@ -351,6 +366,111 @@ static JSClassRef MyObject_class(JSContextRef context)
     return jsClass;
 }
 
+static JSValueRef PropertyCatchalls_getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(propertyName);
+    UNUSED_PARAM(exception);
+
+    if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
+        static size_t count;
+        if (count++ < 5)
+            return NULL;
+
+        // Swallow all .x gets after 5, returning null.
+        return JSValueMakeNull(context);
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, "y")) {
+        static size_t count;
+        if (count++ < 5)
+            return NULL;
+
+        // Swallow all .y gets after 5, returning null.
+        return JSValueMakeNull(context);
+    }
+    
+    if (JSStringIsEqualToUTF8CString(propertyName, "z")) {
+        static size_t count;
+        if (count++ < 5)
+            return NULL;
+
+        // Swallow all .y gets after 5, returning null.
+        return JSValueMakeNull(context);
+    }
+
+    return NULL;
+}
+
+static bool PropertyCatchalls_setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(object);
+    UNUSED_PARAM(propertyName);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(exception);
+
+    if (JSStringIsEqualToUTF8CString(propertyName, "x")) {
+        static size_t count;
+        if (count++ < 5)
+            return false;
+
+        // Swallow all .x sets after 4.
+        return true;
+    }
+
+    return false;
+}
+
+static void PropertyCatchalls_getPropertyNames(JSContextRef context, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames)
+{
+    UNUSED_PARAM(context);
+    UNUSED_PARAM(object);
+
+    static size_t count;
+    static const char* numbers[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+    
+    // Provide a property of a different name every time.
+    JSStringRef propertyName = JSStringCreateWithUTF8CString(numbers[count++ % 10]);
+    JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+    JSStringRelease(propertyName);
+}
+
+JSClassDefinition PropertyCatchalls_definition = {
+    0,
+    kJSClassAttributeNone,
+    
+    "PropertyCatchalls",
+    NULL,
+    
+    NULL,
+    NULL,
+    
+    NULL,
+    NULL,
+    NULL,
+    PropertyCatchalls_getProperty,
+    PropertyCatchalls_setProperty,
+    NULL,
+    PropertyCatchalls_getPropertyNames,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+};
+
+static JSClassRef PropertyCatchalls_class(JSContextRef context)
+{
+    UNUSED_PARAM(context);
+
+    static JSClassRef jsClass;
+    if (!jsClass)
+        jsClass = JSClassCreate(&PropertyCatchalls_definition);
+    
+    return jsClass;
+}
+
 static bool EvilExceptionObject_hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleValue, JSValueRef* exception)
 {
     UNUSED_PARAM(context);
@@ -764,8 +884,68 @@ static void makeGlobalNumberValue(JSContextRef context) {
     v = NULL;
 }
 
+static bool assertTrue(bool value, const char* message)
+{
+    if (!value) {
+        if (message)
+            fprintf(stderr, "assertTrue failed: '%s'\n", message);
+        else
+            fprintf(stderr, "assertTrue failed.\n");
+        failed = 1;
+    }
+    return value;
+}
+
+static bool checkForCycleInPrototypeChain()
+{
+    bool result = true;
+    JSGlobalContextRef context = JSGlobalContextCreate(0);
+    JSObjectRef object1 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
+    JSObjectRef object2 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
+    JSObjectRef object3 = JSObjectMake(context, /* jsClass */ 0, /* data */ 0);
+
+    JSObjectSetPrototype(context, object1, JSValueMakeNull(context));
+    ASSERT(JSValueIsNull(context, JSObjectGetPrototype(context, object1)));
+
+    // object1 -> object1
+    JSObjectSetPrototype(context, object1, object1);
+    result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to assign self as a prototype");
+
+    // object1 -> object2 -> object1
+    JSObjectSetPrototype(context, object2, object1);
+    ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object1));
+    JSObjectSetPrototype(context, object1, object2);
+    result &= assertTrue(JSValueIsNull(context, JSObjectGetPrototype(context, object1)), "It is possible to close a prototype chain cycle");
+
+    // object1 -> object2 -> object3 -> object1
+    JSObjectSetPrototype(context, object2, object3);
+    ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object2), object3));
+    JSObjectSetPrototype(context, object1, object2);
+    ASSERT(JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object1), object2));
+    JSObjectSetPrototype(context, object3, object1);
+    result &= assertTrue(!JSValueIsStrictEqual(context, JSObjectGetPrototype(context, object3), object1), "It is possible to close a prototype chain cycle");
+
+    JSValueRef exception;
+    JSStringRef code = JSStringCreateWithUTF8CString("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
+    JSStringRef file = JSStringCreateWithUTF8CString("");
+    result &= assertTrue(!JSEvaluateScript(context, code, /* thisObject*/ 0, file, 1, &exception)
+                         , "An exception should be thrown");
+
+    JSStringRelease(code);
+    JSStringRelease(file);
+    JSGlobalContextRelease(context);
+    return result;
+}
+
 int main(int argc, char* argv[])
 {
+#if OS(WINDOWS)
+    // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
+    // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
+    // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
+    ::SetErrorMode(0);
+#endif
+
     const char *scriptPath = "testapi.js";
     if (argc > 1) {
         scriptPath = argv[1];
@@ -858,6 +1038,11 @@ int main(int argc, char* argv[])
     ASSERT(JSValueGetType(context, jsCFEmptyString) == kJSTypeString);
     ASSERT(JSValueGetType(context, jsCFEmptyStringWithCharacters) == kJSTypeString);
 
+    JSObjectRef propertyCatchalls = JSObjectMake(context, PropertyCatchalls_class(context), NULL);
+    JSStringRef propertyCatchallsString = JSStringCreateWithUTF8CString("PropertyCatchalls");
+    JSObjectSetProperty(context, globalObject, propertyCatchallsString, propertyCatchalls, kJSPropertyAttributeNone, NULL);
+    JSStringRelease(propertyCatchallsString);
+
     JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);
     JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");
     JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);
@@ -874,21 +1059,21 @@ int main(int argc, char* argv[])
     JSStringRelease(EmptyObjectIString);
     
     JSStringRef lengthStr = JSStringCreateWithUTF8CString("length");
-    aHeapRef = JSObjectMakeArray(context, 0, 0, 0);
+    JSObjectRef aStackRef = JSObjectMakeArray(context, 0, 0, 0);
+    aHeapRef = aStackRef;
     JSObjectSetProperty(context, aHeapRef, lengthStr, JSValueMakeNumber(context, 10), 0, 0);
     JSStringRef privatePropertyName = JSStringCreateWithUTF8CString("privateProperty");
     if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, aHeapRef)) {
         printf("FAIL: Could not set private property.\n");
-        failed = 1;        
-    } else {
+        failed = 1;
+    } else
         printf("PASS: Set private property.\n");
-    }
+    aStackRef = 0;
     if (JSObjectSetPrivateProperty(context, aHeapRef, privatePropertyName, aHeapRef)) {
         printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n");
-        failed = 1;        
-    } else {
+        failed = 1;
+    } else
         printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n");
-    }
     if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName) != aHeapRef) {
         printf("FAIL: Could not retrieve private property.\n");
         failed = 1;
@@ -899,25 +1084,37 @@ int main(int argc, char* argv[])
         failed = 1;
     } else
         printf("PASS: JSObjectGetPrivateProperty return NULL.\n");
-    
+
     if (JSObjectGetProperty(context, myObject, privatePropertyName, 0) == aHeapRef) {
         printf("FAIL: Accessed private property through ordinary property lookup.\n");
         failed = 1;
     } else
         printf("PASS: Cannot access private property through ordinary property lookup.\n");
-    
+
     JSGarbageCollect(context);
-    
+
     for (int i = 0; i < 10000; i++)
         JSObjectMake(context, 0, 0);
 
+    aHeapRef = JSValueToObject(context, JSObjectGetPrivateProperty(context, myObject, privatePropertyName), 0);
     if (JSValueToNumber(context, JSObjectGetProperty(context, aHeapRef, lengthStr, 0), 0) != 10) {
         printf("FAIL: Private property has been collected.\n");
         failed = 1;
     } else
         printf("PASS: Private property does not appear to have been collected.\n");
     JSStringRelease(lengthStr);
-    
+
+    if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, 0)) {
+        printf("FAIL: Could not set private property to NULL.\n");
+        failed = 1;
+    } else
+        printf("PASS: Set private property to NULL.\n");
+    if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName)) {
+        printf("FAIL: Could not retrieve private property.\n");
+        failed = 1;
+    } else
+        printf("PASS: Retrieved private property.\n");
+
     JSStringRef validJSON = JSStringCreateWithUTF8CString("{\"aProperty\":true}");
     JSValueRef jsonObject = JSValueMakeFromJSONString(context, validJSON);
     JSStringRelease(validJSON);
@@ -1346,6 +1543,13 @@ int main(int argc, char* argv[])
 
     printf("PASS: Infinite prototype chain does not occur.\n");
 
+    if (checkForCycleInPrototypeChain())
+        printf("PASS: A cycle in a prototype chain can't be created.\n");
+    else {
+        printf("FAIL: A cycle in a prototype chain can be created.\n");
+        failed = true;
+    }
+
     if (failed) {
         printf("FAIL: Some tests failed.\n");
         return 1;
index 15c9e50db22e7da230f2bb895bd017bb38912bde..61d4533e84f4bde092983e5429cfd924aeb1764e 100644 (file)
@@ -94,6 +94,9 @@ shouldBe("MyObject('throwOnCall')", "an exception");
 shouldBe("new MyObject('throwOnConstruct')", "an exception");
 shouldBe("'throwOnHasInstance' instanceof MyObject", "an exception");
 
+MyObject.nullGetForwardSet = 1;
+shouldBe("MyObject.nullGetForwardSet", 1);
+
 var foundMyPropertyName = false;
 var foundRegularType = false;
 for (var p in MyObject) {
@@ -162,8 +165,8 @@ shouldBe("constructedObject.value", 1);
 shouldBe("myObject instanceof MyObject", true);
 shouldBe("(new Object()) instanceof MyObject", false);
 
-shouldThrow("MyObject.nullGetSet = 1");
-shouldThrow("MyObject.nullGetSet");
+MyObject.nullGetSet = 1;
+shouldBe("MyObject.nullGetSet", 1);
 shouldThrow("MyObject.nullCall()");
 shouldThrow("MyObject.hasPropertyLie");
 
@@ -246,6 +249,32 @@ shouldThrow("String(EvilExceptionObject)");
 
 shouldBe("EmptyObject", "[object CallbackObject]");
 
+for (var i = 0; i < 6; ++i)
+    PropertyCatchalls.x = i;
+shouldBe("PropertyCatchalls.x", 4);
+
+for (var i = 0; i < 6; ++i)
+    var x = PropertyCatchalls.x;
+shouldBe("x", null);
+
+for (var i = 0; i < 10; ++i) {
+    for (var p in PropertyCatchalls) {
+        if (p == "x")
+            continue;
+        shouldBe("p", i % 10);
+        break;
+    }
+}
+
+PropertyCatchalls.__proto__ = { y: 1 };
+for (var i = 0; i < 6; ++i)
+    var y = PropertyCatchalls.y;
+shouldBe("y", null);
+
+var o = { __proto__: PropertyCatchalls };
+for (var i = 0; i < 6; ++i)
+    var z = PropertyCatchalls.z;
+shouldBe("z", null);
+
 if (failed)
     throw "Some tests failed";
-
diff --git a/Android.mk b/Android.mk
deleted file mode 100644 (file)
index 1b5da02..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-##
-## Copyright 2009, The Android Open Source Project
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##  * Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer.
-##  * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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.
-##
-
-LOCAL_SRC_FILES := \
-       API/JSValueRef.cpp \
-       API/JSCallbackObject.cpp \
-       API/OpaqueJSString.cpp \
-       \
-       bytecode/CodeBlock.cpp \
-       bytecode/JumpTable.cpp \
-       bytecode/Opcode.cpp \
-       bytecode/SamplingTool.cpp \
-       bytecode/StructureStubInfo.cpp \
-       \
-       bytecompiler/BytecodeGenerator.cpp \
-       bytecompiler/NodesCodegen.cpp \
-       \
-       debugger/Debugger.cpp \
-       debugger/DebuggerActivation.cpp \
-       debugger/DebuggerCallFrame.cpp \
-       \
-       interpreter/CallFrame.cpp \
-       interpreter/Interpreter.cpp \
-       interpreter/RegisterFile.cpp \
-       \
-       jit/ExecutableAllocator.cpp\
-       jit/ExecutableAllocatorFixedVMPool.cpp \
-       jit/ExecutableAllocatorPosix.cpp \
-       jit/JIT.cpp \
-       jit/JITArithmetic.cpp \
-       jit/JITCall.cpp \
-       jit/JITOpcodes.cpp \
-       jit/JITPropertyAccess.cpp \
-       jit/JITStubs.cpp \
-       \
-       parser/Lexer.cpp \
-       parser/Nodes.cpp \
-       parser/Parser.cpp \
-       parser/ParserArena.cpp \
-       \
-       pcre/pcre_compile.cpp \
-       pcre/pcre_exec.cpp \
-       pcre/pcre_tables.cpp \
-       pcre/pcre_ucp_searchfuncs.cpp \
-       pcre/pcre_xclass.cpp \
-       \
-       profiler/Profile.cpp \
-       profiler/ProfileGenerator.cpp \
-       profiler/ProfileNode.cpp \
-       profiler/Profiler.cpp \
-       \
-       runtime/ArgList.cpp \
-       runtime/Arguments.cpp \
-       runtime/ArrayConstructor.cpp \
-       runtime/ArrayPrototype.cpp \
-       runtime/BooleanConstructor.cpp \
-       runtime/BooleanObject.cpp \
-       runtime/BooleanPrototype.cpp \
-       runtime/CallData.cpp \
-       runtime/Collector.cpp \
-       runtime/CommonIdentifiers.cpp \
-       runtime/Completion.cpp \
-       runtime/ConstructData.cpp \
-       runtime/DateConstructor.cpp \
-       runtime/DateConversion.cpp \
-       runtime/DateInstance.cpp \
-       runtime/DatePrototype.cpp \
-       runtime/Error.cpp \
-       runtime/ErrorConstructor.cpp \
-       runtime/ErrorInstance.cpp \
-       runtime/ErrorPrototype.cpp \
-       runtime/ExceptionHelpers.cpp \
-       runtime/Executable.cpp \
-       runtime/FunctionConstructor.cpp \
-       runtime/FunctionPrototype.cpp \
-       runtime/GetterSetter.cpp \
-       runtime/GlobalEvalFunction.cpp \
-       runtime/Identifier.cpp \
-       runtime/InitializeThreading.cpp \
-       runtime/InternalFunction.cpp \
-       runtime/JSAPIValueWrapper.cpp \
-       runtime/JSActivation.cpp \
-       runtime/JSArray.cpp \
-       runtime/JSByteArray.cpp \
-       runtime/JSCell.cpp \
-       runtime/JSFunction.cpp \
-       runtime/JSGlobalData.cpp \
-       runtime/JSGlobalObject.cpp \
-       runtime/JSGlobalObjectFunctions.cpp \
-       runtime/JSImmediate.cpp \
-       runtime/JSLock.cpp \
-       runtime/JSNotAnObject.cpp \
-       runtime/JSNumberCell.cpp \
-       runtime/JSONObject.cpp \
-       runtime/JSObject.cpp \
-       runtime/JSPropertyNameIterator.cpp \
-       runtime/JSStaticScopeObject.cpp \
-       runtime/JSString.cpp \
-       runtime/JSValue.cpp \
-       runtime/JSVariableObject.cpp \
-       runtime/JSWrapperObject.cpp \
-       runtime/LiteralParser.cpp \
-       runtime/Lookup.cpp \
-       runtime/MarkStack.cpp \
-       runtime/MarkStackPosix.cpp \
-       runtime/MathObject.cpp \
-       runtime/NativeErrorConstructor.cpp \
-       runtime/NativeErrorPrototype.cpp \
-       runtime/NumberConstructor.cpp \
-       runtime/NumberObject.cpp \
-       runtime/NumberPrototype.cpp \
-       runtime/ObjectConstructor.cpp \
-       runtime/ObjectPrototype.cpp \
-       runtime/Operations.cpp \
-       runtime/PropertyDescriptor.cpp \
-       runtime/PropertyNameArray.cpp \
-       runtime/PropertySlot.cpp \
-       runtime/PrototypeFunction.cpp \
-       runtime/RegExp.cpp \
-       runtime/RegExpConstructor.cpp \
-       runtime/RegExpObject.cpp \
-       runtime/RegExpPrototype.cpp \
-       runtime/ScopeChain.cpp \
-       runtime/SmallStrings.cpp \
-       runtime/StringConstructor.cpp \
-       runtime/StringObject.cpp \
-       runtime/StringPrototype.cpp \
-       runtime/Structure.cpp \
-       runtime/StructureChain.cpp \
-       runtime/TimeoutChecker.cpp \
-       runtime/UString.cpp \
-       \
-       wtf/Assertions.cpp \
-       wtf/ByteArray.cpp \
-       wtf/CurrentTime.cpp \
-       wtf/DateMath.cpp \
-       wtf/FastMalloc.cpp \
-       wtf/HashTable.cpp \
-       wtf/MainThread.cpp \
-       wtf/RandomNumber.cpp \
-       wtf/RefCountedLeakCounter.cpp \
-       wtf/TCSystemAlloc.cpp \
-       wtf/ThreadIdentifierDataPthreads.cpp \
-       wtf/Threading.cpp \
-       wtf/ThreadingPthreads.cpp \
-       wtf/WTFThreadData.cpp \
-       \
-       wtf/TypeTraits.cpp \
-       wtf/dtoa.cpp \
-       \
-       wtf/android/MainThreadAndroid.cpp \
-       \
-       wtf/text/AtomicString.cpp \
-       wtf/text/CString.cpp \
-       wtf/text/StringImpl.cpp \
-       wtf/text/WTFString.cpp \
-       \
-       wtf/unicode/CollatorDefault.cpp \
-       wtf/unicode/UTF8.cpp \
-       \
-       wtf/unicode/icu/CollatorICU.cpp \
-       \
-       yarr/RegexCompiler.cpp \
-       yarr/RegexInterpreter.cpp \
-       yarr/RegexJIT.cpp
-
-# Rule to build grammar.y with our custom bison.
-GEN := $(intermediates)/parser/Grammar.cpp
-$(GEN) : PRIVATE_YACCFLAGS := -p jscyy
-$(GEN) : $(LOCAL_PATH)/parser/Grammar.y
-       $(call local-transform-y-to-cpp,.cpp)
-$(GEN) : $(LOCAL_BISON)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-# generated headers
-JSC_OBJECTS := $(addprefix $(intermediates)/runtime/, \
-                               ArrayPrototype.lut.h \
-                               DatePrototype.lut.h \
-                               JSONObject.lut.h \
-                               MathObject.lut.h \
-                               NumberConstructor.lut.h \
-                               RegExpConstructor.lut.h \
-                               RegExpObject.lut.h \
-                               StringPrototype.lut.h \
-                       )
-$(JSC_OBJECTS): PRIVATE_PATH := $(LOCAL_PATH)
-$(JSC_OBJECTS): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@
-$(JSC_OBJECTS): $(LOCAL_PATH)/create_hash_table
-$(JSC_OBJECTS): $(intermediates)/%.lut.h : $(LOCAL_PATH)/%.cpp
-       $(transform-generated-source)
-
-
-LEXER_HEADER := $(intermediates)/Lexer.lut.h
-$(LEXER_HEADER): PRIVATE_PATH := $(LOCAL_PATH)
-$(LEXER_HEADER): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/create_hash_table $< -i > $@
-$(LEXER_HEADER): $(LOCAL_PATH)/create_hash_table
-$(LEXER_HEADER): $(intermediates)/%.lut.h : $(LOCAL_PATH)/parser/Keywords.table
-       $(transform-generated-source)
-
-CHARTABLES := $(intermediates)/chartables.c
-$(CHARTABLES): PRIVATE_PATH := $(LOCAL_PATH)
-$(CHARTABLES): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/pcre/dftables $@
-$(CHARTABLES): $(LOCAL_PATH)/pcre/dftables
-$(CHARTABLES): $(LOCAL_PATH)/pcre/pcre_internal.h
-       $(transform-generated-source)
-
-LOCAL_GENERATED_SOURCES += $(JSC_OBJECTS) $(LEXER_HEADER) $(CHARTABLES)
diff --git a/Android.v8.wtf.mk b/Android.v8.wtf.mk
deleted file mode 100644 (file)
index 9249e47..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-##
-## Copyright 2009, The Android Open Source Project
-##
-## Redistribution and use in source and binary forms, with or without
-## modification, are permitted provided that the following conditions
-## are met:
-##  * Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer.
-##  * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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.
-##
-
-# wtf source files
-
-LOCAL_SRC_FILES := \
-       pcre/pcre_compile.cpp \
-       pcre/pcre_exec.cpp \
-       pcre/pcre_tables.cpp \
-       pcre/pcre_ucp_searchfuncs.cpp \
-       pcre/pcre_xclass.cpp \
-       \
-       wtf/Assertions.cpp \
-       wtf/ByteArray.cpp \
-       wtf/CurrentTime.cpp \
-       wtf/DateMath.cpp \
-       wtf/FastMalloc.cpp \
-       wtf/HashTable.cpp \
-       wtf/MainThread.cpp \
-       wtf/RandomNumber.cpp \
-       wtf/RefCountedLeakCounter.cpp \
-       wtf/TCSystemAlloc.cpp \
-       wtf/ThreadIdentifierDataPthreads.cpp \
-       wtf/Threading.cpp \
-       wtf/ThreadingPthreads.cpp \
-       wtf/WTFThreadData.cpp \
-       \
-       wtf/TypeTraits.cpp \
-       wtf/dtoa.cpp \
-       \
-       wtf/android/MainThreadAndroid.cpp \
-       \
-       wtf/text/AtomicString.cpp \
-       wtf/text/CString.cpp \
-       wtf/text/StringImpl.cpp \
-       wtf/text/WTFString.cpp \
-       \
-       wtf/unicode/CollatorDefault.cpp \
-       wtf/unicode/UTF8.cpp \
-       \
-       wtf/unicode/icu/CollatorICU.cpp
-
-CHARTABLES := $(intermediates)/chartables.c
-$(CHARTABLES): PRIVATE_PATH := $(LOCAL_PATH)
-$(CHARTABLES): PRIVATE_CUSTOM_TOOL = perl $(PRIVATE_PATH)/pcre/dftables $@
-$(CHARTABLES): $(LOCAL_PATH)/pcre/dftables
-$(CHARTABLES): $(LOCAL_PATH)/pcre/pcre_internal.h
-       $(transform-generated-source)
-
-$(intermediates)/pcre/pcre_tables.o : $(CHARTABLES)
-
-# We do not add $(CHARTABLES) to LOCAL_GENERATED_SOURCES because the chartables.c file
-# is explicitly #included in pcre_tables.cpp.
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..870b15e
--- /dev/null
@@ -0,0 +1,266 @@
+SET(JavaScriptCore_INCLUDE_DIRECTORIES
+    "${CMAKE_BINARY_DIR}"
+    "${JAVASCRIPTCORE_DIR}"
+    "${JAVASCRIPTCORE_DIR}/API"
+    "${JAVASCRIPTCORE_DIR}/ForwardingHeaders"
+    "${JAVASCRIPTCORE_DIR}/assembler"
+    "${JAVASCRIPTCORE_DIR}/bytecode"
+    "${JAVASCRIPTCORE_DIR}/bytecompiler"
+    "${JAVASCRIPTCORE_DIR}/heap"
+    "${JAVASCRIPTCORE_DIR}/debugger"
+    "${JAVASCRIPTCORE_DIR}/interpreter"
+    "${JAVASCRIPTCORE_DIR}/jit"
+    "${JAVASCRIPTCORE_DIR}/parser"
+    "${JAVASCRIPTCORE_DIR}/profiler"
+    "${JAVASCRIPTCORE_DIR}/runtime"
+    "${JAVASCRIPTCORE_DIR}/yarr"
+    "${WTF_INCLUDE_DIRECTORIES}"
+    "${CMAKE_SOURCE_DIR}"
+)
+
+SET(JavaScriptCore_SOURCES
+    API/JSBase.cpp
+    API/JSCallbackConstructor.cpp
+    API/JSCallbackFunction.cpp
+    API/JSCallbackObject.cpp
+    API/JSClassRef.cpp
+    API/JSContextRef.cpp
+    API/JSObjectRef.cpp
+    API/JSProfilerPrivate.cpp
+    API/JSStringRef.cpp
+    API/JSValueRef.cpp
+    API/JSWeakObjectMapRefPrivate.cpp
+    API/OpaqueJSString.cpp
+
+    bytecode/CodeBlock.cpp
+    bytecode/JumpTable.cpp
+    bytecode/Opcode.cpp
+    bytecode/SamplingTool.cpp
+    bytecode/StructureStubInfo.cpp
+
+    bytecompiler/BytecodeGenerator.cpp
+    bytecompiler/NodesCodegen.cpp
+
+    heap/Heap.cpp
+    heap/HandleHeap.cpp
+    heap/HandleStack.cpp
+    heap/MachineStackMarker.cpp
+    heap/MarkedBlock.cpp
+    heap/MarkedSpace.cpp
+    heap/ConservativeRoots.cpp
+    heap/MarkStack.cpp
+
+    debugger/Debugger.cpp
+    debugger/DebuggerActivation.cpp
+    debugger/DebuggerCallFrame.cpp
+
+    interpreter/CallFrame.cpp
+    interpreter/Interpreter.cpp
+    interpreter/RegisterFile.cpp
+
+    jit/ExecutableAllocator.cpp
+    jit/JITArithmetic32_64.cpp
+    jit/JITArithmetic.cpp
+    jit/JITCall32_64.cpp
+    jit/JITCall.cpp
+    jit/JIT.cpp
+    jit/JITOpcodes32_64.cpp
+    jit/JITOpcodes.cpp
+    jit/JITPropertyAccess32_64.cpp
+    jit/JITPropertyAccess.cpp
+    jit/JITStubs.cpp
+    jit/ThunkGenerators.cpp
+
+    parser/JSParser.cpp
+    parser/Lexer.cpp
+    parser/Nodes.cpp
+    parser/Parser.cpp
+    parser/ParserArena.cpp
+    parser/SourceProviderCache.cpp
+
+    profiler/Profile.cpp
+    profiler/ProfileGenerator.cpp
+    profiler/ProfileNode.cpp
+    profiler/Profiler.cpp
+
+    runtime/ArgList.cpp
+    runtime/Arguments.cpp
+    runtime/ArrayConstructor.cpp
+    runtime/ArrayPrototype.cpp
+    runtime/BooleanConstructor.cpp
+    runtime/BooleanObject.cpp
+    runtime/BooleanPrototype.cpp
+    runtime/CallData.cpp
+    runtime/CommonIdentifiers.cpp
+    runtime/Completion.cpp
+    runtime/ConstructData.cpp
+    runtime/DateConstructor.cpp
+    runtime/DateConversion.cpp
+    runtime/DateInstance.cpp
+    runtime/DatePrototype.cpp
+    runtime/Error.cpp
+    runtime/ErrorConstructor.cpp
+    runtime/ErrorInstance.cpp
+    runtime/ErrorPrototype.cpp
+    runtime/ExceptionHelpers.cpp
+    runtime/Executable.cpp
+    runtime/FunctionConstructor.cpp
+    runtime/FunctionPrototype.cpp
+    runtime/GCActivityCallback.cpp
+    runtime/GetterSetter.cpp
+    runtime/Identifier.cpp
+    runtime/InitializeThreading.cpp
+    runtime/InternalFunction.cpp
+    runtime/JSActivation.cpp
+    runtime/JSAPIValueWrapper.cpp
+    runtime/JSArray.cpp
+    runtime/JSByteArray.cpp
+    runtime/JSCell.cpp
+    runtime/JSFunction.cpp
+    runtime/JSGlobalData.cpp
+    runtime/JSGlobalObject.cpp
+    runtime/JSGlobalObjectFunctions.cpp
+    runtime/JSLock.cpp
+    runtime/JSNotAnObject.cpp
+    runtime/JSObject.cpp
+    runtime/JSObjectWithGlobalObject.cpp
+    runtime/JSONObject.cpp
+    runtime/JSPropertyNameIterator.cpp
+    runtime/JSStaticScopeObject.cpp
+    runtime/JSString.cpp
+    runtime/JSValue.cpp
+    runtime/JSVariableObject.cpp
+    runtime/JSWrapperObject.cpp
+    runtime/JSZombie.cpp
+    runtime/LiteralParser.cpp
+    runtime/Lookup.cpp
+    runtime/MathObject.cpp
+    runtime/NativeErrorConstructor.cpp
+    runtime/NativeErrorPrototype.cpp
+    runtime/NumberConstructor.cpp
+    runtime/NumberObject.cpp
+    runtime/NumberPrototype.cpp
+    runtime/ObjectConstructor.cpp
+    runtime/ObjectPrototype.cpp
+    runtime/Operations.cpp
+    runtime/PropertyDescriptor.cpp
+    runtime/PropertyNameArray.cpp
+    runtime/PropertySlot.cpp
+    runtime/RegExp.cpp
+    runtime/RegExpCache.cpp
+    runtime/RegExpConstructor.cpp
+    runtime/RegExpObject.cpp
+    runtime/RegExpPrototype.cpp
+    runtime/RopeImpl.cpp
+    runtime/ScopeChain.cpp
+    runtime/SmallStrings.cpp
+    runtime/StrictEvalActivation.cpp
+    runtime/StringConstructor.cpp
+    runtime/StringObject.cpp
+    runtime/StringPrototype.cpp
+    runtime/StringRecursionChecker.cpp
+    runtime/Structure.cpp
+    runtime/StructureChain.cpp
+    runtime/TimeoutChecker.cpp
+    runtime/UString.cpp
+
+    yarr/YarrPattern.cpp
+    yarr/YarrInterpreter.cpp
+    yarr/YarrJIT.cpp
+    yarr/YarrSyntaxChecker.cpp
+
+    wtf/DateMath.cpp
+    wtf/PageAllocationAligned.cpp
+    wtf/PageBlock.cpp
+)
+SET(JavaScriptCore_HEADERS )
+
+SET(JavaScriptCore_LUT_FILES
+    runtime/ArrayConstructor.cpp
+    runtime/ArrayPrototype.cpp
+    runtime/BooleanPrototype.cpp
+    runtime/DateConstructor.cpp
+    runtime/DatePrototype.cpp
+    runtime/ErrorPrototype.cpp
+    runtime/JSGlobalObject.cpp
+    runtime/JSONObject.cpp
+    runtime/MathObject.cpp
+    runtime/NumberConstructor.cpp
+    runtime/NumberPrototype.cpp
+    runtime/ObjectConstructor.cpp
+    runtime/ObjectPrototype.cpp
+    runtime/RegExpConstructor.cpp
+    runtime/RegExpObject.cpp
+    runtime/RegExpPrototype.cpp
+    runtime/StringConstructor.cpp
+    runtime/StringPrototype.cpp
+)
+
+SET(JavaScriptCore_LIBRARIES
+    ${WTF_LIBRARY_NAME}
+)
+
+
+# GENERATOR 1-A: LUT creator
+FOREACH (_file ${JavaScriptCore_LUT_FILES})
+    GET_FILENAME_COMPONENT(_name ${_file} NAME_WE)
+    GENERATE_HASH_LUT(${JAVASCRIPTCORE_DIR}/${_file} ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/${_name}.lut.h)
+    LIST(APPEND JavaScriptCore_HEADERS ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/${_name}.lut.h)
+ENDFOREACH ()
+
+
+# GENERATOR 1-B: particular LUT creator (for 1 file only)
+GENERATE_HASH_LUT(${JAVASCRIPTCORE_DIR}/parser/Keywords.table ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Lexer.lut.h MAIN_DEPENDENCY)
+LIST(APPEND JavaScriptCore_HEADERS ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Lexer.lut.h)
+
+#GENERATOR: "RegExpJitTables.h": tables used by Yarr
+ADD_CUSTOM_COMMAND(
+    OUTPUT ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/RegExpJitTables.h
+    MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/create_regex_tables
+    COMMAND ${PYTHON_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/create_regex_tables > ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/RegExpJitTables.h
+    VERBATIM)
+ADD_SOURCE_DEPENDENCIES(${JAVASCRIPTCORE_DIR}/yarr/YarrPattern.cpp ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/RegExpJitTables.h)
+
+
+#GENERATOR: "KeywordLookup.h": keyword decision tree used by the lexer
+ADD_CUSTOM_COMMAND(
+    OUTPUT ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/KeywordLookup.h
+    MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/KeywordLookupGenerator.py
+    COMMAND ${PYTHON_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/KeywordLookupGenerator.py ${JAVASCRIPTCORE_DIR}/parser/Keywords.table > ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/KeywordLookup.h
+    VERBATIM)
+ADD_SOURCE_DEPENDENCIES(${JAVASCRIPTCORE_DIR}/parser/Lexer.cpp ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/KeywordLookup.h)
+
+IF (WTF_CPU_ARM)
+    LIST(APPEND JavaScriptCore_SOURCES
+        assembler/ARMAssembler.cpp
+        assembler/ARMv7Assembler.cpp
+        assembler/MacroAssemblerARM.cpp
+    )
+ELSEIF (WTF_CPU_MIPS)
+ELSEIF (WTF_CPU_X86)
+ELSEIF (WTF_CPU_X86_64)
+ELSE ()
+    MESSAGE(FATAL_ERROR "Unknown CPU")
+ENDIF ()
+
+
+INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/CMakeLists${PORT}.txt)
+
+
+ADD_SUBDIRECTORY(wtf)
+ADD_SUBDIRECTORY(shell)
+
+WEBKIT_WRAP_SOURCELIST(${JavaScriptCore_SOURCES})
+INCLUDE_DIRECTORIES(${JavaScriptCore_INCLUDE_DIRECTORIES})
+ADD_DEFINITIONS(-DBUILDING_JavaScriptCore)
+ADD_LIBRARY(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARY_TYPE} ${JavaScriptCore_HEADERS} ${JavaScriptCore_SOURCES})
+TARGET_LINK_LIBRARIES(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARIES})
+
+IF (JavaScriptCore_LINK_FLAGS)
+    ADD_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} LINK_FLAGS "${JavaScriptCore_LINK_FLAGS}")
+ENDIF ()
+
+IF (SHARED_CORE)
+    SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
+    INSTALL(TARGETS ${JavaScriptCore_LIBRARY_NAME} DESTINATION lib)
+ENDIF ()
diff --git a/CMakeListsEfl.txt b/CMakeListsEfl.txt
new file mode 100644 (file)
index 0000000..cdc3fe2
--- /dev/null
@@ -0,0 +1,20 @@
+LIST(APPEND JavaScriptCore_SOURCES
+    jit/ExecutableAllocatorFixedVMPool.cpp
+    jit/ExecutableAllocator.cpp
+    heap/MarkStackPosix.cpp
+    wtf/OSAllocatorPosix.cpp
+)
+
+LIST(APPEND JavaScriptCore_LIBRARIES
+    ${ICU_I18N_LIBRARIES}
+)
+
+IF (ENABLE_GLIB_SUPPORT)
+  LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES
+    ${JAVASCRIPTCORE_DIR}/wtf/gobject
+  )
+ENDIF ()
+
+LIST(APPEND JavaScriptCore_LINK_FLAGS
+    ${ECORE_LDFLAGS}
+)
diff --git a/CMakeListsWinCE.txt b/CMakeListsWinCE.txt
new file mode 100644 (file)
index 0000000..d878863
--- /dev/null
@@ -0,0 +1,22 @@
+LIST(APPEND JavaScriptCore_SOURCES
+    jit/ExecutableAllocator.cpp
+
+    heap/MarkStackWin.cpp
+)
+
+IF (ENABLE_JIT AND WTF_CPU_ARM)
+    ADD_CUSTOM_COMMAND(
+        OUTPUT ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.asm
+        MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/create_jit_stubs
+        DEPENDS ${JAVASCRIPTCORE_DIR}/jit/JITStubs.cpp
+        COMMAND ${PERL_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/create_jit_stubs --prefix=MSVC ${JAVASCRIPTCORE_DIR}/jit/JITStubs.cpp > ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.asm
+        VERBATIM)
+
+    ADD_CUSTOM_COMMAND(
+        OUTPUT ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.obj
+        MAIN_DEPENDENCY ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.asm
+        COMMAND armasm -nologo ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.asm ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.obj
+        VERBATIM)
+
+    LIST (APPEND JavaScriptCore_SOURCES ${DERIVED_SOURCES_DIR}/GeneratedJITStubs.obj)
+ENDIF ()
index 4fc9cad1e732a6e079597db63ba4fa66b968c72a..80af4b6d506d551a096bc272b2ea3ece4716fae6 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+# Copyright (C) 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -27,7 +27,6 @@
 VPATH = \
     $(JavaScriptCore) \
     $(JavaScriptCore)/parser \
-    $(JavaScriptCore)/pcre \
     $(JavaScriptCore)/docs \
     $(JavaScriptCore)/runtime \
     $(JavaScriptCore)/interpreter \
@@ -36,19 +35,31 @@ VPATH = \
 
 .PHONY : all
 all : \
+    ArrayConstructor.lut.h \
     ArrayPrototype.lut.h \
-    chartables.c \
+    BooleanPrototype.lut.h \
+    DateConstructor.lut.h \
     DatePrototype.lut.h \
-    Grammar.cpp \
+    ErrorPrototype.lut.h \
+    HeaderDetection.h \
     JSONObject.lut.h \
+    JavaScriptCore.JSVALUE32_64.exp \
+    JavaScriptCore.JSVALUE64.exp \
+    JSGlobalObject.lut.h \
+    KeywordLookup.h \
     Lexer.lut.h \
     MathObject.lut.h \
     NumberConstructor.lut.h \
+    NumberPrototype.lut.h \
+    ObjectConstructor.lut.h \
+    ObjectPrototype.lut.h \
     RegExpConstructor.lut.h \
+    RegExpPrototype.lut.h \
+    RegExpJitTables.h \
     RegExpObject.lut.h \
+    StringConstructor.lut.h \
     StringPrototype.lut.h \
     docs/bytecode.html \
-    RegExpJitTables.h \
 #
 
 # lookup tables for classes
@@ -58,24 +69,38 @@ all : \
 Lexer.lut.h: create_hash_table Keywords.table
        $^ > $@
 
-# JavaScript language grammar
-
-Grammar.cpp: Grammar.y
-       bison -d -p jscyy $< -o $@ > bison_out.txt 2>&1
-       perl -p -e 'END { if ($$conflict) { unlink "Grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt
-       touch Grammar.cpp.h
-       touch Grammar.hpp
-       cat Grammar.cpp.h Grammar.hpp > Grammar.h
-       rm -f Grammar.cpp.h Grammar.hpp bison_out.txt
-
-# character tables for PCRE
-
-chartables.c : dftables
-       $^ $@
-
 docs/bytecode.html: make-bytecode-docs.pl Interpreter.cpp 
        perl $^ $@
 
-#character tables for Yarr
+# character tables for Yarr
+
 RegExpJitTables.h: create_regex_tables
        python $^ > $@
+
+KeywordLookup.h: KeywordLookupGenerator.py Keywords.table
+       python $^ > $@
+
+# export files
+
+JavaScriptCore.JSVALUE32_64.exp: JavaScriptCore.exp JavaScriptCore.JSVALUE32_64only.exp
+       cat $^ > $@
+
+JavaScriptCore.JSVALUE64.exp: JavaScriptCore.exp JavaScriptCore.JSVALUE64only.exp
+       cat $^ > $@
+
+
+# header detection
+
+ifeq ($(OS),MACOS)
+
+HeaderDetection.h : DerivedSources.make /System/Library/CoreServices/SystemVersion.plist
+       rm -f $@
+       echo "/* This is a generated file. Do not edit. */" > $@
+       if [ -f $(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/pthread_machdep.h ]; then echo "#define HAVE_PTHREAD_MACHDEP_H 1" >> $@; else echo >> $@; fi
+
+else
+
+HeaderDetection.h :
+       echo > $@
+
+endif
index 7c5aad8de3bd090973d8853f82e16cb1f949ee99..09896051498e4427a5b9ec2795458c2ac11f052b 100644 (file)
@@ -14,22 +14,29 @@ CONFIG(standalone_package) {
 }
 
 LUT_FILES += \
+    runtime/ArrayConstructor.cpp \
     runtime/ArrayPrototype.cpp \
+    runtime/BooleanPrototype.cpp \
+    runtime/DateConstructor.cpp \
     runtime/DatePrototype.cpp \
+    runtime/ErrorPrototype.cpp \
+    runtime/JSGlobalObject.cpp \
     runtime/JSONObject.cpp \
     runtime/MathObject.cpp \
     runtime/NumberConstructor.cpp \
+    runtime/NumberPrototype.cpp \
+    runtime/ObjectConstructor.cpp \
+    runtime/ObjectPrototype.cpp \
     runtime/RegExpConstructor.cpp \
     runtime/RegExpObject.cpp \
-    runtime/StringPrototype.cpp
+    runtime/RegExpPrototype.cpp \
+    runtime/StringConstructor.cpp \
+    runtime/StringPrototype.cpp \
 
 KEYWORDLUT_FILES += \
     parser/Keywords.table
 
-JSCBISON += \
-    parser/Grammar.y
-
-RVCT_STUB_FILES += \
+JIT_STUB_FILES += \
     jit/JITStubs.cpp
 
 defineTest(addExtraCompiler) {
@@ -68,30 +75,23 @@ keywordlut.commands = perl $$keywordlut.wkScript ${QMAKE_FILE_NAME} -i > ${QMAKE
 keywordlut.depends = ${QMAKE_FILE_NAME}
 addExtraCompiler(keywordlut)
 
-# GENERATOR 2: bison grammar
-jscbison.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.cpp
-jscbison.input = JSCBISON
-jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c && $(MOVE) $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.h $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.h
-jscbison.depends = ${QMAKE_FILE_NAME}
-addExtraCompiler(jscbison)
-
-# GENERATOR 3: JIT Stub functions for RVCT
+# GENERATOR 2-A: JIT Stub functions for RVCT
 rvctstubs.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Generated${QMAKE_FILE_BASE}_RVCT.h
 rvctstubs.wkScript = $$PWD/create_jit_stubs
 rvctstubs.commands = perl -i $$rvctstubs.wkScript --prefix RVCT ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
 rvctstubs.depends = ${QMAKE_FILE_NAME}
-rvctstubs.input = RVCT_STUB_FILES
+rvctstubs.input = JIT_STUB_FILES
 rvctstubs.CONFIG += no_link
 addExtraCompiler(rvctstubs)
 
-# GENERATOR: "chartables.c": compile and execute the chartables generator (and add it to sources)
-win32-msvc*|wince*: PREPROCESSOR = "--preprocessor=\"$$QMAKE_CC /E\""
-ctgen.output = $$JSC_GENERATED_SOURCES_DIR/chartables.c
-ctgen.wkScript = $$PWD/pcre/dftables
-ctgen.input = ctgen.wkScript
-ctgen.commands = perl $$ctgen.wkScript ${QMAKE_FILE_OUT} $$PREPROCESSOR
-ctgen.clean = ${QMAKE_FILE_OUT} ${QMAKE_VAR_JSC_GENERATED_SOURCES_DIR}${QMAKE_FILE_BASE}
-addExtraCompiler(ctgen)
+# GENERATOR 2-B: JIT Stub functions for MSVC
+msvcstubs.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Generated${QMAKE_FILE_BASE}_MSVC.asm
+msvcstubs.wkScript = $$PWD/create_jit_stubs
+msvcstubs.commands = perl -i $$msvcstubs.wkScript --prefix MSVC ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
+msvcstubs.depends = ${QMAKE_FILE_NAME}
+msvcstubs.input = JIT_STUB_FILES
+msvcstubs.CONFIG += no_link
+addExtraCompiler(msvcstubs)
 
 #GENERATOR: "RegExpJitTables.h": tables used by Yarr
 retgen.output = $$JSC_GENERATED_SOURCES_DIR/RegExpJitTables.h
@@ -99,3 +99,10 @@ retgen.wkScript = $$PWD/create_regex_tables
 retgen.input = retgen.wkScript
 retgen.commands = python $$retgen.wkScript > ${QMAKE_FILE_OUT}
 addExtraCompiler(retgen)
+
+#GENERATOR: "KeywordLookup.h": decision tree used by the lexer
+klgen.output = $$JSC_GENERATED_SOURCES_DIR/KeywordLookup.h
+klgen.wkScript = $$PWD/KeywordLookupGenerator.py 
+klgen.input = KEYWORDLUT_FILES
+klgen.commands = python $$klgen.wkScript ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT}
+addExtraCompiler(klgen)
diff --git a/ForwardingHeaders/JavaScriptCore/APIShims.h b/ForwardingHeaders/JavaScriptCore/APIShims.h
new file mode 100644 (file)
index 0000000..92e712a
--- /dev/null
@@ -0,0 +1 @@
+#include <JavaScriptCore/API/APIShims.h>
index cd93c1bc378b465d9d43678ac0858e42be1526ef..c710d2aba427dee3ca4c429c426e3d89095f706f 100644 (file)
-javascriptcore_cppflags += \
-       -I$(srcdir)/JavaScriptCore \
-       -I$(srcdir)/JavaScriptCore/API \
-       -I$(srcdir)/JavaScriptCore/ForwardingHeaders \
-       -I$(srcdir)/JavaScriptCore/interpreter \
-       -I$(srcdir)/JavaScriptCore/bytecode \
-       -I$(srcdir)/JavaScriptCore/bytecompiler \
-       -I$(srcdir)/JavaScriptCore/debugger \
-       -I$(srcdir)/JavaScriptCore/jit \
-       -I$(srcdir)/JavaScriptCore/pcre \
-       -I$(srcdir)/JavaScriptCore/profiler \
-       -I$(srcdir)/JavaScriptCore/runtime \
-       -I$(srcdir)/JavaScriptCore/jit \
-       -I$(srcdir)/JavaScriptCore/assembler \
-       -I$(srcdir)/JavaScriptCore/wtf \
-       -I$(srcdir)/JavaScriptCore/wtf/text \
-       -I$(srcdir)/JavaScriptCore/wtf/unicode \
-       -I$(srcdir)/JavaScriptCore/yarr \
-       -I$(top_builddir)/JavaScriptCore \
-       -I$(top_builddir)/JavaScriptCore/pcre \
-       -I$(top_builddir)/JavaScriptCore/parser \
-       -I$(top_builddir)/JavaScriptCore/runtime
-
-javascriptcore_h_api += \
-       JavaScriptCore/API/JSBase.h \
-       JavaScriptCore/API/JSContextRef.h \
-       JavaScriptCore/API/JSObjectRef.h \
-       JavaScriptCore/API/JSStringRef.h \
-       JavaScriptCore/API/JSStringRefBSTR.h \
-       JavaScriptCore/API/JSStringRefCF.h \
-       JavaScriptCore/API/JSValueRef.h \
-       JavaScriptCore/API/JavaScript.h \
-       JavaScriptCore/API/JavaScriptCore.h \
-       JavaScriptCore/API/WebKitAvailability.h
-
-javascriptcore_built_nosources += \
-       DerivedSources/Lexer.lut.h \
-       JavaScriptCore/RegExpJitTables.h \
-       JavaScriptCore/runtime/ArrayPrototype.lut.h \
-       JavaScriptCore/runtime/DatePrototype.lut.h \
-       JavaScriptCore/runtime/JSONObject.lut.h \
-       JavaScriptCore/runtime/MathObject.lut.h \
-       JavaScriptCore/runtime/NumberConstructor.lut.h \
-       JavaScriptCore/runtime/RegExpConstructor.lut.h \
-       JavaScriptCore/runtime/RegExpObject.lut.h \
-       JavaScriptCore/runtime/StringPrototype.lut.h \
-       JavaScriptCore/pcre/chartables.c
-
-javascriptcore_sources += \
-       JavaScriptCore/API/APICast.h \
-       JavaScriptCore/API/APIShims.h \
-       JavaScriptCore/API/JSBase.cpp \
-       JavaScriptCore/API/JSBasePrivate.h \
-       JavaScriptCore/API/JSCallbackConstructor.cpp \
-       JavaScriptCore/API/JSCallbackConstructor.h \
-       JavaScriptCore/API/JSCallbackFunction.cpp \
-       JavaScriptCore/API/JSCallbackFunction.h \
-       JavaScriptCore/API/JSCallbackObject.cpp \
-       JavaScriptCore/API/JSCallbackObject.h \
-       JavaScriptCore/API/JSCallbackObjectFunctions.h \
-       JavaScriptCore/API/JSClassRef.cpp \
-       JavaScriptCore/API/JSClassRef.h \
-       JavaScriptCore/API/JSContextRef.cpp \
-       JavaScriptCore/API/JSContextRefPrivate.h \
-       JavaScriptCore/API/JSObjectRef.cpp \
-       JavaScriptCore/API/JSRetainPtr.h \
-       JavaScriptCore/API/JSStringRef.cpp \
-       JavaScriptCore/API/JSValueRef.cpp \
-       JavaScriptCore/API/OpaqueJSString.cpp \
-       JavaScriptCore/API/OpaqueJSString.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSBase.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSContextRef.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRef.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSRetainPtr.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRef.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRefCF.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSValueRef.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScript.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScriptCore.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/OpaqueJSString.h \
-       JavaScriptCore/ForwardingHeaders/JavaScriptCore/WebKitAvailability.h \
-       JavaScriptCore/JavaScriptCorePrefix.h \
-       JavaScriptCore/jit/ExecutableAllocator.h \
-       JavaScriptCore/jit/JIT.cpp \
-       JavaScriptCore/jit/JITOpcodes.cpp \
-       JavaScriptCore/jit/JITOpcodes32_64.cpp \
-       JavaScriptCore/jit/JITCall.cpp \
-       JavaScriptCore/jit/JITCode.h \
-       JavaScriptCore/jit/JITPropertyAccess.cpp \
-       JavaScriptCore/jit/JITPropertyAccess32_64.cpp \
-       JavaScriptCore/jit/JITArithmetic.cpp \
-       JavaScriptCore/jit/JITArithmetic32_64.cpp \
-       JavaScriptCore/jit/ExecutableAllocator.cpp \
-       JavaScriptCore/jit/JIT.h \
-       JavaScriptCore/jit/JITInlineMethods.h \
-       JavaScriptCore/jit/JITStubs.cpp \
-       JavaScriptCore/jit/JITStubs.h \
-       JavaScriptCore/jit/JITStubCall.h \
-       JavaScriptCore/jit/JSInterfaceJIT.h \
-       JavaScriptCore/jit/SpecializedThunkJIT.h \
-       JavaScriptCore/jit/ThunkGenerators.cpp \
-       JavaScriptCore/jit/ThunkGenerators.h \
-       JavaScriptCore/bytecode/StructureStubInfo.cpp \
-       JavaScriptCore/bytecode/StructureStubInfo.h \
-       JavaScriptCore/bytecode/CodeBlock.cpp \
-       JavaScriptCore/bytecode/CodeBlock.h \
-       JavaScriptCore/bytecode/JumpTable.cpp \
-       JavaScriptCore/bytecode/JumpTable.h \
-       JavaScriptCore/bytecode/EvalCodeCache.h \
-       JavaScriptCore/bytecode/Instruction.h \
-       JavaScriptCore/bytecompiler/Label.h \
-       JavaScriptCore/interpreter/Interpreter.cpp \
-       JavaScriptCore/interpreter/Interpreter.h \
-       JavaScriptCore/bytecode/Opcode.cpp \
-       JavaScriptCore/bytecode/Opcode.h \
-       JavaScriptCore/interpreter/Register.h \
-       JavaScriptCore/bytecompiler/RegisterID.h \
-       JavaScriptCore/bytecode/SamplingTool.cpp \
-       JavaScriptCore/bytecode/SamplingTool.h \
-       JavaScriptCore/config.h \
-       JavaScriptCore/debugger/DebuggerActivation.cpp \
-       JavaScriptCore/debugger/DebuggerActivation.h \
-       JavaScriptCore/debugger/DebuggerCallFrame.cpp \
-       JavaScriptCore/debugger/DebuggerCallFrame.h \
-       JavaScriptCore/icu/unicode/parseerr.h \
-       JavaScriptCore/icu/unicode/platform.h \
-       JavaScriptCore/icu/unicode/putil.h \
-       JavaScriptCore/icu/unicode/uchar.h \
-       JavaScriptCore/icu/unicode/ucnv.h \
-       JavaScriptCore/icu/unicode/ucnv_err.h \
-       JavaScriptCore/icu/unicode/ucol.h \
-       JavaScriptCore/icu/unicode/uconfig.h \
-       JavaScriptCore/icu/unicode/uenum.h \
-       JavaScriptCore/icu/unicode/uiter.h \
-       JavaScriptCore/icu/unicode/uloc.h \
-       JavaScriptCore/icu/unicode/umachine.h \
-       JavaScriptCore/icu/unicode/unorm.h \
-       JavaScriptCore/icu/unicode/urename.h \
-       JavaScriptCore/icu/unicode/uset.h \
-       JavaScriptCore/icu/unicode/ustring.h \
-       JavaScriptCore/icu/unicode/utf.h \
-       JavaScriptCore/icu/unicode/utf16.h \
-       JavaScriptCore/icu/unicode/utf8.h \
-       JavaScriptCore/icu/unicode/utf_old.h \
-       JavaScriptCore/icu/unicode/utypes.h \
-       JavaScriptCore/icu/unicode/uversion.h \
-       JavaScriptCore/assembler/ARMAssembler.h \
-       JavaScriptCore/assembler/ARMAssembler.cpp \
-       JavaScriptCore/assembler/X86Assembler.h \
-       JavaScriptCore/assembler/AbstractMacroAssembler.h \
-       JavaScriptCore/assembler/AssemblerBuffer.h \
-       JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
-       JavaScriptCore/assembler/CodeLocation.h \
-       JavaScriptCore/assembler/LinkBuffer.h \
-       JavaScriptCore/assembler/MacroAssembler.h \
-       JavaScriptCore/assembler/MacroAssemblerARM.h \
-       JavaScriptCore/assembler/MacroAssemblerARM.cpp \
-       JavaScriptCore/assembler/MacroAssemblerCodeRef.h \
-       JavaScriptCore/assembler/MacroAssemblerX86.h \
-       JavaScriptCore/assembler/MacroAssemblerX86_64.h \
-       JavaScriptCore/assembler/MacroAssemblerX86Common.h \
-       JavaScriptCore/assembler/RepatchBuffer.h \
-       JavaScriptCore/os-win32/stdbool.h \
-       JavaScriptCore/os-win32/stdint.h \
-       JavaScriptCore/pcre/pcre.h \
-       JavaScriptCore/pcre/pcre_compile.cpp \
-       JavaScriptCore/pcre/pcre_exec.cpp \
-       JavaScriptCore/pcre/pcre_internal.h \
-       JavaScriptCore/pcre/pcre_tables.cpp \
-       JavaScriptCore/pcre/pcre_ucp_searchfuncs.cpp \
-       JavaScriptCore/pcre/pcre_xclass.cpp \
-       JavaScriptCore/pcre/ucpinternal.h \
-       JavaScriptCore/profiler/CallIdentifier.h \
-       JavaScriptCore/profiler/Profile.cpp \
-       JavaScriptCore/profiler/Profile.h \
-       JavaScriptCore/profiler/ProfileGenerator.cpp \
-       JavaScriptCore/profiler/ProfileGenerator.h \
-       JavaScriptCore/profiler/ProfileNode.cpp \
-       JavaScriptCore/profiler/ProfileNode.h \
-       JavaScriptCore/profiler/Profiler.cpp \
-       JavaScriptCore/profiler/Profiler.h \
-       JavaScriptCore/interpreter/CachedCall.h \
-       JavaScriptCore/interpreter/CallFrame.cpp \
-       JavaScriptCore/interpreter/CallFrame.h \
-       JavaScriptCore/interpreter/CallFrameClosure.h \
-       JavaScriptCore/runtime/ExceptionHelpers.cpp \
-       JavaScriptCore/runtime/ExceptionHelpers.h \
-       JavaScriptCore/runtime/Executable.cpp \
-       JavaScriptCore/runtime/Executable.h \
-       JavaScriptCore/runtime/InitializeThreading.cpp \
-       JavaScriptCore/runtime/InitializeThreading.h \
-       JavaScriptCore/runtime/JSActivation.cpp \
-       JavaScriptCore/runtime/JSActivation.h \
-       JavaScriptCore/runtime/JSByteArray.cpp \
-       JavaScriptCore/runtime/JSByteArray.h \
-       JavaScriptCore/runtime/JSGlobalData.cpp \
-       JavaScriptCore/runtime/JSGlobalData.h \
-       JavaScriptCore/runtime/JSNotAnObject.cpp \
-       JavaScriptCore/runtime/JSNotAnObject.h \
-       JavaScriptCore/runtime/JSONObject.cpp \
-       JavaScriptCore/runtime/JSONObject.h \
-       JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
-       JavaScriptCore/runtime/JSPropertyNameIterator.h \
-       JavaScriptCore/runtime/JSStringBuilder.h \
-       JavaScriptCore/runtime/JSZombie.h \
-       JavaScriptCore/runtime/LiteralParser.cpp \
-       JavaScriptCore/runtime/LiteralParser.h \
-       JavaScriptCore/runtime/MarkStack.cpp \
-       JavaScriptCore/runtime/MarkStack.h \
-       JavaScriptCore/runtime/NumericStrings.h \
-       JavaScriptCore/runtime/PropertyDescriptor.h \
-       JavaScriptCore/runtime/PropertyDescriptor.cpp \
-       JavaScriptCore/runtime/SmallStrings.cpp \
-       JavaScriptCore/runtime/SmallStrings.h \
-       JavaScriptCore/runtime/StringBuilder.h \
-       JavaScriptCore/runtime/Structure.cpp \
-       JavaScriptCore/runtime/Structure.h \
-       JavaScriptCore/runtime/StructureChain.cpp \
-       JavaScriptCore/runtime/StructureChain.h \
-       JavaScriptCore/runtime/StructureTransitionTable.h \
-       JavaScriptCore/runtime/Terminator.h \
-       JavaScriptCore/runtime/TimeoutChecker.cpp \
-       JavaScriptCore/runtime/TimeoutChecker.h \
-       JavaScriptCore/runtime/JSTypeInfo.h \
-       JavaScriptCore/runtime/WeakGCMap.h \
-       JavaScriptCore/runtime/WeakGCPtr.h \
-       JavaScriptCore/wtf/ASCIICType.h \
-       JavaScriptCore/wtf/AVLTree.h \
-       JavaScriptCore/wtf/AlwaysInline.h \
-       JavaScriptCore/wtf/Assertions.cpp \
-       JavaScriptCore/wtf/Assertions.h \
-       JavaScriptCore/wtf/Atomics.h \
-       JavaScriptCore/wtf/ByteArray.cpp \
-       JavaScriptCore/wtf/ByteArray.h \
-       JavaScriptCore/wtf/CrossThreadRefCounted.h \
-       JavaScriptCore/wtf/CurrentTime.cpp \
-       JavaScriptCore/wtf/CurrentTime.h \
-       JavaScriptCore/wtf/DateMath.cpp \
-       JavaScriptCore/wtf/DateMath.h \
-       JavaScriptCore/wtf/Deque.h \
-       JavaScriptCore/wtf/DisallowCType.h \
-       JavaScriptCore/wtf/Forward.h \
-       JavaScriptCore/wtf/GetPtr.h \
-       JavaScriptCore/wtf/HashCountedSet.h \
-       JavaScriptCore/wtf/HashFunctions.h \
-       JavaScriptCore/wtf/HashIterators.h \
-       JavaScriptCore/wtf/HashMap.h \
-       JavaScriptCore/wtf/HashSet.h \
-       JavaScriptCore/wtf/HashTable.cpp \
-       JavaScriptCore/wtf/HashTable.h \
-       JavaScriptCore/wtf/HashTraits.h \
-       JavaScriptCore/wtf/ListHashSet.h \
-       JavaScriptCore/wtf/ListRefPtr.h \
-       JavaScriptCore/wtf/Locker.h \
-       JavaScriptCore/wtf/MD5.cpp \
-       JavaScriptCore/wtf/MD5.h \
-       JavaScriptCore/wtf/MainThread.cpp \
-       JavaScriptCore/wtf/MainThread.h \
-       JavaScriptCore/wtf/MathExtras.h \
-       JavaScriptCore/wtf/MessageQueue.h \
-       JavaScriptCore/wtf/Noncopyable.h \
-       JavaScriptCore/wtf/NotFound.h \
-       JavaScriptCore/wtf/OwnArrayPtr.h \
-       JavaScriptCore/wtf/OwnFastMallocPtr.h \
-       JavaScriptCore/wtf/OwnPtr.h \
-       JavaScriptCore/wtf/OwnPtrCommon.h \
-       JavaScriptCore/wtf/PassOwnPtr.h \
-       JavaScriptCore/wtf/PassRefPtr.h \
-       JavaScriptCore/wtf/Platform.h \
-       JavaScriptCore/wtf/PossiblyNull.h \
-       JavaScriptCore/wtf/RandomNumber.cpp \
-       JavaScriptCore/wtf/RandomNumber.h \
-       JavaScriptCore/wtf/RandomNumberSeed.h \
-       JavaScriptCore/wtf/RefCounted.h \
-       JavaScriptCore/wtf/RefCountedLeakCounter.cpp \
-       JavaScriptCore/wtf/RefCountedLeakCounter.h \
-       JavaScriptCore/wtf/RefPtr.h \
-       JavaScriptCore/wtf/RefPtrHashMap.h \
-       JavaScriptCore/wtf/RetainPtr.h \
-       JavaScriptCore/wtf/SegmentedVector.h \
-       JavaScriptCore/wtf/StaticConstructors.h \
-       JavaScriptCore/wtf/StdLibExtras.h \
-       JavaScriptCore/wtf/StringExtras.h \
-       JavaScriptCore/wtf/StringHashFunctions.h \
-       JavaScriptCore/wtf/TCPackedCache.h \
-       JavaScriptCore/wtf/TCPageMap.h \
-       JavaScriptCore/wtf/TCSpinLock.h \
-       JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp \
-       JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h \
-       JavaScriptCore/wtf/Threading.cpp \
-       JavaScriptCore/wtf/Threading.h \
-       JavaScriptCore/wtf/ThreadingPrimitives.h \
-       JavaScriptCore/wtf/ThreadingPthreads.cpp \
-       JavaScriptCore/wtf/ThreadSafeShared.h \
-       JavaScriptCore/wtf/ThreadSpecific.h \
-       JavaScriptCore/wtf/TypeTraits.cpp \
-       JavaScriptCore/wtf/TypeTraits.h \
-       JavaScriptCore/wtf/UnusedParam.h \
-       JavaScriptCore/wtf/ValueCheck.h \
-       JavaScriptCore/wtf/Vector.h \
-       JavaScriptCore/wtf/VectorTraits.h \
-       JavaScriptCore/wtf/WTFThreadData.cpp \
-       JavaScriptCore/wtf/WTFThreadData.h \
-       JavaScriptCore/wtf/gobject/GOwnPtr.cpp \
-       JavaScriptCore/wtf/gobject/GOwnPtr.h \
-       JavaScriptCore/wtf/gobject/GRefPtr.cpp \
-       JavaScriptCore/wtf/gobject/GRefPtr.h \
-       JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \
-       JavaScriptCore/wtf/gtk/ThreadingGtk.cpp \
-       JavaScriptCore/wtf/text/AtomicString.cpp \
-       JavaScriptCore/wtf/text/AtomicString.h \
-       JavaScriptCore/wtf/text/AtomicStringImpl.h \
-       JavaScriptCore/wtf/text/CString.cpp \
-       JavaScriptCore/wtf/text/CString.h \
-       JavaScriptCore/wtf/text/StringHash.h \
-       JavaScriptCore/wtf/text/StringImpl.cpp \
-       JavaScriptCore/wtf/text/StringImpl.h \
-       JavaScriptCore/wtf/text/StringStatics.cpp \
-       JavaScriptCore/wtf/text/WTFString.cpp \
-       JavaScriptCore/wtf/text/WTFString.h \
-       JavaScriptCore/wtf/unicode/Collator.h \
-       JavaScriptCore/wtf/unicode/CollatorDefault.cpp \
-       JavaScriptCore/wtf/unicode/UTF8.cpp \
-       JavaScriptCore/wtf/unicode/UTF8.h \
-       JavaScriptCore/wtf/unicode/Unicode.h
+include $(srcdir)/Source/JavaScriptCore/GNUmakefile.list.am
 
-if TARGET_WIN32
-javascriptcore_sources += \
-       JavaScriptCore/wtf/ThreadSpecificWin.cpp \
-       JavaScriptCore/jit/ExecutableAllocatorWin.cpp \
-       JavaScriptCore/runtime/MarkStackWin.cpp
-else
-javascriptcore_sources += \
-       JavaScriptCore/jit/ExecutableAllocatorPosix.cpp \
-       JavaScriptCore/runtime/MarkStackPosix.cpp
-endif
+lib_LTLIBRARIES += \
+       libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la
 
-# ----
-# icu unicode backend
-# ----
-if USE_ICU_UNICODE
-javascriptcore_sources += \
-       JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp \
-       JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
-endif # USE_ICU_UNICODE
+# We are going to make everything public for now. When
+# https://bugs.webkit.org/show_bug.cgi?id=27551 is fixed we'll able to
+# simply rely on the usual symbol visibility flags.
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_LDFLAGS = \
+       -version-info @LIBWEBKITGTK_VERSION@ \
+       $(no_undefined)
 
-# ----
-# glib unicode backend
-# ----
-if USE_GLIB_UNICODE
-javascriptcore_sources += \
-       JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h \
-       JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp \
-       JavaScriptCore/wtf/unicode/glib/UnicodeMacrosFromICU.h
-endif
+nodist_EXTRA_libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
+       $(javascriptcore_built_nosources)
 
-javascriptcore_sources += \
-       JavaScriptCore/wtf/VMTags.h \
-       JavaScriptCore/yarr/RegexCompiler.cpp \
-       JavaScriptCore/yarr/RegexCompiler.h \
-       JavaScriptCore/yarr/RegexInterpreter.cpp \
-       JavaScriptCore/yarr/RegexInterpreter.h \
-       JavaScriptCore/yarr/RegexJIT.cpp \
-       JavaScriptCore/yarr/RegexJIT.h \
-       JavaScriptCore/yarr/RegexParser.h \
-       JavaScriptCore/yarr/RegexPattern.h
+nodist_libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
+       $(javascriptcore_built_sources)
 
-javascriptcore_sources += \
-       JavaScriptCore/interpreter/RegisterFile.cpp \
-       JavaScriptCore/interpreter/RegisterFile.h \
-       JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \
-       JavaScriptCore/bytecompiler/BytecodeGenerator.h \
-       JavaScriptCore/bytecompiler/NodesCodegen.cpp \
-       JavaScriptCore/bytecompiler/LabelScope.h \
-       JavaScriptCore/debugger/Debugger.cpp \
-       JavaScriptCore/debugger/Debugger.h \
-       JavaScriptCore/parser/Lexer.cpp \
-       JavaScriptCore/parser/Lexer.h \
-       JavaScriptCore/parser/NodeConstructors.h \
-       JavaScriptCore/parser/NodeInfo.h \
-       JavaScriptCore/parser/Nodes.cpp \
-       JavaScriptCore/parser/Nodes.h \
-       JavaScriptCore/parser/Parser.cpp \
-       JavaScriptCore/parser/Parser.h \
-       JavaScriptCore/parser/ParserArena.cpp \
-       JavaScriptCore/parser/ParserArena.h \
-       JavaScriptCore/parser/ResultType.h \
-       JavaScriptCore/parser/SourceCode.h \
-       JavaScriptCore/parser/SourceProvider.h \
-       JavaScriptCore/runtime/ArgList.cpp \
-       JavaScriptCore/runtime/ArgList.h \
-       JavaScriptCore/runtime/Arguments.cpp \
-       JavaScriptCore/runtime/Arguments.h \
-       JavaScriptCore/runtime/ArrayConstructor.cpp \
-       JavaScriptCore/runtime/ArrayConstructor.h \
-       JavaScriptCore/runtime/ArrayPrototype.cpp \
-       JavaScriptCore/runtime/ArrayPrototype.h \
-       JavaScriptCore/runtime/BatchedTransitionOptimizer.h \
-       JavaScriptCore/runtime/BooleanConstructor.cpp \
-       JavaScriptCore/runtime/BooleanConstructor.h \
-       JavaScriptCore/runtime/BooleanObject.cpp \
-       JavaScriptCore/runtime/BooleanObject.h \
-       JavaScriptCore/runtime/BooleanPrototype.cpp \
-       JavaScriptCore/runtime/BooleanPrototype.h \
-       JavaScriptCore/runtime/CallData.cpp \
-       JavaScriptCore/runtime/CallData.h \
-       JavaScriptCore/runtime/ClassInfo.h \
-       JavaScriptCore/runtime/Collector.cpp \
-       JavaScriptCore/runtime/Collector.h \
-       JavaScriptCore/runtime/CollectorHeapIterator.h \
-       JavaScriptCore/runtime/CommonIdentifiers.cpp \
-       JavaScriptCore/runtime/CommonIdentifiers.h \
-       JavaScriptCore/runtime/Completion.h \
-       JavaScriptCore/runtime/ConstructData.cpp \
-       JavaScriptCore/runtime/ConstructData.h \
-       JavaScriptCore/runtime/DateConstructor.cpp \
-       JavaScriptCore/runtime/DateConstructor.h \
-       JavaScriptCore/runtime/DateConversion.cpp \
-       JavaScriptCore/runtime/DateConversion.h \
-       JavaScriptCore/runtime/DateInstance.cpp \
-       JavaScriptCore/runtime/DateInstance.h \
-       JavaScriptCore/runtime/DateInstanceCache.h \
-       JavaScriptCore/runtime/DatePrototype.cpp \
-       JavaScriptCore/runtime/DatePrototype.h \
-       JavaScriptCore/runtime/Error.cpp \
-       JavaScriptCore/runtime/Error.h \
-       JavaScriptCore/runtime/ErrorConstructor.cpp \
-       JavaScriptCore/runtime/ErrorConstructor.h \
-       JavaScriptCore/runtime/ErrorInstance.cpp \
-       JavaScriptCore/runtime/ErrorInstance.h \
-       JavaScriptCore/runtime/ErrorPrototype.cpp \
-       JavaScriptCore/runtime/ErrorPrototype.h \
-       JavaScriptCore/runtime/FunctionConstructor.cpp \
-       JavaScriptCore/runtime/FunctionConstructor.h \
-       JavaScriptCore/runtime/FunctionPrototype.cpp \
-       JavaScriptCore/runtime/FunctionPrototype.h \
-       JavaScriptCore/runtime/GetterSetter.cpp \
-       JavaScriptCore/runtime/GetterSetter.h \
-       JavaScriptCore/runtime/GlobalEvalFunction.cpp \
-       JavaScriptCore/runtime/GlobalEvalFunction.h \
-       JavaScriptCore/runtime/Identifier.cpp \
-       JavaScriptCore/runtime/Identifier.h \
-       JavaScriptCore/runtime/InternalFunction.cpp \
-       JavaScriptCore/runtime/InternalFunction.h \
-       JavaScriptCore/runtime/Completion.cpp \
-       JavaScriptCore/runtime/JSArray.cpp \
-       JavaScriptCore/runtime/JSArray.h \
-       JavaScriptCore/runtime/JSAPIValueWrapper.cpp \
-       JavaScriptCore/runtime/JSAPIValueWrapper.h \
-       JavaScriptCore/runtime/JSCell.cpp \
-       JavaScriptCore/runtime/JSCell.h \
-       JavaScriptCore/runtime/JSFunction.cpp \
-       JavaScriptCore/runtime/JSFunction.h \
-       JavaScriptCore/runtime/JSGlobalObject.cpp \
-       JavaScriptCore/runtime/JSGlobalObject.h \
-       JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp \
-       JavaScriptCore/runtime/JSGlobalObjectFunctions.h \
-       JavaScriptCore/runtime/JSImmediate.cpp \
-       JavaScriptCore/runtime/JSImmediate.h \
-       JavaScriptCore/runtime/JSLock.cpp \
-       JavaScriptCore/runtime/JSLock.h \
-       JavaScriptCore/runtime/JSNumberCell.cpp \
-       JavaScriptCore/runtime/JSNumberCell.h \
-       JavaScriptCore/runtime/JSObject.cpp \
-       JavaScriptCore/runtime/JSObject.h \
-       JavaScriptCore/runtime/JSStaticScopeObject.cpp \
-       JavaScriptCore/runtime/JSStaticScopeObject.h \
-       JavaScriptCore/runtime/JSString.cpp \
-       JavaScriptCore/runtime/JSString.h \
-       JavaScriptCore/runtime/JSType.h \
-       JavaScriptCore/runtime/JSValue.cpp \
-       JavaScriptCore/runtime/JSValue.h \
-       JavaScriptCore/runtime/JSVariableObject.cpp \
-       JavaScriptCore/runtime/JSVariableObject.h \
-       JavaScriptCore/runtime/JSWrapperObject.cpp \
-       JavaScriptCore/runtime/JSWrapperObject.h \
-       JavaScriptCore/runtime/Lookup.cpp \
-       JavaScriptCore/runtime/Lookup.h \
-       JavaScriptCore/runtime/MathObject.cpp \
-       JavaScriptCore/runtime/MathObject.h \
-       JavaScriptCore/runtime/NativeErrorConstructor.cpp \
-       JavaScriptCore/runtime/NativeErrorConstructor.h \
-       JavaScriptCore/runtime/NativeErrorPrototype.cpp \
-       JavaScriptCore/runtime/NativeErrorPrototype.h \
-       JavaScriptCore/runtime/NativeFunctionWrapper.h \
-       JavaScriptCore/runtime/NumberConstructor.cpp \
-       JavaScriptCore/runtime/NumberConstructor.h \
-       JavaScriptCore/runtime/NumberObject.cpp \
-       JavaScriptCore/runtime/NumberObject.h \
-       JavaScriptCore/runtime/NumberPrototype.cpp \
-       JavaScriptCore/runtime/NumberPrototype.h \
-       JavaScriptCore/runtime/ObjectConstructor.cpp \
-       JavaScriptCore/runtime/ObjectConstructor.h \
-       JavaScriptCore/runtime/ObjectPrototype.cpp \
-       JavaScriptCore/runtime/ObjectPrototype.h \
-       JavaScriptCore/runtime/Operations.cpp \
-       JavaScriptCore/runtime/Operations.h \
-       JavaScriptCore/runtime/PropertyMapHashTable.h \
-       JavaScriptCore/runtime/PropertyNameArray.cpp \
-       JavaScriptCore/runtime/PropertyNameArray.h \
-       JavaScriptCore/runtime/PropertySlot.cpp \
-       JavaScriptCore/runtime/PropertySlot.h \
-       JavaScriptCore/runtime/Protect.h \
-       JavaScriptCore/runtime/PrototypeFunction.cpp \
-       JavaScriptCore/runtime/PrototypeFunction.h \
-       JavaScriptCore/runtime/PutPropertySlot.h \
-       JavaScriptCore/runtime/RegExp.cpp \
-       JavaScriptCore/runtime/RegExp.h \
-       JavaScriptCore/runtime/RegExpCache.cpp \
-       JavaScriptCore/runtime/RegExpCache.h \
-       JavaScriptCore/runtime/RegExpConstructor.cpp \
-       JavaScriptCore/runtime/RegExpConstructor.h \
-       JavaScriptCore/runtime/RegExpKey.h \
-       JavaScriptCore/runtime/RegExpMatchesArray.h \
-       JavaScriptCore/runtime/RegExpObject.cpp \
-       JavaScriptCore/runtime/RegExpObject.h \
-       JavaScriptCore/runtime/RegExpPrototype.cpp \
-       JavaScriptCore/runtime/RegExpPrototype.h \
-       JavaScriptCore/runtime/RopeImpl.cpp \
-       JavaScriptCore/runtime/RopeImpl.h \
-       JavaScriptCore/runtime/ScopeChain.cpp \
-       JavaScriptCore/runtime/ScopeChain.h \
-       JavaScriptCore/runtime/ScopeChainMark.h \
-       JavaScriptCore/runtime/StringConstructor.cpp \
-       JavaScriptCore/runtime/StringConstructor.h \
-       JavaScriptCore/runtime/StringObject.cpp \
-       JavaScriptCore/runtime/StringObject.h \
-       JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h \
-       JavaScriptCore/runtime/StringPrototype.cpp \
-       JavaScriptCore/runtime/StringPrototype.h \
-       JavaScriptCore/runtime/SymbolTable.h \
-       JavaScriptCore/runtime/Tracing.h \
-       JavaScriptCore/runtime/UString.cpp \
-       JavaScriptCore/runtime/UString.h \
-       JavaScriptCore/runtime/UStringImpl.h \
-       JavaScriptCore/runtime/WeakRandom.h \
-       JavaScriptCore/wtf/FastAllocBase.h \
-       JavaScriptCore/wtf/FastMalloc.cpp \
-       JavaScriptCore/wtf/FastMalloc.h \
-       JavaScriptCore/wtf/MallocZoneSupport.h \
-       JavaScriptCore/wtf/TCSystemAlloc.cpp \
-       JavaScriptCore/wtf/TCSystemAlloc.h \
-       JavaScriptCore/wtf/dtoa.cpp \
-       JavaScriptCore/wtf/dtoa.h
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_ladir = $(prefix)/include/webkit-@WEBKITGTK_API_VERSION@/JavaScriptCore
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_HEADERS = $(javascriptcore_h_api)
 
-javascriptcore_built_sources += \
-       DerivedSources/Grammar.cpp \
-       DerivedSources/Grammar.h
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOURCES = \
+       $(javascriptcore_sources)
 
-DerivedSources/Grammar.h: DerivedSources/Grammar.cpp;
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_LIBADD = \
+       $(UNICODE_LIBS) \
+       $(GLIB_LIBS) \
+       $(WINMM_LIBS) \
+       -lpthread
 
-DerivedSources/Grammar.cpp: $(srcdir)/JavaScriptCore/parser/Grammar.y
-       $(BISON) -d -p jscyy $(srcdir)/JavaScriptCore/parser/Grammar.y -o $@ > bison_out.txt 2>&1
-       $(PERL) -p -e 'END { if ($$conflict) { unlink "Grammar.cpp"; die; } } $$conflict ||= /conflict/' < bison_out.txt
-       cat $(GENSOURCES)/Grammar.hpp > $(GENSOURCES)/Grammar.h
-       rm -f $(GENSOURCES)/Grammar.hpp bison_out.txt
-
-DerivedSources/Lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/parser/Keywords.table
-       $(PERL) $^ > $@
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CXXFLAGS = \
+       $(global_cxxflags) \
+       $(libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CFLAGS)
 
-JavaScriptCore/%.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/%.cpp
-       $(PERL) $^ -i > $@
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CFLAGS = \
+       -fstrict-aliasing \
+       -O3 \
+       $(global_cflags) \
+       $(GLIB_CFLAGS) \
+       $(UNICODE_CFLAGS)
 
-JavaScriptCore/RegExpJitTables.h: $(srcdir)/JavaScriptCore/create_regex_tables
-       $(PYTHON) $(srcdir)/JavaScriptCore/create_regex_tables > $@
+libjavascriptcoregtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_CPPFLAGS = \
+       $(global_cppflags) \
+       $(javascriptcore_cppflags)
 
-JavaScriptCore/pcre/chartables.c: $(srcdir)/JavaScriptCore/pcre/dftables
-       $(PERL) $^ $@
+javascriptcore_cppflags += \
+       -I$(srcdir)/Source \
+       -I$(srcdir)/Source/JavaScriptCore \
+       -I$(srcdir)/Source/JavaScriptCore/API \
+       -I$(srcdir)/Source/JavaScriptCore/assembler \
+       -I$(srcdir)/Source/JavaScriptCore/bytecode \
+       -I$(srcdir)/Source/JavaScriptCore/bytecompiler \
+       -I$(srcdir)/Source/JavaScriptCore/heap \
+       -I$(srcdir)/Source/JavaScriptCore/debugger \
+       -I$(srcdir)/Source/JavaScriptCore/ForwardingHeaders \
+       -I$(srcdir)/Source/JavaScriptCore/interpreter \
+       -I$(srcdir)/Source/JavaScriptCore/jit \
+       -I$(srcdir)/Source/JavaScriptCore/jit \
+       -I$(srcdir)/Source/JavaScriptCore/parser \
+       -I$(srcdir)/Source/JavaScriptCore/profiler \
+       -I$(srcdir)/Source/JavaScriptCore/runtime \
+       -I$(srcdir)/Source/JavaScriptCore/wtf \
+       -I$(srcdir)/Source/JavaScriptCore/wtf \
+       -I$(srcdir)/Source/JavaScriptCore/wtf/gobject \
+       -I$(srcdir)/Source/JavaScriptCore/wtf/gtk \
+       -I$(srcdir)/Source/JavaScriptCore/wtf/text \
+       -I$(srcdir)/Source/JavaScriptCore/wtf/unicode \
+       -I$(srcdir)/Source/JavaScriptCore/yarr \
+       -I$(top_builddir)/Source/JavaScriptCore \
+       -I$(top_builddir)/Source/JavaScriptCore/parser \
+       -I$(top_builddir)/Source/JavaScriptCore/runtime
+
+Source/JavaScriptCore/Lexer.lut.h: $(srcdir)/Source/JavaScriptCore/create_hash_table $(srcdir)/Source/JavaScriptCore/parser/Keywords.table
+       $(AM_V_GEN)$(PERL) $^ > $@
+
+Source/JavaScriptCore/%.lut.h: $(srcdir)/Source/JavaScriptCore/create_hash_table $(srcdir)/Source/JavaScriptCore/%.cpp
+       $(AM_V_GEN)$(PERL) $^ -i > $@
+
+Source/JavaScriptCore/RegExpJitTables.h: $(srcdir)/Source/JavaScriptCore/create_regex_tables
+       $(AM_V_GEN)$(PYTHON) $^ > $@
+
+Source/JavaScriptCore/KeywordLookup.h: $(srcdir)/Source/JavaScriptCore/KeywordLookupGenerator.py $(srcdir)/Source/JavaScriptCore/parser/Keywords.table
+       $(AM_V_GEN)$(PYTHON) $^ > $@
+
+jsc: $(javascriptcore_built_nosources) Programs/jsc$(EXEEXT)
 
 bin_PROGRAMS += \
-       Programs/jsc
+       Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@$(EXEEXT)
 
 noinst_PROGRAMS += \
+       Programs/jsc \
        Programs/minidom
 
-# minidom
-Programs_minidom_SOURCES = \
-       JavaScriptCore/API/tests/JSNode.c \
-       JavaScriptCore/API/tests/JSNode.h \
-       JavaScriptCore/API/tests/JSNodeList.c \
-       JavaScriptCore/API/tests/JSNodeList.h \
-       JavaScriptCore/API/tests/Node.c \
-       JavaScriptCore/API/tests/Node.h \
-       JavaScriptCore/API/tests/NodeList.c \
-       JavaScriptCore/API/tests/NodeList.h \
-       JavaScriptCore/API/tests/minidom.c
-
 Programs_minidom_CPPFLAGS = \
        $(global_cppflags) \
        $(javascriptcore_cppflags)
@@ -597,58 +102,72 @@ Programs_minidom_CFLAGS = \
        $(GLOBALDEPS_CFLAGS)
 
 Programs_minidom_LDADD = \
-        libJavaScriptCore.la \
-        -lm \
-        -lstdc++
+       libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
+       $(WINMM_LIBS) \
+       -lm \
+       -lpthread \
+       -lstdc++
 
 Programs_minidom_LDFLAGS = \
        -no-install \
        -no-fast-install
 
 # jsc
-Programs_jsc_SOURCES = \
-       JavaScriptCore/jsc.cpp
+Programs/jsc$(EXEEXT): Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@$(EXEEXT)
+       $(AM_V_GEN)cp -f Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@$(EXEEXT) Programs/jsc$(EXEEXT)
+Programs_jsc_LDADD =
+Programs_jsc_SOURCES =
 
-Programs_jsc_CPPFLAGS = \
+Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_CPPFLAGS = \
        $(global_cppflags) \
        $(javascriptcore_cppflags)
 
-Programs_jsc_CXXFLAGS = \
+Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_CXXFLAGS = \
        -fno-strict-aliasing \
        $(global_cxxflags) \
        $(global_cflags) \
        $(GLOBALDEPS_CFLAGS) \
        $(UNICODE_CFLAGS)
 
-Programs_jsc_LDADD = \
-       libJavaScriptCore.la
-
-javascriptcore_dist += \
-       $(CREATE_HASH_TABLE) \
-       $(CREATE_REGEXP_TABLES) \
-       JavaScriptCore/AUTHORS \
-       JavaScriptCore/COPYING.LIB \
-       JavaScriptCore/ChangeLog \
-       JavaScriptCore/THANKS \
-       JavaScriptCore/icu/LICENSE \
-       JavaScriptCore/icu/README \
-       JavaScriptCore/pcre/COPYING \
-       JavaScriptCore/pcre/AUTHORS \
-       JavaScriptCore/pcre/dftables \
-       JavaScriptCore/pcre/ucptable.cpp \
-       JavaScriptCore/parser/Grammar.y \
-       JavaScriptCore/parser/Keywords.table
+Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_LDADD = \
+       -lpthread \
+       libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
+       $(WINMM_LIBS)
+
+EXTRA_DIST += \
+       Source/JavaScriptCore/AUTHORS \
+       Source/JavaScriptCore/ChangeLog \
+       Source/JavaScriptCore/COPYING.LIB \
+       Source/JavaScriptCore/create_hash_table \
+       Source/JavaScriptCore/create_regex_tables \
+       Source/JavaScriptCore/icu/LICENSE \
+       Source/JavaScriptCore/icu/README \
+       Source/JavaScriptCore/parser/Keywords.table \
+       Source/JavaScriptCore/THANKS
 
 # Clean rules for JavaScriptCore
+# FIXME: Should this list be generated from javascriptcore_built_nosources?
 CLEANFILES += \
-       JavaScriptCore/runtime/ArrayPrototype.lut.h \
-       JavaScriptCore/runtime/DatePrototype.lut.h \
-       JavaScriptCore/runtime/JSONObject.lut.h \
-       JavaScriptCore/runtime/MathObject.lut.h \
-       JavaScriptCore/runtime/NumberConstructor.lut.h \
-       JavaScriptCore/runtime/RegExpConstructor.lut.h \
-       JavaScriptCore/runtime/RegExpObject.lut.h \
-       JavaScriptCore/runtime/StringPrototype.lut.h \
-       JavaScriptCore/pcre/chartables.c \
+       Source/JavaScriptCore/Lexer.lut.h \
+       Source/JavaScriptCore/RegExpJitTables.h \
+        Source/JavaScriptCore/runtime/ArrayConstructor.lut.h \
+        Source/JavaScriptCore/runtime/ArrayPrototype.lut.h \
+        Source/JavaScriptCore/runtime/BooleanPrototype.lut.h \
+        Source/JavaScriptCore/runtime/DateConstructor.lut.h \
+        Source/JavaScriptCore/runtime/DatePrototype.lut.h \
+        Source/JavaScriptCore/runtime/ErrorPrototype.lut.h \
+        Source/JavaScriptCore/runtime/JSGlobalObject.lut.h \
+        Source/JavaScriptCore/runtime/JSONObject.lut.h \
+        Source/JavaScriptCore/runtime/MathObject.lut.h \
+        Source/JavaScriptCore/runtime/NumberConstructor.lut.h \
+        Source/JavaScriptCore/runtime/NumberPrototype.lut.h \
+        Source/JavaScriptCore/runtime/ObjectConstructor.lut.h \
+        Source/JavaScriptCore/runtime/ObjectPrototype.lut.h \
+        Source/JavaScriptCore/runtime/RegExpConstructor.lut.h \
+        Source/JavaScriptCore/runtime/RegExpObject.lut.h \
+        Source/JavaScriptCore/runtime/RegExpPrototype.lut.h \
+        Source/JavaScriptCore/runtime/StringConstructor.lut.h \
+        Source/JavaScriptCore/runtime/StringPrototype.lut.h \
        Programs/jsc \
+       Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@ \
        Programs/minidom
diff --git a/GNUmakefile.list.am b/GNUmakefile.list.am
new file mode 100644 (file)
index 0000000..e33c2a4
--- /dev/null
@@ -0,0 +1,620 @@
+javascriptcore_h_api += \
+       Source/JavaScriptCore/API/JSBase.h \
+       Source/JavaScriptCore/API/JSContextRef.h \
+       Source/JavaScriptCore/API/JSObjectRef.h \
+       Source/JavaScriptCore/API/JSStringRef.h \
+       Source/JavaScriptCore/API/JSStringRefBSTR.h \
+       Source/JavaScriptCore/API/JSStringRefCF.h \
+       Source/JavaScriptCore/API/JSValueRef.h \
+       Source/JavaScriptCore/API/JavaScript.h \
+       Source/JavaScriptCore/API/JavaScriptCore.h \
+       Source/JavaScriptCore/API/WebKitAvailability.h
+
+javascriptcore_built_nosources += \
+       Source/JavaScriptCore/Lexer.lut.h \
+       Source/JavaScriptCore/RegExpJitTables.h \
+        Source/JavaScriptCore/runtime/ArrayConstructor.lut.h \
+        Source/JavaScriptCore/runtime/ArrayPrototype.lut.h \
+        Source/JavaScriptCore/runtime/BooleanPrototype.lut.h \
+        Source/JavaScriptCore/runtime/DateConstructor.lut.h \
+        Source/JavaScriptCore/runtime/DatePrototype.lut.h \
+        Source/JavaScriptCore/runtime/ErrorPrototype.lut.h \
+        Source/JavaScriptCore/runtime/JSGlobalObject.lut.h \
+        Source/JavaScriptCore/runtime/JSONObject.lut.h \
+        Source/JavaScriptCore/runtime/MathObject.lut.h \
+        Source/JavaScriptCore/runtime/NumberConstructor.lut.h \
+        Source/JavaScriptCore/runtime/NumberPrototype.lut.h \
+        Source/JavaScriptCore/runtime/ObjectConstructor.lut.h \
+        Source/JavaScriptCore/runtime/ObjectPrototype.lut.h \
+        Source/JavaScriptCore/runtime/RegExpConstructor.lut.h \
+        Source/JavaScriptCore/runtime/RegExpObject.lut.h \
+        Source/JavaScriptCore/runtime/RegExpPrototype.lut.h \
+        Source/JavaScriptCore/runtime/StringConstructor.lut.h \
+        Source/JavaScriptCore/runtime/StringPrototype.lut.h
+
+javascriptcore_sources += \
+       Source/JavaScriptCore/API/APICast.h \
+       Source/JavaScriptCore/API/APIShims.h \
+       Source/JavaScriptCore/API/JSBase.cpp \
+       Source/JavaScriptCore/API/JSBasePrivate.h \
+       Source/JavaScriptCore/API/JSCallbackConstructor.cpp \
+       Source/JavaScriptCore/API/JSCallbackConstructor.h \
+       Source/JavaScriptCore/API/JSCallbackFunction.cpp \
+       Source/JavaScriptCore/API/JSCallbackFunction.h \
+       Source/JavaScriptCore/API/JSCallbackObject.cpp \
+       Source/JavaScriptCore/API/JSCallbackObjectFunctions.h \
+       Source/JavaScriptCore/API/JSCallbackObject.h \
+       Source/JavaScriptCore/API/JSClassRef.cpp \
+       Source/JavaScriptCore/API/JSClassRef.h \
+       Source/JavaScriptCore/API/JSContextRef.cpp \
+       Source/JavaScriptCore/API/JSContextRefPrivate.h \
+       Source/JavaScriptCore/API/JSObjectRef.cpp \
+       Source/JavaScriptCore/API/JSObjectRefPrivate.h \
+       Source/JavaScriptCore/API/JSRetainPtr.h \
+       Source/JavaScriptCore/API/JSStringRef.cpp \
+       Source/JavaScriptCore/API/JSValueRef.cpp \
+       Source/JavaScriptCore/API/JSWeakObjectMapRefInternal.h \
+       Source/JavaScriptCore/API/OpaqueJSString.cpp \
+       Source/JavaScriptCore/API/OpaqueJSString.h \
+       Source/JavaScriptCore/assembler/AbstractMacroAssembler.h \
+       Source/JavaScriptCore/assembler/ARMAssembler.cpp \
+       Source/JavaScriptCore/assembler/ARMAssembler.h \
+       Source/JavaScriptCore/assembler/ARMv7Assembler.cpp \
+       Source/JavaScriptCore/assembler/ARMv7Assembler.h \
+       Source/JavaScriptCore/assembler/AssemblerBuffer.h \
+       Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h \
+       Source/JavaScriptCore/assembler/CodeLocation.h \
+       Source/JavaScriptCore/assembler/LinkBuffer.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerARM.cpp \
+       Source/JavaScriptCore/assembler/MacroAssemblerARM.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h \
+       Source/JavaScriptCore/assembler/MacroAssembler.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerX86.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerSH4.h \
+       Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp \
+       Source/JavaScriptCore/assembler/SH4Assembler.h \
+       Source/JavaScriptCore/assembler/RepatchBuffer.h \
+       Source/JavaScriptCore/assembler/X86Assembler.h \
+       Source/JavaScriptCore/bytecode/CodeBlock.cpp \
+       Source/JavaScriptCore/bytecode/CodeBlock.h \
+       Source/JavaScriptCore/bytecode/EvalCodeCache.h \
+       Source/JavaScriptCore/bytecode/Instruction.h \
+       Source/JavaScriptCore/bytecode/JumpTable.cpp \
+       Source/JavaScriptCore/bytecode/JumpTable.h \
+       Source/JavaScriptCore/bytecode/Opcode.cpp \
+       Source/JavaScriptCore/bytecode/Opcode.h \
+       Source/JavaScriptCore/bytecode/SamplingTool.cpp \
+       Source/JavaScriptCore/bytecode/SamplingTool.h \
+       Source/JavaScriptCore/bytecode/StructureStubInfo.cpp \
+       Source/JavaScriptCore/bytecode/StructureStubInfo.h \
+       Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp \
+       Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h \
+       Source/JavaScriptCore/bytecompiler/Label.h \
+       Source/JavaScriptCore/bytecompiler/LabelScope.h \
+       Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp \
+       Source/JavaScriptCore/bytecompiler/RegisterID.h \
+       Source/JavaScriptCore/heap/ConservativeRoots.cpp \
+       Source/JavaScriptCore/heap/ConservativeRoots.h \
+       Source/JavaScriptCore/heap/Handle.h \
+       Source/JavaScriptCore/heap/HandleHeap.cpp \
+       Source/JavaScriptCore/heap/HandleHeap.h \
+       Source/JavaScriptCore/heap/HandleStack.cpp \
+       Source/JavaScriptCore/heap/HandleStack.h \
+       Source/JavaScriptCore/heap/HandleTypes.h \
+       Source/JavaScriptCore/heap/Heap.cpp \
+       Source/JavaScriptCore/heap/Heap.h \
+       Source/JavaScriptCore/heap/Local.h \
+       Source/JavaScriptCore/heap/LocalScope.h \
+       Source/JavaScriptCore/heap/MachineStackMarker.cpp \
+       Source/JavaScriptCore/heap/MachineStackMarker.h \
+       Source/JavaScriptCore/heap/MarkStack.cpp \
+       Source/JavaScriptCore/heap/MarkStack.h \
+       Source/JavaScriptCore/heap/MarkedBlock.cpp \
+       Source/JavaScriptCore/heap/MarkedBlock.h \
+       Source/JavaScriptCore/heap/MarkedSpace.cpp \
+       Source/JavaScriptCore/heap/MarkedSpace.h \
+       Source/JavaScriptCore/heap/Strong.h \
+       Source/JavaScriptCore/heap/Weak.h \
+       Source/JavaScriptCore/config.h \
+       Source/JavaScriptCore/debugger/DebuggerActivation.cpp \
+       Source/JavaScriptCore/debugger/DebuggerActivation.h \
+       Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp \
+       Source/JavaScriptCore/debugger/DebuggerCallFrame.h \
+       Source/JavaScriptCore/debugger/Debugger.cpp \
+       Source/JavaScriptCore/debugger/Debugger.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APICast.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/APIShims.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScriptCore.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JavaScript.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSBase.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSContextRef.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSObjectRef.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSRetainPtr.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRefCF.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSStringRef.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/JSValueRef.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/OpaqueJSString.h \
+       Source/JavaScriptCore/ForwardingHeaders/JavaScriptCore/WebKitAvailability.h \
+       Source/JavaScriptCore/icu/unicode/parseerr.h \
+       Source/JavaScriptCore/icu/unicode/platform.h \
+       Source/JavaScriptCore/icu/unicode/putil.h \
+       Source/JavaScriptCore/icu/unicode/uchar.h \
+       Source/JavaScriptCore/icu/unicode/ucnv_err.h \
+       Source/JavaScriptCore/icu/unicode/ucnv.h \
+       Source/JavaScriptCore/icu/unicode/ucol.h \
+       Source/JavaScriptCore/icu/unicode/uconfig.h \
+       Source/JavaScriptCore/icu/unicode/uenum.h \
+       Source/JavaScriptCore/icu/unicode/uiter.h \
+       Source/JavaScriptCore/icu/unicode/uloc.h \
+       Source/JavaScriptCore/icu/unicode/umachine.h \
+       Source/JavaScriptCore/icu/unicode/unorm.h \
+       Source/JavaScriptCore/icu/unicode/urename.h \
+       Source/JavaScriptCore/icu/unicode/uset.h \
+       Source/JavaScriptCore/icu/unicode/ustring.h \
+       Source/JavaScriptCore/icu/unicode/utf16.h \
+       Source/JavaScriptCore/icu/unicode/utf8.h \
+       Source/JavaScriptCore/icu/unicode/utf.h \
+       Source/JavaScriptCore/icu/unicode/utf_old.h \
+       Source/JavaScriptCore/icu/unicode/utypes.h \
+       Source/JavaScriptCore/icu/unicode/uversion.h \
+       Source/JavaScriptCore/interpreter/CachedCall.h \
+       Source/JavaScriptCore/interpreter/CallFrameClosure.h \
+       Source/JavaScriptCore/interpreter/CallFrame.cpp \
+       Source/JavaScriptCore/interpreter/CallFrame.h \
+       Source/JavaScriptCore/interpreter/Interpreter.cpp \
+       Source/JavaScriptCore/interpreter/Interpreter.h \
+       Source/JavaScriptCore/interpreter/RegisterFile.cpp \
+       Source/JavaScriptCore/interpreter/RegisterFile.h \
+       Source/JavaScriptCore/interpreter/Register.h \
+       Source/JavaScriptCore/JavaScriptCorePrefix.h \
+       Source/JavaScriptCore/jit/ExecutableAllocator.cpp \
+       Source/JavaScriptCore/jit/ExecutableAllocator.h \
+       Source/JavaScriptCore/jit/JITArithmetic32_64.cpp \
+       Source/JavaScriptCore/jit/JITArithmetic.cpp \
+       Source/JavaScriptCore/jit/JITCall32_64.cpp \
+       Source/JavaScriptCore/jit/JITCall.cpp \
+       Source/JavaScriptCore/jit/JITCode.h \
+       Source/JavaScriptCore/jit/JIT.cpp \
+       Source/JavaScriptCore/jit/JIT.h \
+       Source/JavaScriptCore/jit/JITInlineMethods.h \
+       Source/JavaScriptCore/jit/JITOpcodes32_64.cpp \
+       Source/JavaScriptCore/jit/JITOpcodes.cpp \
+       Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp \
+       Source/JavaScriptCore/jit/JITPropertyAccess.cpp \
+       Source/JavaScriptCore/jit/JITStubCall.h \
+       Source/JavaScriptCore/jit/JITStubs.cpp \
+       Source/JavaScriptCore/jit/JITStubs.h \
+       Source/JavaScriptCore/jit/JSInterfaceJIT.h \
+       Source/JavaScriptCore/jit/SpecializedThunkJIT.h \
+       Source/JavaScriptCore/jit/ThunkGenerators.cpp \
+       Source/JavaScriptCore/jit/ThunkGenerators.h \
+       Source/JavaScriptCore/os-win32/stdbool.h \
+       Source/JavaScriptCore/os-win32/stdint.h \
+       Source/JavaScriptCore/parser/ASTBuilder.h \
+       Source/JavaScriptCore/parser/JSParser.cpp \
+       Source/JavaScriptCore/parser/JSParser.h \
+       Source/JavaScriptCore/parser/Lexer.cpp \
+       Source/JavaScriptCore/parser/Lexer.h \
+       Source/JavaScriptCore/parser/NodeConstructors.h \
+       Source/JavaScriptCore/parser/NodeInfo.h \
+       Source/JavaScriptCore/parser/Nodes.cpp \
+       Source/JavaScriptCore/parser/Nodes.h \
+       Source/JavaScriptCore/parser/ParserArena.cpp \
+       Source/JavaScriptCore/parser/ParserArena.h \
+       Source/JavaScriptCore/parser/Parser.cpp \
+       Source/JavaScriptCore/parser/Parser.h \
+       Source/JavaScriptCore/parser/ResultType.h \
+       Source/JavaScriptCore/parser/SourceCode.h \
+       Source/JavaScriptCore/parser/SourceProvider.h \
+       Source/JavaScriptCore/parser/SourceProviderCache.cpp \
+       Source/JavaScriptCore/parser/SourceProviderCache.h \
+       Source/JavaScriptCore/parser/SourceProviderCacheItem.h \
+       Source/JavaScriptCore/parser/SyntaxChecker.h \
+       Source/JavaScriptCore/profiler/CallIdentifier.h \
+       Source/JavaScriptCore/profiler/Profile.cpp \
+       Source/JavaScriptCore/profiler/ProfileGenerator.cpp \
+       Source/JavaScriptCore/profiler/ProfileGenerator.h \
+       Source/JavaScriptCore/profiler/Profile.h \
+       Source/JavaScriptCore/profiler/ProfileNode.cpp \
+       Source/JavaScriptCore/profiler/ProfileNode.h \
+       Source/JavaScriptCore/profiler/Profiler.cpp \
+       Source/JavaScriptCore/profiler/Profiler.h \
+       Source/JavaScriptCore/runtime/ArgList.cpp \
+       Source/JavaScriptCore/runtime/ArgList.h \
+       Source/JavaScriptCore/runtime/Arguments.cpp \
+       Source/JavaScriptCore/runtime/Arguments.h \
+       Source/JavaScriptCore/runtime/ArrayConstructor.cpp \
+       Source/JavaScriptCore/runtime/ArrayConstructor.h \
+       Source/JavaScriptCore/runtime/ArrayPrototype.cpp \
+       Source/JavaScriptCore/runtime/ArrayPrototype.h \
+       Source/JavaScriptCore/runtime/BatchedTransitionOptimizer.h \
+       Source/JavaScriptCore/runtime/BooleanConstructor.cpp \
+       Source/JavaScriptCore/runtime/BooleanConstructor.h \
+       Source/JavaScriptCore/runtime/BooleanObject.cpp \
+       Source/JavaScriptCore/runtime/BooleanObject.h \
+       Source/JavaScriptCore/runtime/BooleanPrototype.cpp \
+       Source/JavaScriptCore/runtime/BooleanPrototype.h \
+       Source/JavaScriptCore/runtime/CachedTranscendentalFunction.h \
+       Source/JavaScriptCore/runtime/CallData.cpp \
+       Source/JavaScriptCore/runtime/CallData.h \
+       Source/JavaScriptCore/runtime/ClassInfo.h \
+       Source/JavaScriptCore/runtime/CommonIdentifiers.cpp \
+       Source/JavaScriptCore/runtime/CommonIdentifiers.h \
+       Source/JavaScriptCore/runtime/Completion.cpp \
+       Source/JavaScriptCore/runtime/Completion.h \
+       Source/JavaScriptCore/runtime/ConstructData.cpp \
+       Source/JavaScriptCore/runtime/ConstructData.h \
+       Source/JavaScriptCore/runtime/DateConstructor.cpp \
+       Source/JavaScriptCore/runtime/DateConstructor.h \
+       Source/JavaScriptCore/runtime/DateConversion.cpp \
+       Source/JavaScriptCore/runtime/DateConversion.h \
+       Source/JavaScriptCore/runtime/DateInstanceCache.h \
+       Source/JavaScriptCore/runtime/DateInstance.cpp \
+       Source/JavaScriptCore/runtime/DateInstance.h \
+       Source/JavaScriptCore/runtime/DatePrototype.cpp \
+       Source/JavaScriptCore/runtime/DatePrototype.h \
+       Source/JavaScriptCore/runtime/ErrorConstructor.cpp \
+       Source/JavaScriptCore/runtime/ErrorConstructor.h \
+       Source/JavaScriptCore/runtime/Error.cpp \
+       Source/JavaScriptCore/runtime/Error.h \
+       Source/JavaScriptCore/runtime/ErrorInstance.cpp \
+       Source/JavaScriptCore/runtime/ErrorInstance.h \
+       Source/JavaScriptCore/runtime/ErrorPrototype.cpp \
+       Source/JavaScriptCore/runtime/ErrorPrototype.h \
+       Source/JavaScriptCore/runtime/ExceptionHelpers.cpp \
+       Source/JavaScriptCore/runtime/ExceptionHelpers.h \
+       Source/JavaScriptCore/runtime/Executable.cpp \
+       Source/JavaScriptCore/runtime/Executable.h \
+       Source/JavaScriptCore/runtime/FunctionConstructor.cpp \
+       Source/JavaScriptCore/runtime/FunctionConstructor.h \
+       Source/JavaScriptCore/runtime/FunctionPrototype.cpp \
+       Source/JavaScriptCore/runtime/FunctionPrototype.h \
+       Source/JavaScriptCore/runtime/GCActivityCallback.cpp \
+       Source/JavaScriptCore/runtime/GCActivityCallback.h \
+       Source/JavaScriptCore/runtime/GetterSetter.cpp \
+       Source/JavaScriptCore/runtime/GetterSetter.h \
+       Source/JavaScriptCore/runtime/Identifier.cpp \
+       Source/JavaScriptCore/runtime/Identifier.h \
+       Source/JavaScriptCore/runtime/InitializeThreading.cpp \
+       Source/JavaScriptCore/runtime/InitializeThreading.h \
+       Source/JavaScriptCore/runtime/InternalFunction.cpp \
+       Source/JavaScriptCore/runtime/InternalFunction.h \
+       Source/JavaScriptCore/runtime/JSActivation.cpp \
+       Source/JavaScriptCore/runtime/JSActivation.h \
+       Source/JavaScriptCore/runtime/JSAPIValueWrapper.cpp \
+       Source/JavaScriptCore/runtime/JSAPIValueWrapper.h \
+       Source/JavaScriptCore/runtime/JSArray.cpp \
+       Source/JavaScriptCore/runtime/JSArray.h \
+       Source/JavaScriptCore/runtime/JSByteArray.cpp \
+       Source/JavaScriptCore/runtime/JSByteArray.h \
+       Source/JavaScriptCore/runtime/JSCell.cpp \
+       Source/JavaScriptCore/runtime/JSCell.h \
+       Source/JavaScriptCore/runtime/JSFunction.cpp \
+       Source/JavaScriptCore/runtime/JSFunction.h \
+       Source/JavaScriptCore/runtime/JSGlobalData.cpp \
+       Source/JavaScriptCore/runtime/JSGlobalData.h \
+       Source/JavaScriptCore/runtime/JSGlobalObject.cpp \
+       Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp \
+       Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h \
+       Source/JavaScriptCore/runtime/JSGlobalObject.h \
+       Source/JavaScriptCore/runtime/JSLock.cpp \
+       Source/JavaScriptCore/runtime/JSLock.h \
+       Source/JavaScriptCore/runtime/JSNotAnObject.cpp \
+       Source/JavaScriptCore/runtime/JSNotAnObject.h \
+       Source/JavaScriptCore/runtime/JSObject.cpp \
+       Source/JavaScriptCore/runtime/JSObject.h \
+       Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.cpp \
+       Source/JavaScriptCore/runtime/JSObjectWithGlobalObject.h \
+       Source/JavaScriptCore/runtime/JSONObject.cpp \
+       Source/JavaScriptCore/runtime/JSONObject.h \
+       Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp \
+       Source/JavaScriptCore/runtime/JSPropertyNameIterator.h \
+       Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp \
+       Source/JavaScriptCore/runtime/JSStaticScopeObject.h \
+       Source/JavaScriptCore/runtime/JSStringBuilder.h \
+       Source/JavaScriptCore/runtime/JSString.cpp \
+       Source/JavaScriptCore/runtime/JSString.h \
+       Source/JavaScriptCore/runtime/JSType.h \
+       Source/JavaScriptCore/runtime/JSTypeInfo.h \
+       Source/JavaScriptCore/runtime/JSValue.cpp \
+       Source/JavaScriptCore/runtime/JSValue.h \
+       Source/JavaScriptCore/runtime/JSValueInlineMethods.h \
+       Source/JavaScriptCore/runtime/JSVariableObject.cpp \
+       Source/JavaScriptCore/runtime/JSVariableObject.h \
+       Source/JavaScriptCore/runtime/JSWrapperObject.cpp \
+       Source/JavaScriptCore/runtime/JSWrapperObject.h \
+       Source/JavaScriptCore/runtime/JSZombie.h \
+       Source/JavaScriptCore/runtime/LiteralParser.cpp \
+       Source/JavaScriptCore/runtime/LiteralParser.h \
+       Source/JavaScriptCore/runtime/Lookup.cpp \
+       Source/JavaScriptCore/runtime/Lookup.h \
+       Source/JavaScriptCore/runtime/MathObject.cpp \
+       Source/JavaScriptCore/runtime/MathObject.h \
+       Source/JavaScriptCore/runtime/NativeErrorConstructor.cpp \
+       Source/JavaScriptCore/runtime/NativeErrorConstructor.h \
+       Source/JavaScriptCore/runtime/NativeErrorPrototype.cpp \
+       Source/JavaScriptCore/runtime/NativeErrorPrototype.h \
+       Source/JavaScriptCore/runtime/NumberConstructor.cpp \
+       Source/JavaScriptCore/runtime/NumberConstructor.h \
+       Source/JavaScriptCore/runtime/NumberObject.cpp \
+       Source/JavaScriptCore/runtime/NumberObject.h \
+       Source/JavaScriptCore/runtime/NumberPrototype.cpp \
+       Source/JavaScriptCore/runtime/NumberPrototype.h \
+       Source/JavaScriptCore/runtime/NumericStrings.h \
+       Source/JavaScriptCore/runtime/ObjectConstructor.cpp \
+       Source/JavaScriptCore/runtime/ObjectConstructor.h \
+       Source/JavaScriptCore/runtime/ObjectPrototype.cpp \
+       Source/JavaScriptCore/runtime/ObjectPrototype.h \
+       Source/JavaScriptCore/runtime/Operations.cpp \
+       Source/JavaScriptCore/runtime/Operations.h \
+       Source/JavaScriptCore/runtime/PropertyDescriptor.cpp \
+       Source/JavaScriptCore/runtime/PropertyDescriptor.h \
+       Source/JavaScriptCore/runtime/PropertyMapHashTable.h \
+       Source/JavaScriptCore/runtime/PropertyNameArray.cpp \
+       Source/JavaScriptCore/runtime/PropertyNameArray.h \
+       Source/JavaScriptCore/runtime/PropertySlot.cpp \
+       Source/JavaScriptCore/runtime/PropertySlot.h \
+       Source/JavaScriptCore/runtime/Protect.h \
+       Source/JavaScriptCore/runtime/PutPropertySlot.h \
+       Source/JavaScriptCore/runtime/RegExpCache.cpp \
+       Source/JavaScriptCore/runtime/RegExpCache.h \
+       Source/JavaScriptCore/runtime/RegExpConstructor.cpp \
+       Source/JavaScriptCore/runtime/RegExpConstructor.h \
+       Source/JavaScriptCore/runtime/RegExp.cpp \
+       Source/JavaScriptCore/runtime/RegExp.h \
+       Source/JavaScriptCore/runtime/RegExpKey.h \
+       Source/JavaScriptCore/runtime/RegExpMatchesArray.h \
+       Source/JavaScriptCore/runtime/RegExpObject.cpp \
+       Source/JavaScriptCore/runtime/RegExpObject.h \
+       Source/JavaScriptCore/runtime/RegExpPrototype.cpp \
+       Source/JavaScriptCore/runtime/RegExpPrototype.h \
+       Source/JavaScriptCore/runtime/RopeImpl.cpp \
+       Source/JavaScriptCore/runtime/RopeImpl.h \
+       Source/JavaScriptCore/runtime/ScopeChain.cpp \
+       Source/JavaScriptCore/runtime/ScopeChain.h \
+       Source/JavaScriptCore/runtime/ScopeChainMark.h \
+       Source/JavaScriptCore/runtime/SmallStrings.cpp \
+       Source/JavaScriptCore/runtime/SmallStrings.h \
+       Source/JavaScriptCore/runtime/StrictEvalActivation.cpp \
+       Source/JavaScriptCore/runtime/StrictEvalActivation.h \
+       Source/JavaScriptCore/runtime/StringConstructor.cpp \
+       Source/JavaScriptCore/runtime/StringConstructor.h \
+       Source/JavaScriptCore/runtime/StringObject.cpp \
+       Source/JavaScriptCore/runtime/StringObject.h \
+       Source/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h \
+       Source/JavaScriptCore/runtime/StringPrototype.cpp \
+       Source/JavaScriptCore/runtime/StringPrototype.h \
+       Source/JavaScriptCore/runtime/StringRecursionChecker.cpp \
+       Source/JavaScriptCore/runtime/StringRecursionChecker.h \
+       Source/JavaScriptCore/runtime/StructureChain.cpp \
+       Source/JavaScriptCore/runtime/StructureChain.h \
+       Source/JavaScriptCore/runtime/Structure.cpp \
+       Source/JavaScriptCore/runtime/Structure.h \
+       Source/JavaScriptCore/runtime/StructureTransitionTable.h \
+       Source/JavaScriptCore/runtime/SymbolTable.h \
+       Source/JavaScriptCore/runtime/Terminator.h \
+       Source/JavaScriptCore/runtime/TimeoutChecker.cpp \
+       Source/JavaScriptCore/runtime/TimeoutChecker.h \
+       Source/JavaScriptCore/runtime/Tracing.h \
+       Source/JavaScriptCore/runtime/UString.cpp \
+       Source/JavaScriptCore/runtime/UString.h \
+       Source/JavaScriptCore/runtime/UStringBuilder.h \
+       Source/JavaScriptCore/runtime/UStringConcatenate.h \
+       Source/JavaScriptCore/runtime/WeakGCMap.h \
+       Source/JavaScriptCore/runtime/WeakRandom.h \
+       Source/JavaScriptCore/runtime/WriteBarrier.h \
+       Source/JavaScriptCore/wtf/AlwaysInline.h \
+       Source/JavaScriptCore/wtf/ASCIICType.h \
+       Source/JavaScriptCore/wtf/Assertions.cpp \
+       Source/JavaScriptCore/wtf/Assertions.h \
+       Source/JavaScriptCore/wtf/Atomics.h \
+       Source/JavaScriptCore/wtf/AVLTree.h \
+       Source/JavaScriptCore/wtf/Bitmap.h \
+       Source/JavaScriptCore/wtf/BlockStack.h \
+       Source/JavaScriptCore/wtf/BloomFilter.h \
+       Source/JavaScriptCore/wtf/BumpPointerAllocator.h \
+       Source/JavaScriptCore/wtf/ByteArray.cpp \
+       Source/JavaScriptCore/wtf/ByteArray.h \
+       Source/JavaScriptCore/wtf/CrossThreadRefCounted.h \
+       Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp \
+       Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h \
+       Source/JavaScriptCore/wtf/CurrentTime.cpp \
+       Source/JavaScriptCore/wtf/CurrentTime.h \
+       Source/JavaScriptCore/wtf/DateMath.cpp \
+       Source/JavaScriptCore/wtf/DateMath.h \
+       Source/JavaScriptCore/wtf/DecimalNumber.h \
+       Source/JavaScriptCore/wtf/DecimalNumber.cpp \
+       Source/JavaScriptCore/wtf/Decoder.h \
+       Source/JavaScriptCore/wtf/Deque.h \
+       Source/JavaScriptCore/wtf/DisallowCType.h \
+       Source/JavaScriptCore/wtf/DoublyLinkedList.h \
+       Source/JavaScriptCore/wtf/dtoa.cpp \
+       Source/JavaScriptCore/wtf/dtoa.h \
+       Source/JavaScriptCore/wtf/DynamicAnnotations.cpp \
+       Source/JavaScriptCore/wtf/DynamicAnnotations.h \
+       Source/JavaScriptCore/wtf/Encoder.h \
+       Source/JavaScriptCore/wtf/FastAllocBase.h \
+       Source/JavaScriptCore/wtf/FastMalloc.cpp \
+       Source/JavaScriptCore/wtf/FastMalloc.h \
+       Source/JavaScriptCore/wtf/FixedArray.h \
+       Source/JavaScriptCore/wtf/Forward.h \
+       Source/JavaScriptCore/wtf/GetPtr.h \
+       Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp \
+       Source/JavaScriptCore/wtf/gobject/GOwnPtr.h \
+       Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp \
+       Source/JavaScriptCore/wtf/gobject/GRefPtr.h \
+       Source/JavaScriptCore/wtf/gobject/GTypedefs.h \
+       Source/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \
+       Source/JavaScriptCore/wtf/gtk/ThreadingGtk.cpp \
+       Source/JavaScriptCore/wtf/HashCountedSet.h \
+       Source/JavaScriptCore/wtf/HashFunctions.h \
+       Source/JavaScriptCore/wtf/HashIterators.h \
+       Source/JavaScriptCore/wtf/HashMap.h \
+       Source/JavaScriptCore/wtf/HashSet.h \
+       Source/JavaScriptCore/wtf/HashTable.cpp \
+       Source/JavaScriptCore/wtf/HashTable.h \
+       Source/JavaScriptCore/wtf/HashTraits.h \
+       Source/JavaScriptCore/wtf/HexNumber.h \
+       Source/JavaScriptCore/wtf/ListHashSet.h \
+       Source/JavaScriptCore/wtf/ListRefPtr.h \
+       Source/JavaScriptCore/wtf/Locker.h \
+       Source/JavaScriptCore/wtf/MainThread.cpp \
+       Source/JavaScriptCore/wtf/MainThread.h \
+       Source/JavaScriptCore/wtf/MallocZoneSupport.h \
+       Source/JavaScriptCore/wtf/MathExtras.h \
+       Source/JavaScriptCore/wtf/MD5.cpp \
+       Source/JavaScriptCore/wtf/MD5.h \
+       Source/JavaScriptCore/wtf/MessageQueue.h \
+       Source/JavaScriptCore/wtf/NonCopyingSort.h \
+       Source/JavaScriptCore/wtf/Noncopyable.h \
+       Source/JavaScriptCore/wtf/NotFound.h \
+       Source/JavaScriptCore/wtf/NullPtr.h \
+       Source/JavaScriptCore/wtf/OSAllocator.h \
+       Source/JavaScriptCore/wtf/OSRandomSource.cpp \
+       Source/JavaScriptCore/wtf/OSRandomSource.h \
+       Source/JavaScriptCore/wtf/OwnArrayPtr.h \
+       Source/JavaScriptCore/wtf/OwnFastMallocPtr.h \
+       Source/JavaScriptCore/wtf/OwnPtrCommon.h \
+       Source/JavaScriptCore/wtf/OwnPtr.h \
+       Source/JavaScriptCore/wtf/PageAllocation.h \
+       Source/JavaScriptCore/wtf/PageAllocationAligned.cpp \
+       Source/JavaScriptCore/wtf/PageAllocationAligned.h \
+       Source/JavaScriptCore/wtf/PageReservation.h \
+       Source/JavaScriptCore/wtf/PageBlock.cpp \
+       Source/JavaScriptCore/wtf/PageBlock.h \
+       Source/JavaScriptCore/wtf/PassOwnArrayPtr.h \
+       Source/JavaScriptCore/wtf/PassOwnPtr.h \
+       Source/JavaScriptCore/wtf/PassRefPtr.h \
+       Source/JavaScriptCore/wtf/PassTraits.h \
+       Source/JavaScriptCore/wtf/ParallelJobs.h \
+       Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp \
+       Source/JavaScriptCore/wtf/ParallelJobsGeneric.h \
+       Source/JavaScriptCore/wtf/ParallelJobsLibdispatch.h \
+       Source/JavaScriptCore/wtf/ParallelJobsOpenMP.h \
+       Source/JavaScriptCore/wtf/Platform.h \
+       Source/JavaScriptCore/wtf/PossiblyNull.h \
+       Source/JavaScriptCore/wtf/RandomNumber.cpp \
+       Source/JavaScriptCore/wtf/RandomNumber.h \
+       Source/JavaScriptCore/wtf/RandomNumberSeed.h \
+       Source/JavaScriptCore/wtf/RefCounted.h \
+       Source/JavaScriptCore/wtf/RefCountedLeakCounter.cpp \
+       Source/JavaScriptCore/wtf/RefCountedLeakCounter.h \
+       Source/JavaScriptCore/wtf/RefPtr.h \
+       Source/JavaScriptCore/wtf/RefPtrHashMap.h \
+       Source/JavaScriptCore/wtf/RetainPtr.h \
+       Source/JavaScriptCore/wtf/SegmentedVector.h \
+       Source/JavaScriptCore/wtf/SentinelLinkedList.h \
+       Source/JavaScriptCore/wtf/SHA1.cpp \
+       Source/JavaScriptCore/wtf/SHA1.h \
+       Source/JavaScriptCore/wtf/SinglyLinkedList.h \
+       Source/JavaScriptCore/wtf/StackBounds.cpp \
+       Source/JavaScriptCore/wtf/StackBounds.h \
+       Source/JavaScriptCore/wtf/StaticConstructors.h \
+       Source/JavaScriptCore/wtf/StdLibExtras.h \
+       Source/JavaScriptCore/wtf/StringExtras.h \
+       Source/JavaScriptCore/wtf/StringHasher.h \
+       Source/JavaScriptCore/wtf/TCPackedCache.h \
+       Source/JavaScriptCore/wtf/TCPageMap.h \
+       Source/JavaScriptCore/wtf/TCSpinLock.h \
+       Source/JavaScriptCore/wtf/TCSystemAlloc.cpp \
+       Source/JavaScriptCore/wtf/TCSystemAlloc.h \
+       Source/JavaScriptCore/wtf/text/AtomicString.cpp \
+       Source/JavaScriptCore/wtf/text/AtomicString.h \
+       Source/JavaScriptCore/wtf/text/AtomicStringHash.h \
+       Source/JavaScriptCore/wtf/text/AtomicStringImpl.h \
+       Source/JavaScriptCore/wtf/text/CString.cpp \
+       Source/JavaScriptCore/wtf/text/CString.h \
+       Source/JavaScriptCore/wtf/text/StringBuffer.h \
+       Source/JavaScriptCore/wtf/text/StringBuilder.cpp \
+       Source/JavaScriptCore/wtf/text/StringBuilder.h \
+       Source/JavaScriptCore/wtf/text/StringConcatenate.h \
+       Source/JavaScriptCore/wtf/text/StringHash.h \
+       Source/JavaScriptCore/wtf/text/StringImplBase.h \
+       Source/JavaScriptCore/wtf/text/StringImpl.cpp \
+       Source/JavaScriptCore/wtf/text/StringImpl.h \
+       Source/JavaScriptCore/wtf/text/StringOperators.h \
+       Source/JavaScriptCore/wtf/text/StringStatics.cpp \
+       Source/JavaScriptCore/wtf/text/TextPosition.h \
+       Source/JavaScriptCore/wtf/text/WTFString.cpp \
+       Source/JavaScriptCore/wtf/text/WTFString.h \
+       Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp \
+       Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h \
+       Source/JavaScriptCore/wtf/Threading.cpp \
+       Source/JavaScriptCore/wtf/Threading.h \
+       Source/JavaScriptCore/wtf/ThreadingPrimitives.h \
+       Source/JavaScriptCore/wtf/ThreadingPthreads.cpp \
+       Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h \
+       Source/JavaScriptCore/wtf/ThreadSpecific.h \
+       Source/JavaScriptCore/wtf/TypeTraits.cpp \
+       Source/JavaScriptCore/wtf/TypeTraits.h \
+       Source/JavaScriptCore/wtf/unicode/CharacterNames.h \
+       Source/JavaScriptCore/wtf/unicode/CollatorDefault.cpp \
+       Source/JavaScriptCore/wtf/unicode/Collator.h \
+       Source/JavaScriptCore/wtf/unicode/Unicode.h \
+       Source/JavaScriptCore/wtf/unicode/UTF8.cpp \
+       Source/JavaScriptCore/wtf/unicode/UTF8.h \
+       Source/JavaScriptCore/wtf/UnusedParam.h \
+       Source/JavaScriptCore/wtf/ValueCheck.h \
+       Source/JavaScriptCore/wtf/Vector.h \
+       Source/JavaScriptCore/wtf/VectorTraits.h \
+       Source/JavaScriptCore/wtf/VMTags.h \
+       Source/JavaScriptCore/wtf/WTFThreadData.cpp \
+       Source/JavaScriptCore/wtf/WTFThreadData.h \
+       Source/JavaScriptCore/yarr/Yarr.h \
+       Source/JavaScriptCore/yarr/YarrInterpreter.cpp \
+       Source/JavaScriptCore/yarr/YarrInterpreter.h \
+       Source/JavaScriptCore/yarr/YarrJIT.cpp \
+       Source/JavaScriptCore/yarr/YarrJIT.h \
+       Source/JavaScriptCore/yarr/YarrParser.h \
+       Source/JavaScriptCore/yarr/YarrPattern.cpp \
+       Source/JavaScriptCore/yarr/YarrPattern.h \
+       Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp \
+       Source/JavaScriptCore/yarr/YarrSyntaxChecker.h
+
+if TARGET_WIN32
+javascriptcore_sources += \
+       Source/JavaScriptCore/heap/MarkStackWin.cpp \
+       Source/JavaScriptCore/wtf/OSAllocatorWin.cpp
+else
+javascriptcore_sources += \
+       Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp \
+       Source/JavaScriptCore/heap/MarkStackPosix.cpp \
+       Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp
+endif
+
+# ----
+# icu unicode backend
+# ----
+if USE_ICU_UNICODE
+javascriptcore_sources += \
+       Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp \
+       Source/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h
+endif # USE_ICU_UNICODE
+
+# ----
+# glib unicode backend
+# ----
+if USE_GLIB_UNICODE
+javascriptcore_sources += \
+       Source/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h \
+       Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h \
+       Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp
+endif # USE_GLIB_UNICODE
+
+# minidom
+Programs_minidom_SOURCES = \
+       Source/JavaScriptCore/API/tests/JSNode.c \
+       Source/JavaScriptCore/API/tests/JSNode.h \
+       Source/JavaScriptCore/API/tests/JSNodeList.c \
+       Source/JavaScriptCore/API/tests/JSNodeList.h \
+       Source/JavaScriptCore/API/tests/Node.c \
+       Source/JavaScriptCore/API/tests/Node.h \
+       Source/JavaScriptCore/API/tests/NodeList.c \
+       Source/JavaScriptCore/API/tests/NodeList.h \
+       Source/JavaScriptCore/API/tests/minidom.c
+
+Programs_jsc_@WEBKITGTK_API_MAJOR_VERSION@_SOURCES = \
+       Source/JavaScriptCore/jsc.cpp
index 77c9eb80491c9dbfa6bf308e6aa987f6abbdf8b5..a8ae5cca56c2596f032e2d2515805e3d46e2b9db 100644 (file)
@@ -7,7 +7,7 @@
        <key>CFBundleExecutable</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundleGetInfoString</key>
-       <string>${BUNDLE_VERSION}, Copyright 2003-2010 Apple Inc.; Copyright 1999-2001 Harri Porten &lt;porten@kde.org&gt;; Copyright 2001 Peter Kelly &lt;pmk@post.com&gt;; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string>
+       <string>${BUNDLE_VERSION}, Copyright 2003-2011 Apple Inc.; Copyright 1999-2001 Harri Porten &lt;porten@kde.org&gt;; Copyright 2001 Peter Kelly &lt;pmk@post.com&gt;; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string>
        <key>CFBundleIdentifier</key>
        <string>com.apple.${PRODUCT_NAME}</string>
        <key>CFBundleInfoDictionaryVersion</key>
diff --git a/JavaScriptCore.JSVALUE32_64only.exp b/JavaScriptCore.JSVALUE32_64only.exp
new file mode 100644 (file)
index 0000000..f9eee85
--- /dev/null
@@ -0,0 +1 @@
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPFxS2_E
diff --git a/JavaScriptCore.JSVALUE64only.exp b/JavaScriptCore.JSVALUE64only.exp
new file mode 100644 (file)
index 0000000..eaa9f51
--- /dev/null
@@ -0,0 +1 @@
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPFPvS2_E
index 6b5f9b7d506b23244e172b5ace267d7396313c64..9c8805923cbabbaeb24b5287764e5614569f9296 100644 (file)
@@ -8,6 +8,7 @@ _JSContextGetGroup
 _JSContextGroupCreate
 _JSContextGroupRelease
 _JSContextGroupRetain
+_JSContextCreateBacktrace
 _JSEndProfiling
 _JSEvaluateScript
 _JSGarbageCollect
@@ -87,38 +88,43 @@ _JSValueUnprotect
 _JSWeakObjectMapClear
 _JSWeakObjectMapCreate
 _JSWeakObjectMapGet
+_JSWeakObjectMapRemove
 _JSWeakObjectMapSet
 _WTFLog
 _WTFLogVerbose
 _WTFReportArgumentAssertionFailure
 _WTFReportAssertionFailure
 _WTFReportAssertionFailureWithMessage
+_WTFReportBacktrace
 _WTFReportError
 _WTFReportFatalError
 _WebCoreWebThreadIsLockedOrDisabled
-__Z12jsRegExpFreeP8JSRegExp
-__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
-__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN7WebCore10StringImplE
-__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN7WebCore10StringImplE
+__ZN3JSC10HandleHeap12writeBarrierEPNS_7JSValueERKS1_
+__ZN3JSC10HandleHeap4growEv
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN3WTF10StringImplE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN3WTF10StringImplE
 __ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_12JSGlobalDataE
 __ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_9ExecStateE
 __ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
 __ZN3JSC10Identifier4fromEPNS_9ExecStateEi
 __ZN3JSC10Identifier4fromEPNS_9ExecStateEj
-__ZN3JSC10Identifier5equalEPKN7WebCore10StringImplEPKc
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
-__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
-__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC10Identifier5equalEPKN3WTF10StringImplEPKc
+__ZN3JSC10Identifier8toUInt32ERKNS_7UStringERb
+__ZN3JSC10JSFunction4nameEPNS_9ExecStateE
+__ZN3JSC10JSFunction6s_infoE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3JSC11JSByteArray13s_defaultInfoE
+__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataENS_7JSValueEPKNS_9ClassInfoE
+__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
+__ZN3JSC11MarkedSpace21allocateFromSizeClassERNS0_9SizeClassE
 __ZN3JSC11ParserArena5resetEv
 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
-__ZN3JSC12DateInstance4infoE
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd
+__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC11regExpFlagsERKNS_7UStringE
+__ZN3JSC12DateInstance6s_infoE
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEPNS_9StructureEd
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC12JSGlobalData11jsArrayVPtrE
 __ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
@@ -128,8 +134,15 @@ __ZN3JSC12JSGlobalData13startSamplingEv
 __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC12JSGlobalData14resetDateCacheEv
 __ZN3JSC12JSGlobalData14sharedInstanceEv
+__ZN3JSC12JSGlobalData15dumpRegExpTraceEv
+__ZN3JSC12JSGlobalData22clearBuiltinStructuresEv
+#ifndef NDEBUG
+__ZN3JSC12JSGlobalData23releaseExecutableMemoryEv
+#endif
 __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC12RegExpObject6s_infoE
+__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEPNS_9StructureEPNS_6RegExpE
 __ZN3JSC12SamplingTool5setupEv
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
 __ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
@@ -139,44 +152,56 @@ __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC12StringObject4infoE
-__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringE
-__ZN3JSC12jsNumberCellEPNS_9ExecStateEd
+__ZN3JSC12StringObject6s_infoE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEPNS_9StructureERKNS_7UStringE
 __ZN3JSC12nonInlineNaNEv
 __ZN3JSC13SamplingFlags4stopEv
 __ZN3JSC13SamplingFlags5startEv
 __ZN3JSC13SamplingFlags7s_flagsE
 __ZN3JSC13StatementNode6setLocEii
 __ZN3JSC14JSGlobalObject10globalExecEv
+__ZN3JSC14JSGlobalObject11disableEvalEv
 __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
 __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
-__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject16addStaticGlobalsEPNS0_18GlobalPropertyInfoEi
 __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC14JSGlobalObject25destroyJSGlobalObjectDataEPv
+__ZN3JSC14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC14JSGlobalObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject6s_infoE
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3JSC14MachineThreads16addCurrentThreadEv
+__ZN3JSC14MachineThreads29makeUsableFromMultipleThreadsEv
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
+__ZN3JSC14ScopeChainNode6s_infoE
 __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
 __ZN3JSC14TimeoutChecker5resetEv
-__ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE
-__ZN3JSC15createTypeErrorEPNS_9ExecStateEPKc
-__ZN3JSC15toInt32SlowCaseEdRb
-__ZN3JSC16InternalFunction4infoE
+__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
+__ZN3JSC15JSWrapperObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_9MarkStackE
+__ZN3JSC15WeakHandleOwner8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC15WeakHandleOwnerD2Ev
+__ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16InternalFunction12vtableAnchorEv
 __ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
-__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3JSC16InternalFunction6s_infoE
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC16toUInt32SlowCaseEdRb
+__ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16slowValidateCellEPNS_14JSGlobalObjectE
+__ZN3JSC16slowValidateCellEPNS_6JSCellE
+__ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
 __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
-__ZN3JSC17PropertyNameArray3addEPN7WebCore10StringImplE
-__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE
-__ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE
-__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
-__ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
+__ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
+__ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC17createSyntaxErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC18DebuggerActivationC1ERNS_12JSGlobalDataEPNS_8JSObjectE
 __ZN3JSC18PropertyDescriptor11setWritableEb
 __ZN3JSC18PropertyDescriptor12setUndefinedEv
 __ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
@@ -186,30 +211,40 @@ __ZN3JSC18PropertyDescriptor17defaultAttributesE
 __ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
 __ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
 __ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
+__ZN3JSC19SourceProviderCache5clearEv
+__ZN3JSC19SourceProviderCacheD1Ev
 __ZN3JSC19initializeThreadingEv
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
+__ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC22globalMemoryStatisticsEv
+__ZN3JSC22objectConstructorTableE
 __ZN3JSC23AbstractSamplingCounter4dumpEv
-__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC24DynamicGlobalObjectScopeC1EPNS_9ExecStateEPNS_14JSGlobalObjectE
+__ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE
+__ZN3JSC24JSObjectWithGlobalObjectC2EPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC24JSObjectWithGlobalObjectC2ERNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureE
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
 __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
 __ZN3JSC3NaNE
-__ZN3JSC4Heap14primaryHeapEndEv
-__ZN3JSC4Heap15recordExtraCostEm
+__ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC4Heap16activityCallbackEv
+__ZN3JSC4Heap16allocateSlowCaseEm
 __ZN3JSC4Heap16objectTypeCountsEv
-__ZN3JSC4Heap16primaryHeapBeginEv
 __ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC4Heap17globalObjectCountEv
+__ZN3JSC4Heap19setActivityCallbackEN3WTF10PassOwnPtrINS_18GCActivityCallbackEEE
 __ZN3JSC4Heap20protectedObjectCountEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
-__ZN3JSC4Heap6isBusyEv
+__ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
-__ZN3JSC4Heap8allocateEm
 __ZN3JSC4Heap9unprotectENS_7JSValueE
+__ZN3JSC4Yarr11YarrPatternC1ERKNS_7UStringEbbPPKc
+__ZN3JSC4Yarr11byteCompileERNS0_11YarrPatternEPN3WTF20BumpPointerAllocatorE
+__ZN3JSC4Yarr9interpretEPNS0_15BytecodePatternEPKtjjPi
 __ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC6JSCell11getJSNumberEv
@@ -225,29 +260,36 @@ __ZN3JSC6JSCell9getObjectEv
 __ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
 __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
 __ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3JSC6JSLock26currentThreadIsHoldingLockEv
 __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock9lockCountEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
-__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
-__ZN3JSC7JSArray12markChildrenERNS_9MarkStackE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE
+__ZN3JSC6RegExpD1Ev
+__ZN3JSC7JSArray13visitChildrenERNS_9MarkStackE
 __ZN3JSC7JSArray15setSubclassDataEPv
-__ZN3JSC7JSArray4infoE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC7JSArray6s_infoE
 __ZN3JSC7JSArray9setLengthEj
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE
-__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureERKNS_7ArgListE
+__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
 __ZN3JSC7JSArrayD2Ev
+__ZN3JSC7JSValue13isValidCalleeEv
 __ZN3JSC7Profile10restoreAllEv
 __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
-__ZN3JSC7UString4fromEd
-__ZN3JSC7UString4fromEi
-__ZN3JSC7UString4fromEj
-__ZN3JSC7UString4fromEl
+__ZN3JSC7UString6numberEd
+__ZN3JSC7UString6numberEi
+__ZN3JSC7UString6numberEj
+__ZN3JSC7UString6numberEl
 __ZN3JSC7UStringC1EPKc
+__ZN3JSC7UStringC1EPKcj
+__ZN3JSC7UStringC1EPKt
 __ZN3JSC7UStringC1EPKtj
+__ZN3JSC7toInt32Ed
 __ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
 __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
@@ -257,14 +299,18 @@ __ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
 __ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
 __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC8JSObject12markChildrenERNS_9MarkStackE
+__ZN3JSC8JSObject13visitChildrenERNS_9MarkStackE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC8JSObject15unwrappedObjectEv
 __ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC8JSObject17createInheritorIDEv
 __ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
+__ZN3JSC8JSObject17preventExtensionsERNS_12JSGlobalDataE
+__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
+__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
+__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataEjNS_7JSValueEj
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotE
 __ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateEjNS_7JSValueEj
@@ -272,48 +318,98 @@ __ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
 __ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE  
+__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_16WriteBarrierBaseINS_7UnknownEEE
 __ZN3JSC8JSObject23allocatePropertyStorageEmm
 __ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE  
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC8JSObject6s_infoE
 __ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler8profilerEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
+__ZN3JSC8evaluateEPNS_9ExecStateEPNS_14ScopeChainNodeERKNS_10SourceCodeENS_7JSValueE
+__ZN3JSC8isZombieEPKNS_6JSCellE
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
 __ZN3JSC9MarkStack10s_pageSizeE
-__ZN3JSC9MarkStack12releaseStackEPvm
-__ZN3JSC9MarkStack13allocateStackEm
 __ZN3JSC9MarkStack18initializePagesizeEv
-__ZN3JSC9Structure13hasTransitionEPN7WebCore10StringImplEj
-__ZN3JSC9Structure17stopIgnoringLeaksEv
-__ZN3JSC9Structure18startIgnoringLeaksEv
-__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
-__ZN3JSC9Structure22materializePropertyMapEv
-__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
-__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
-__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
-__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
-__ZN3JSC9Structure3getEPKN7WebCore10StringImplERjRPNS_6JSCellE
+__ZN3JSC9Structure21addPropertyTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
+__ZN3JSC9Structure22materializePropertyMapERNS_12JSGlobalDataE
+__ZN3JSC9Structure25changePrototypeTransitionERNS_12JSGlobalDataEPS0_NS_7JSValueE
+__ZN3JSC9Structure27despecifyDictionaryFunctionERNS_12JSGlobalDataERKNS_10IdentifierE
+__ZN3JSC9Structure27despecifyFunctionTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierE
+__ZN3JSC9Structure28addPropertyWithoutTransitionERNS_12JSGlobalDataERKNS_10IdentifierEjPNS_6JSCellE
+__ZN3JSC9Structure3getERNS_12JSGlobalDataEPN3WTF10StringImplERjRPNS_6JSCellE
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
-__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoEj
+__ZN3JSC9Structure6s_infoE
+__ZN3JSC9StructureC1ERNS_12JSGlobalDataENS_7JSValueERKNS_8TypeInfoEjPKNS_9ClassInfoE
 __ZN3JSC9StructureD1Ev
 __ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
 __ZN3JSCeqERKNS_7UStringEPKc
 __ZN3JSCgtERKNS_7UStringES2_
 __ZN3JSCltERKNS_7UStringES2_
+__ZN3WTF10StringImpl11reverseFindEPS0_j
+__ZN3WTF10StringImpl11reverseFindEtj
+__ZN3WTF10StringImpl12sharedBufferEv
+__ZN3WTF10StringImpl16findIgnoringCaseEPKcj
+__ZN3WTF10StringImpl16findIgnoringCaseEPS0_j
+__ZN3WTF10StringImpl18simplifyWhiteSpaceEv
+__ZN3WTF10StringImpl19characterStartingAtEj
+__ZN3WTF10StringImpl19createUninitializedEjRPt
+__ZN3WTF10StringImpl22containsOnlyWhitespaceEv
+__ZN3WTF10StringImpl23defaultWritingDirectionEPb
+__ZN3WTF10StringImpl23reverseFindIgnoringCaseEPS0_j
+__ZN3WTF10StringImpl37createStrippingNullCharactersSlowCaseEPKtj
+__ZN3WTF10StringImpl4findEPFbtEj
+__ZN3WTF10StringImpl4findEPKcj
+__ZN3WTF10StringImpl4findEPS0_j
+__ZN3WTF10StringImpl4findEtj
+__ZN3WTF10StringImpl5adoptERNS_12StringBufferE
+__ZN3WTF10StringImpl5emptyEv
+__ZN3WTF10StringImpl5lowerEv
+__ZN3WTF10StringImpl5toIntEPb
+__ZN3WTF10StringImpl5upperEv
+__ZN3WTF10StringImpl6createEPKc
+__ZN3WTF10StringImpl6createEPKcj
+__ZN3WTF10StringImpl6createEPKtj
+__ZN3WTF10StringImpl6secureEtNS0_21LastCharacterBehaviorE
+__ZN3WTF10StringImpl7replaceEPS0_S1_
+__ZN3WTF10StringImpl7replaceEjjPS0_
+__ZN3WTF10StringImpl7replaceEtPS0_
+__ZN3WTF10StringImpl7replaceEtt
+__ZN3WTF10StringImpl8endsWithEPS0_b
+__ZN3WTF10StringImpl9substringEjj
+__ZN3WTF10StringImplD1Ev
 __ZN3WTF10fastCallocEmm
 __ZN3WTF10fastMallocEm
 __ZN3WTF10fastStrDupEPKc
+__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbbb
+__ZN3WTF11OSAllocator18releaseDecommittedEPvm
+__ZN3WTF11commentAtomE
 __ZN3WTF11currentTimeEv
+__ZN3WTF11dtoaRoundDPEPcdiRbRiRj
+__ZN3WTF11dtoaRoundSFEPcdiRbRiRj
+__ZN3WTF11emptyStringEv
 __ZN3WTF11fastReallocEPvm
+__ZN3WTF12AtomicString11addSlowCaseEPNS_10StringImplE
+__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
+__ZN3WTF12AtomicString3addEPKc
+__ZN3WTF12AtomicString3addEPKt
+__ZN3WTF12AtomicString3addEPKtj
+__ZN3WTF12AtomicString3addEPKtjj
+__ZN3WTF12AtomicString4findEPKtjj
+__ZN3WTF12AtomicString4initEv
 __ZN3WTF12createThreadEPFPvS0_ES0_
 __ZN3WTF12createThreadEPFPvS0_ES0_PKc
 __ZN3WTF12detachThreadEj
 __ZN3WTF12isMainThreadEv
 __ZN3WTF12randomNumberEv
+__ZN3WTF13StringBuilder11reifyStringEv
+__ZN3WTF13StringBuilder11shrinkToFitEv
+__ZN3WTF13StringBuilder15reserveCapacityEj
+__ZN3WTF13StringBuilder6appendEPKcj
+__ZN3WTF13StringBuilder6appendEPKtj
+__ZN3WTF13StringBuilder6resizeEj
 __ZN3WTF13WTFThreadData10staticDataE
 __ZN3WTF13WTFThreadDataC1Ev
 __ZN3WTF13WTFThreadDataD1Ev
@@ -321,17 +417,29 @@ __ZN3WTF13currentThreadEv
 __ZN3WTF13tryFastCallocEmm
 __ZN3WTF13tryFastMallocEm
 __ZN3WTF14fastMallocSizeEPKv
+__ZN3WTF14numberToStringEdPt
+__ZN3WTF14tryFastReallocEPvm
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF15ThreadCondition9broadcastEv
 __ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
 __ZN3WTF15ThreadConditionC1Ev
 __ZN3WTF15ThreadConditionD1Ev
+__ZN3WTF15charactersToIntEPKtmPb
 __ZN3WTF16callOnMainThreadEPFvPvES0_
+__ZN3WTF16codePointCompareERKNS_6StringES2_
 __ZN3WTF16fastZeroedMallocEm
+__ZN3WTF17charactersToFloatEPKtmPbS2_
+__ZN3WTF17equalIgnoringCaseEPKtPKcj
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKc
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
+__ZN3WTF18calculateDSTOffsetEdd
+__ZN3WTF18calculateUTCOffsetEv
+__ZN3WTF18charactersToDoubleEPKtmPbS2_
 __ZN3WTF18dateToDaysFrom1970Eiii
 __ZN3WTF18monthFromDayInYearEib
 __ZN3WTF19initializeThreadingEv
+__ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_
 __ZN3WTF20fastMallocStatisticsEv
 __ZN3WTF20initializeMainThreadEv
 __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
@@ -340,125 +448,88 @@ __ZN3WTF21RefCountedLeakCounter9decrementEv
 __ZN3WTF21RefCountedLeakCounter9incrementEv
 __ZN3WTF21RefCountedLeakCounterC1EPKc
 __ZN3WTF21RefCountedLeakCounterD1Ev
+__ZN3WTF21charactersToIntStrictEPKtmPbi
+__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_
+__ZN3WTF22charactersToUIntStrictEPKtmPbi
 __ZN3WTF23callOnMainThreadAndWaitEPFvPvES0_
 __ZN3WTF23dayInMonthFromDayInYearEib
 __ZN3WTF23waitForThreadCompletionEjPPv
 __ZN3WTF27releaseFastMallocFreeMemoryEv
 __ZN3WTF28setMainThreadCallbacksPausedEb
-__ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj
+__ZN3WTF29cryptographicallyRandomNumberEv
+__ZN3WTF29cryptographicallyRandomValuesEPvm
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
 __ZN3WTF39initializeMainThreadToProcessMainThreadEv
 __ZN3WTF3MD58addBytesEPKhm
-__ZN3WTF3MD58checksumEv
+__ZN3WTF3MD58checksumERNS_6VectorIhLm16EEE
 __ZN3WTF3MD5C1Ev
+__ZN3WTF4SHA111computeHashERNS_6VectorIhLm20EEE
+__ZN3WTF4SHA18addBytesEPKhm
+__ZN3WTF4SHA1C1Ev
+__ZN3WTF4dtoaEPcdRbRiRj
 __ZN3WTF5Mutex4lockEv
 __ZN3WTF5Mutex6unlockEv
 __ZN3WTF5Mutex7tryLockEv
 __ZN3WTF5MutexC1Ev
 __ZN3WTF5MutexD1Ev
+__ZN3WTF5equalEPKNS_10StringImplEPKc
+__ZN3WTF5equalEPKNS_10StringImplES2_
+__ZN3WTF5yieldEv
+__ZN3WTF6String26fromUTF8WithLatin1FallbackEPKcm
+__ZN3WTF6String29charactersWithNullTerminationEv
+__ZN3WTF6String6appendEPKtj
+__ZN3WTF6String6appendERKS0_
+__ZN3WTF6String6appendEc
+__ZN3WTF6String6appendEt
+__ZN3WTF6String6formatEPKcz
+__ZN3WTF6String6insertERKS0_j
+__ZN3WTF6String6numberEd
+__ZN3WTF6String6numberEi
+__ZN3WTF6String6numberEj
+__ZN3WTF6String6numberEl
+__ZN3WTF6String6numberEm
+__ZN3WTF6String6numberEt
+__ZN3WTF6String6numberEx
+__ZN3WTF6String6numberEy
+__ZN3WTF6String6removeEji
+__ZN3WTF6String8fromUTF8EPKc
+__ZN3WTF6String8fromUTF8EPKcm
+__ZN3WTF6String8truncateEj
+__ZN3WTF6StringC1EPKc
+__ZN3WTF6StringC1EPKcj
+__ZN3WTF6StringC1EPKt
+__ZN3WTF6StringC1EPKtj
 __ZN3WTF6strtodEPKcPPc
 __ZN3WTF7CString11mutableDataEv
 __ZN3WTF7CString16newUninitializedEmRPc
 __ZN3WTF7CStringC1EPKc
-__ZN3WTF7CStringC1EPKcj
+__ZN3WTF7CStringC1EPKcm
 __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
 __ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
+__ZN3WTF7xmlAtomE
 __ZN3WTF8Collator18setOrderLowerFirstEb
 __ZN3WTF8CollatorC1EPKc
 __ZN3WTF8CollatorD1Ev
+__ZN3WTF8Internal21fastMallocMatchFailedEPv
 __ZN3WTF8fastFreeEPv
 __ZN3WTF8msToYearEd
+__ZN3WTF8nullAtomE
+__ZN3WTF8starAtomE
+__ZN3WTF8textAtomE
 __ZN3WTF9ByteArray6createEm
 __ZN3WTF9dayInYearEdi
+__ZN3WTF9emptyAtomE
+__ZN3WTF9xmlnsAtomE
+__ZN3WTFeqERKNS_12AtomicStringEPKc
+__ZN3WTFeqERKNS_12AtomicStringERKNS_6VectorItLm0EEE
 __ZN3WTFeqERKNS_7CStringES2_
-__ZN7WebCore10StringImpl11reverseFindEPS0_ib
-__ZN7WebCore10StringImpl11reverseFindEti
-__ZN7WebCore10StringImpl12sharedBufferEv
-__ZN7WebCore10StringImpl18simplifyWhiteSpaceEv
-__ZN7WebCore10StringImpl19characterStartingAtEj
-__ZN7WebCore10StringImpl19createUninitializedEjRPt
-__ZN7WebCore10StringImpl22containsOnlyWhitespaceEv
-__ZN7WebCore10StringImpl23defaultWritingDirectionEv
-__ZN7WebCore10StringImpl37createStrippingNullCharactersSlowCaseEPKtj
-__ZN7WebCore10StringImpl4findEPFbtEi
-__ZN7WebCore10StringImpl4findEPKcib
-__ZN7WebCore10StringImpl4findEPS0_ib
-__ZN7WebCore10StringImpl4findEti
-__ZN7WebCore10StringImpl5adoptERNS_12StringBufferE
-__ZN7WebCore10StringImpl5emptyEv
-__ZN7WebCore10StringImpl5lowerEv
-__ZN7WebCore10StringImpl5toIntEPb
-__ZN7WebCore10StringImpl5upperEv
-__ZN7WebCore10StringImpl6createEPKc
-__ZN7WebCore10StringImpl6createEPKcj
-__ZN7WebCore10StringImpl6createEPKtj
-__ZN7WebCore10StringImpl6createEPKtjN3WTF10PassRefPtrINS3_21CrossThreadRefCountedINS3_16OwnFastMallocPtrIS1_EEEEEE
-__ZN7WebCore10StringImpl6secureEtb
-__ZN7WebCore10StringImpl7replaceEPS0_S1_
-__ZN7WebCore10StringImpl7replaceEjjPS0_
-__ZN7WebCore10StringImpl7replaceEtPS0_
-__ZN7WebCore10StringImpl7replaceEtt
-__ZN7WebCore10StringImpl8endsWithEPS0_b
-__ZN7WebCore10StringImpl9substringEjj
-__ZN7WebCore10StringImplD1Ev
-__ZN7WebCore11commentAtomE
-__ZN7WebCore12AtomicString11addSlowCaseEPNS_10StringImplE
-__ZN7WebCore12AtomicString3addEPKc
-__ZN7WebCore12AtomicString3addEPKt
-__ZN7WebCore12AtomicString3addEPKtj
-__ZN7WebCore12AtomicString3addEPKtjj
-__ZN7WebCore12AtomicString4findEPKtjj
-__ZN7WebCore12AtomicString4initEv
-__ZN7WebCore15charactersToIntEPKtmPb
-__ZN7WebCore17charactersToFloatEPKtmPb
-__ZN7WebCore17equalIgnoringCaseEPKtPKcj
-__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplEPKc
-__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplES1_
-__ZN7WebCore18charactersToDoubleEPKtmPb
-__ZN7WebCore20equalIgnoringNullityEPNS_10StringImplES1_
-__ZN7WebCore21charactersToIntStrictEPKtmPbi
-__ZN7WebCore22charactersToUIntStrictEPKtmPbi
-__ZN7WebCore5equalEPKNS_10StringImplEPKc
-__ZN7WebCore5equalEPKNS_10StringImplES2_
-__ZN7WebCore6String26fromUTF8WithLatin1FallbackEPKcm
-__ZN7WebCore6String29charactersWithNullTerminationEv
-__ZN7WebCore6String6appendEPKtj
-__ZN7WebCore6String6appendERKS0_
-__ZN7WebCore6String6appendEc
-__ZN7WebCore6String6appendEt
-__ZN7WebCore6String6formatEPKcz
-__ZN7WebCore6String6insertERKS0_j
-__ZN7WebCore6String6numberEd
-__ZN7WebCore6String6numberEi
-__ZN7WebCore6String6numberEj
-__ZN7WebCore6String6numberEl
-__ZN7WebCore6String6numberEm
-__ZN7WebCore6String6numberEt
-__ZN7WebCore6String6numberEx
-__ZN7WebCore6String6numberEy
-__ZN7WebCore6String6removeEji
-__ZN7WebCore6String8fromUTF8EPKc
-__ZN7WebCore6String8fromUTF8EPKcm
-__ZN7WebCore6String8truncateEj
-__ZN7WebCore6StringC1EPKt
-__ZN7WebCore7xmlAtomE
-__ZN7WebCore8nullAtomE
-__ZN7WebCore8starAtomE
-__ZN7WebCore8textAtomE
-__ZN7WebCore9emptyAtomE
-__ZN7WebCore9xmlnsAtomE
-__ZN7WebCoreeqERKNS_12AtomicStringEPKc
-__ZN7WebCoreplEPKcRKNS_6StringE
-__ZN7WebCoreplERKNS_6StringEPKc
-__ZN7WebCoreplERKNS_6StringES2_
 __ZNK3JSC10JSFunction23isHostFunctionNonInlineEv
-__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
+__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE
 __ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
 __ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
 __ZNK3JSC14JSGlobalObject14isDynamicScopeERb
-__ZNK3JSC16InternalFunction9classInfoEv
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
 __ZNK3JSC17DebuggerCallFrame10thisObjectEv
 __ZNK3JSC17DebuggerCallFrame12functionNameEv
@@ -472,74 +543,79 @@ __ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
 __ZNK3JSC18PropertyDescriptor6getterEv
 __ZNK3JSC18PropertyDescriptor6setterEv
 __ZNK3JSC18PropertyDescriptor8writableEv
-__ZNK3JSC4Heap10statisticsEv
+__ZNK3JSC19SourceProviderCache8byteSizeEv
 __ZNK3JSC4Heap11objectCountEv
+__ZNK3JSC4Heap4sizeEv
+__ZNK3JSC4Heap8capacityEv
 __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell14isGetterSetterEv
 __ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
-__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateE
+__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
-__ZNK3JSC6JSCell9classInfoEv
 __ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
 __ZNK3JSC6JSCell9getUInt32ERj
 __ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE
 __ZNK3JSC7ArgList8getSliceEiRS0_
 __ZNK3JSC7JSArray12subclassDataEv
-__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
+__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
 __ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
 __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
-__ZNK3JSC7UString10UTF8StringEb
-__ZNK3JSC7UString14toStrictUInt32EPb
+__ZNK3JSC7UString20substringSharingImplEjj
+__ZNK3JSC7UString4utf8Eb
 __ZNK3JSC7UString5asciiEv
-__ZNK3JSC7UString6is8BitEv
-__ZNK3JSC7UString6substrEjj
-__ZNK3JSC7UString8toUInt32EPb
-__ZNK3JSC7UString8toUInt32EPbb
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
 __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+__ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
-__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
 __ZNK3JSC8JSObject9classNameEv
 __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
 __ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
 __ZNK3JSC9HashTable11deleteTableEv
+__ZNK3WTF12AtomicString5lowerEv
+__ZNK3WTF13DecimalNumber15toStringDecimalEPtj
+__ZNK3WTF13DecimalNumber19toStringExponentialEPtj
+__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
+__ZNK3WTF13DecimalNumber32bufferLengthForStringExponentialEv
+__ZNK3WTF6String11toIntStrictEPbi
+__ZNK3WTF6String12toUIntStrictEPbi
+__ZNK3WTF6String13toInt64StrictEPbi
+__ZNK3WTF6String14threadsafeCopyEv
+__ZNK3WTF6String15stripWhiteSpaceEv
+__ZNK3WTF6String16removeCharactersEPFbtE
+__ZNK3WTF6String17crossThreadStringEv
+__ZNK3WTF6String18simplifyWhiteSpaceEv
+__ZNK3WTF6String19characterStartingAtEj
+__ZNK3WTF6String4utf8Eb
+__ZNK3WTF6String5asciiEv
+__ZNK3WTF6String5lowerEv
+__ZNK3WTF6String5splitERKS0_RNS_6VectorIS0_Lm0EEE
+__ZNK3WTF6String5splitERKS0_bRNS_6VectorIS0_Lm0EEE
+__ZNK3WTF6String5splitEtRNS_6VectorIS0_Lm0EEE
+__ZNK3WTF6String5splitEtbRNS_6VectorIS0_Lm0EEE
+__ZNK3WTF6String5toIntEPb
+__ZNK3WTF6String5upperEv
+__ZNK3WTF6String6latin1Ev
+__ZNK3WTF6String6toUIntEPb
+__ZNK3WTF6String7toFloatEPbS1_
+__ZNK3WTF6String8foldCaseEv
+__ZNK3WTF6String8toDoubleEPbS1_
+__ZNK3WTF6String8toIntPtrEPb
+__ZNK3WTF6String8toUInt64EPb
+__ZNK3WTF6String9substringEjj
 __ZNK3WTF8Collator7collateEPKtmS2_m
-__ZNK7WebCore12AtomicString5lowerEv
-__ZNK7WebCore6String11toIntStrictEPbi
-__ZNK7WebCore6String12toUIntStrictEPbi
-__ZNK7WebCore6String14threadsafeCopyEv
-__ZNK7WebCore6String15stripWhiteSpaceEv
-__ZNK7WebCore6String16removeCharactersEPFbtE
-__ZNK7WebCore6String17crossThreadStringEv
-__ZNK7WebCore6String18simplifyWhiteSpaceEv
-__ZNK7WebCore6String19characterStartingAtEj
-__ZNK7WebCore6String4utf8Ev
-__ZNK7WebCore6String5asciiEv
-__ZNK7WebCore6String5lowerEv
-__ZNK7WebCore6String5splitERKS0_RN3WTF6VectorIS0_Lm0EEE
-__ZNK7WebCore6String5splitERKS0_bRN3WTF6VectorIS0_Lm0EEE
-__ZNK7WebCore6String5splitEtRN3WTF6VectorIS0_Lm0EEE
-__ZNK7WebCore6String5splitEtbRN3WTF6VectorIS0_Lm0EEE
-__ZNK7WebCore6String5toIntEPb
-__ZNK7WebCore6String5upperEv
-__ZNK7WebCore6String6latin1Ev
-__ZNK7WebCore6String6toUIntEPb
-__ZNK7WebCore6String7toFloatEPb
-__ZNK7WebCore6String8foldCaseEv
-__ZNK7WebCore6String8toDoubleEPb
-__ZNK7WebCore6String8toIntPtrEPb
-__ZNK7WebCore6String8toUInt64EPb
-__ZNK7WebCore6String9substringEjj
 __ZTVN3JSC12StringObjectE
 __ZTVN3JSC14JSGlobalObjectE
+__ZTVN3JSC14ScopeChainNodeE
 __ZTVN3JSC15JSWrapperObjectE
+__ZTVN3JSC15WeakHandleOwnerE
 __ZTVN3JSC16InternalFunctionE
 __ZTVN3JSC16JSVariableObjectE
 __ZTVN3JSC8DebuggerE
@@ -548,5 +624,12 @@ __ZTVN3JSC8JSStringE
 _jscore_fastmalloc_introspection
 _kJSClassDefinitionEmpty
 
-# iOS Methods
+# iOS methods
+__ZN3WTF11isWebThreadEv
+__ZN3JSC12JSGlobalData23recompileAllJSFunctionsEv
 __ZN3JSC12JSGlobalData20sharedInstanceExistsEv
+__ZN3JSC25DefaultGCActivityCallbackC2EPNS_4HeapEP11__CFRunLoop
+__ZN3JSC25DefaultGCActivityCallbackD2Ev
+__ZN3JSC25DefaultGCActivityCallbackclEv
+__ZN3JSC25DefaultGCActivityCallback11synchronizeEv
+__ZTVN3JSC25DefaultGCActivityCallbackE
index 9e014ddbdc91fe40f8394fecd3209618c0bad2ae..eff360736e209d0ca07c99e34a3ee416916e3fa2 100644 (file)
@@ -43,7 +43,7 @@
         'chromium_src_dir': '../../WebKit/chromium',
       },{
         # WebKit is checked out in src/chromium/third_party/WebKit
-        'chromium_src_dir': '../../../..',
+        'chromium_src_dir': '../../../../..',
       }],
     ],
   },
         '../wtf/unicode',
       ],
       'sources': [
+        '<@(javascriptcore_publicheader_files)',
+        '<@(javascriptcore_privateheader_files)',
         '<@(javascriptcore_files)',
       ],
       'sources/': [
         ['exclude', '../'],
         # ... Then include what we want.
         ['include', '../wtf/'],
+        # FIXME: This is clearly not sustainable. 
+        ['exclude', '../wtf/android'], 
+        ['exclude', '../wtf/brew'], 
+        ['exclude', '../wtf/efl'], 
+        ['exclude', '../wtf/gobject'], 
+        ['exclude', '../wtf/gtk'], 
+        ['exclude', '../wtf/haiku'], 
+        ['exclude', '../wtf/mac'], 
+        ['exclude', '../wtf/qt'], 
+        ['exclude', '../wtf/url'], 
+        ['exclude', '../wtf/wince'], 
+        ['exclude', '../wtf/wx'], 
+        ['exclude', '../wtf/unicode/brew'], 
+        ['exclude', '../wtf/unicode/wince'], 
+        ['exclude', '../wtf/unicode/glib'], 
+        ['exclude', '../wtf/unicode/qt4'], 
         # GLib/GTK, even though its name doesn't really indicate.
         ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'],
-        ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx)\\.(cpp|mm)$'],
+        ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx|Efl|Symbian)\\.(cpp|mm)$'],
         ['exclude', 'wtf/CurrentTime\\.cpp$'],
+        ['exclude', 'wtf/OSRandomSource\\.cpp$'],
         ['exclude', 'wtf/MainThread.cpp$'],
         ['exclude', 'wtf/TC.*\\.(cpp|h)$'],
       ],
           '../',
           '../wtf',
         ],
+        # Some warnings occur in JSC headers, so they must also be disabled
+        # in targets that use JSC.
+        'msvs_disabled_warnings': [
+          # Don't complain about calling specific versions of templatized
+          # functions (e.g. in RefPtrHashMap.h).
+          4344,
+          # Don't complain about using "this" in an initializer list
+          # (e.g. in StringImpl.h).
+          4355,
+        ],
       },
       'export_dependent_settings': [
         'wtf_config',
           'sources/': [
             ['exclude', 'ThreadIdentifierDataPthreads\\.(h|cpp)$'],
             ['exclude', 'ThreadingPthreads\\.cpp$'],
-            ['include', 'Thread(ing|Specific)Win\\.cpp$']
+            ['include', 'Thread(ing|Specific)Win\\.cpp$'],
+            ['exclude', 'OSAllocatorPosix\\.cpp$'],
+            ['include', 'OSAllocatorWin\\.cpp$']
           ],
           'include_dirs!': [
             '<(SHARED_INTERMEDIATE_DIR)/webkit',
           ],
+          'conditions': [
+            ['inside_chromium_build==1 and component=="shared_library"', {
+              # Chromium windows multi-dll build enables c++ exception and this
+              # causes wtf generates 4291 warning due to operator new/delete
+              # implementations. Disable the warning for chromium windows
+              # multi-dll build.
+              'msvs_disabled_warnings': [4291],
+              'direct_dependent_settings': {
+                'msvs_disabled_warnings': [4291],
+              },
+            }],
+          ],
         }],
       ],
     },
     {
-      'target_name': 'pcre',
+      'target_name': 'yarr',
       'type': '<(library)',
       'dependencies': [
         'wtf',
       'msvs_guid': '49909552-0B0C-4C14-8CF6-DB8A2ADE0934',
       'actions': [
         {
-          'action_name': 'dftables',
+          'action_name': 'retgen',
+          'inputs': [
+            '../create_regex_tables',
+          ],
+          'arguments': [
+            '--no-tables',
+          ],
+          'outputs': [
+            '<(INTERMEDIATE_DIR)/RegExpJitTables.h',
+          ],
+          'action': ['python', '<@(_inputs)', '<@(_arguments)', '<@(_outputs)'],
+        },
+        {
+          'action_name': 'klgen',
           'inputs': [
-            '../pcre/dftables',
+            '../KeywordLookupGenerator.py',
+            '../parser/Keywords.table'
+          ],
+          'arguments': [
           ],
           'outputs': [
-            '<(INTERMEDIATE_DIR)/chartables.c',
+            '<(INTERMEDIATE_DIR)/KeywordLookup.h',
           ],
-          'action': ['perl', '-w', '<@(_inputs)', '<@(_outputs)'],
+          'action': ['python', '<@(_inputs)', '<@(_arguments)', '<@(_outputs)'],
         },
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
+        '../runtime',
       ],
       'sources': [
         '<@(javascriptcore_files)',
         # First exclude everything ...
         ['exclude', '../'],
         # ... Then include what we want.
-        ['include', '../pcre/'],
-        # ucptable.cpp is #included by pcre_ucp_searchfunchs.cpp and is not
-        # intended to be compiled directly.
-        ['exclude', '../pcre/ucptable.cpp$'],
+        ['include', '../yarr/'],
+        # The Yarr JIT isn't used in WebCore.
+        ['exclude', '../yarr/YarrJIT\\.(h|cpp)$'],
       ],
       'export_dependent_settings': [
         'wtf',
index 787e0e6813f7ac507cd3230b59b1b5d261c2b66a..c101031bdda2ac707c2874123b24fc8e2b1c032c 100644 (file)
 {
     'variables': {
-        'javascriptcore_files': [
-            'API/APICast.h',
+        'project_dir': ['.'],
+        # These headers are part of JavaScriptCore's public API in the Apple Mac build.
+        'javascriptcore_publicheader_files': [
+            'API/JSBase.h',
+            'API/JSContextRef.h',
+            'API/JSObjectRef.h',
+            'API/JSStringRef.h',
+            'API/JSStringRefCF.h',
+            'API/JSValueRef.h',
             'API/JavaScript.h',
             'API/JavaScriptCore.h',
-            'API/JSBase.cpp',
-            'API/JSBase.h',
+            'API/WebKitAvailability.h',
+        ],
+        # These headers are part of JavaScriptCore's private API in the Apple Mac build.
+        'javascriptcore_privateheader_files': [
+            'API/APICast.h',
+            'API/APIShims.h',
             'API/JSBasePrivate.h',
+            'API/JSContextRefPrivate.h',
+            'API/JSObjectRefPrivate.h',
+            'API/JSProfilerPrivate.h',
+            'API/JSRetainPtr.h',
+            'API/JSWeakObjectMapRefInternal.h',
+            'API/JSWeakObjectMapRefPrivate.h',
+            'API/OpaqueJSString.h',
+            'assembler/MacroAssemblerCodeRef.h',
+            'bytecode/Opcode.h',
+            'heap/ConservativeRoots.h',
+            'heap/Handle.h',
+            'heap/HandleHeap.h',
+            'heap/HandleStack.h',
+            'heap/HandleTypes.h',
+            'heap/Heap.h',
+            'heap/Local.h',
+            'heap/LocalScope.h',
+            'heap/Strong.h',
+            'heap/Weak.h',
+            'config.h',
+            'debugger/Debugger.h',
+            'debugger/DebuggerActivation.h',
+            'debugger/DebuggerCallFrame.h',
+            'interpreter/CallFrame.h',
+            'interpreter/Interpreter.h',
+            'interpreter/Register.h',
+            'interpreter/RegisterFile.h',
+            'jit/ExecutableAllocator.h',
+            'jit/JITCode.h',
+            'jit/JITStubs.h',
+            'jit/ThunkGenerators.h',
+            'parser/ResultType.h',
+            'parser/SourceCode.h',
+            'parser/SourceProvider.h',
+            'parser/SourceProviderCache.h',
+            'profiler/CallIdentifier.h',
+            'profiler/Profile.h',
+            'profiler/ProfileNode.h',
+            'profiler/Profiler.h',
+            'runtime/ArgList.h',
+            'runtime/ArrayPrototype.h',
+            'runtime/BooleanObject.h',
+            'runtime/CachedTranscendentalFunction.h',
+            'runtime/CallData.h',
+            'runtime/ClassInfo.h',
+            'runtime/CommonIdentifiers.h',
+            'runtime/Completion.h',
+            'runtime/ConstructData.h',
+            'runtime/DateInstance.h',
+            'runtime/DateInstanceCache.h',
+            'runtime/Error.h',
+            'runtime/ExceptionHelpers.h',
+            'runtime/FunctionConstructor.h',
+            'runtime/FunctionPrototype.h',
+            'runtime/GCActivityCallback.h',
+            'runtime/Identifier.h',
+            'runtime/InitializeThreading.h',
+            'runtime/InternalFunction.h',
+            'runtime/JSAPIValueWrapper.h',
+            'runtime/JSArray.h',
+            'runtime/JSByteArray.h',
+            'runtime/JSCell.h',
+            'runtime/JSFunction.h',
+            'runtime/JSGlobalData.h',
+            'runtime/JSGlobalObject.h',
+            'runtime/JSLock.h',
+            'runtime/JSNumberCell.h',
+            'runtime/JSObject.h',
+            'runtime/JSObjectWithGlobalObject.h',
+            'runtime/JSString.h',
+            'runtime/JSType.h',
+            'runtime/JSTypeInfo.h',
+            'runtime/JSValue.h',
+            'runtime/JSValueInlineMethods.h',
+            'runtime/JSVariableObject.h',
+            'runtime/JSWrapperObject.h',
+            'runtime/Lookup.h',
+            'runtime/MathObject.h',
+            'runtime/MemoryStatistics.h',
+            'runtime/NumberObject.h',
+            'runtime/NumberPrototype.h',
+            'runtime/NumericStrings.h',
+            'runtime/ObjectPrototype.h',
+            'runtime/Operations.h',
+            'runtime/PropertyDescriptor.h',
+            'runtime/PropertyMapHashTable.h',
+            'runtime/PropertyNameArray.h',
+            'runtime/PropertySlot.h',
+            'runtime/Protect.h',
+            'runtime/PutPropertySlot.h',
+            'runtime/RegExp.h',
+            'runtime/RegExpKey.h',
+            'runtime/RegExpCache.h',
+            'runtime/RegExpObject.h',
+            'runtime/RopeImpl.h',
+            'runtime/ScopeChain.h',
+            'runtime/SmallStrings.h',
+            'runtime/StringObject.h',
+            'runtime/StringObjectThatMasqueradesAsUndefined.h',
+            'runtime/StringPrototype.h',
+            'runtime/Structure.h',
+            'runtime/StructureChain.h',
+            'runtime/StructureTransitionTable.h',
+            'runtime/SymbolTable.h',
+            'runtime/Terminator.h',
+            'runtime/TimeoutChecker.h',
+            'runtime/UString.h',
+            'runtime/UStringBuilder.h',
+            'runtime/WeakGCMap.h',
+            'runtime/WeakRandom.h',
+            'runtime/WriteBarrier.h',
+            'wtf/ASCIICType.h',
+            'wtf/AVLTree.h',
+            'wtf/Alignment.h',
+            'wtf/AlwaysInline.h',
+            'wtf/Assertions.h',
+            'wtf/Atomics.h',
+            'wtf/Bitmap.h',
+            'wtf/BlockStack.h',
+            'wtf/BloomFilter.h',
+            'wtf/BumpPointerAllocator.h',
+            'wtf/ByteArray.h',
+            'wtf/Complex.h',
+            'wtf/CrossThreadRefCounted.h',
+            'wtf/CryptographicallyRandomNumber.h',
+            'wtf/CurrentTime.h',
+            'wtf/DateMath.h',
+            'wtf/DecimalNumber.h',
+            'wtf/Decoder.h',
+            'wtf/Deque.h',
+            'wtf/DisallowCType.h',
+            'wtf/DoublyLinkedList.h',
+            'wtf/Encoder.h',
+            'wtf/FastAllocBase.h',
+            'wtf/FastMalloc.h',
+            'wtf/FixedArray.h',
+            'wtf/Forward.h',
+            'wtf/GetPtr.h',
+            'wtf/HashCountedSet.h',
+            'wtf/HashFunctions.h',
+            'wtf/HashIterators.h',
+            'wtf/HashMap.h',
+            'wtf/HashSet.h',
+            'wtf/HashTable.h',
+            'wtf/HashTraits.h',
+            'wtf/HexNumber.h',
+            'wtf/ListHashSet.h',
+            'wtf/ListRefPtr.h',
+            'wtf/Locker.h',
+            'wtf/MD5.h',
+            'wtf/MainThread.h',
+            'wtf/MathExtras.h',
+            'wtf/MessageQueue.h',
+            'wtf/NonCopyingSort.h',
+            'wtf/Noncopyable.h',
+            'wtf/NotFound.h',
+            'wtf/NullPtr.h',
+            'wtf/OSAllocator.h',
+            'wtf/OwnArrayPtr.h',
+            'wtf/OwnFastMallocPtr.h',
+            'wtf/OwnPtr.h',
+            'wtf/OwnPtrCommon.h',
+            'wtf/PageAllocation.h',
+            'wtf/PageAllocationAligned.h',
+            'wtf/PageBlock.h',
+            'wtf/PageReservation.h',
+            'wtf/PassOwnArrayPtr.h',
+            'wtf/PassOwnPtr.h',
+            'wtf/PassRefPtr.h',
+            'wtf/PassTraits.h',
+            'wtf/Platform.h',
+            'wtf/PossiblyNull.h',
+            'wtf/RandomNumber.h',
+            'wtf/RefCounted.h',
+            'wtf/RefCountedLeakCounter.h',
+            'wtf/RefPtr.h',
+            'wtf/RefPtrHashMap.h',
+            'wtf/RetainPtr.h',
+            'wtf/SentinelLinkedList.h',
+            'wtf/SinglyLinkedList.h',
+            'wtf/StackBounds.h',
+            'wtf/StaticConstructors.h',
+            'wtf/StdLibExtras.h',
+            'wtf/StringExtras.h',
+            'wtf/StringHasher.h',
+            'wtf/ThreadSafeRefCounted.h',
+            'wtf/ThreadSpecific.h',
+            'wtf/Threading.h',
+            'wtf/ThreadingPrimitives.h',
+            'wtf/TypeTraits.h',
+            'wtf/UnusedParam.h',
+            'wtf/VMTags.h',
+            'wtf/ValueCheck.h',
+            'wtf/Vector.h',
+            'wtf/VectorTraits.h',
+            'wtf/WTFThreadData.h',
+            'wtf/dtoa.h',
+            'wtf/text/AtomicString.h',
+            'wtf/text/AtomicStringHash.h',
+            'wtf/text/AtomicStringImpl.h',
+            'wtf/text/CString.h',
+            'wtf/text/StringBuffer.h',
+            'wtf/text/StringBuilder.h',
+            'wtf/text/StringConcatenate.h',
+            'wtf/text/StringHash.h',
+            'wtf/text/StringImpl.h',
+            'wtf/text/StringImplBase.h',
+            'wtf/text/StringOperators.h',
+            'wtf/text/TextPosition.h',
+            'wtf/text/WTFString.h',
+            'wtf/unicode/CharacterNames.h',
+            'wtf/unicode/Collator.h',
+            'wtf/unicode/UTF8.h',
+            'wtf/unicode/Unicode.h',
+            'wtf/unicode/icu/UnicodeIcu.h',
+            'yarr/Yarr.h',
+            'yarr/YarrInterpreter.h',
+            'yarr/YarrPattern.h',
+        ],
+        'javascriptcore_files': [
+            'API/APIShims.h',
+            'API/JSBase.cpp',
             'API/JSCallbackConstructor.cpp',
             'API/JSCallbackConstructor.h',
             'API/JSCallbackFunction.cpp',
             'API/JSClassRef.cpp',
             'API/JSClassRef.h',
             'API/JSContextRef.cpp',
-            'API/JSContextRef.h',
-            'API/JSContextRefPrivate.h',
             'API/JSObjectRef.cpp',
-            'API/JSObjectRef.h',
             'API/JSProfilerPrivate.cpp',
-            'API/JSProfilerPrivate.h',
-            'API/JSRetainPtr.h',
             'API/JSStringRef.cpp',
-            'API/JSStringRef.h',
             'API/JSStringRefBSTR.cpp',
             'API/JSStringRefBSTR.h',
             'API/JSStringRefCF.cpp',
-            'API/JSStringRefCF.h',
             'API/JSValueRef.cpp',
-            'API/JSValueRef.h',
+            'API/JSWeakObjectMapRefPrivate.cpp',
             'API/OpaqueJSString.cpp',
-            'API/OpaqueJSString.h',
-            'API/tests/JSNode.h',
-            'API/tests/JSNodeList.h',
-            'API/tests/Node.h',
-            'API/tests/NodeList.h',
-            'API/WebKitAvailability.h',
-            'assembler/AbstractMacroAssembler.h',
+            'AllInOneFile.cpp',
+            'ForwardingHeaders/JavaScriptCore/APICast.h',
+            'ForwardingHeaders/JavaScriptCore/APIShims.h',
+            'ForwardingHeaders/JavaScriptCore/JSBase.h',
+            'ForwardingHeaders/JavaScriptCore/JSContextRef.h',
+            'ForwardingHeaders/JavaScriptCore/JSObjectRef.h',
+            'ForwardingHeaders/JavaScriptCore/JSRetainPtr.h',
+            'ForwardingHeaders/JavaScriptCore/JSStringRef.h',
+            'ForwardingHeaders/JavaScriptCore/JSStringRefCF.h',
+            'ForwardingHeaders/JavaScriptCore/JSValueRef.h',
+            'ForwardingHeaders/JavaScriptCore/JavaScript.h',
+            'ForwardingHeaders/JavaScriptCore/JavaScriptCore.h',
+            'ForwardingHeaders/JavaScriptCore/OpaqueJSString.h',
+            'ForwardingHeaders/JavaScriptCore/WebKitAvailability.h',
+            'JavaScriptCorePrefix.h',
+            'assembler/ARMAssembler.cpp',
+            'assembler/ARMAssembler.h',
+            'assembler/ARMv7Assembler.cpp',
             'assembler/ARMv7Assembler.h',
+            'assembler/AbstractMacroAssembler.h',
             'assembler/AssemblerBuffer.h',
+            'assembler/AssemblerBufferWithConstantPool.h',
             'assembler/CodeLocation.h',
+            'assembler/LinkBuffer.h',
+            'assembler/MIPSAssembler.h',
             'assembler/MacroAssembler.h',
+            'assembler/MacroAssemblerARM.cpp',
+            'assembler/MacroAssemblerARM.h',
             'assembler/MacroAssemblerARMv7.h',
-            'assembler/MacroAssemblerCodeRef.h',
+            'assembler/MacroAssemblerMIPS.h',
             'assembler/MacroAssemblerX86.h',
-            'assembler/MacroAssemblerX86_64.h',
             'assembler/MacroAssemblerX86Common.h',
+            'assembler/MacroAssemblerX86_64.h',
+            'assembler/RepatchBuffer.h',
             'assembler/X86Assembler.h',
             'bytecode/CodeBlock.cpp',
             'bytecode/CodeBlock.h',
             'bytecode/JumpTable.cpp',
             'bytecode/JumpTable.h',
             'bytecode/Opcode.cpp',
-            'bytecode/Opcode.h',
             'bytecode/SamplingTool.cpp',
             'bytecode/SamplingTool.h',
             'bytecode/StructureStubInfo.cpp',
             'bytecode/StructureStubInfo.h',
             'bytecompiler/BytecodeGenerator.cpp',
             'bytecompiler/BytecodeGenerator.h',
-            'bytecompiler/NodesCodegen.cpp',
             'bytecompiler/Label.h',
             'bytecompiler/LabelScope.h',
+            'bytecompiler/NodesCodegen.cpp',
             'bytecompiler/RegisterID.h',
-            'config.h',
+            'heap/ConservativeRoots.cpp',
+            'heap/HandleHeap.cpp',
+            'heap/HandleStack.cpp',
+            'heap/Heap.cpp',
+            'heap/MachineStackMarker.cpp',
+            'heap/MachineStackMarker.h',
+            'heap/MarkStack.cpp',
+            'heap/MarkStack.h',
+            'heap/MarkStackPosix.cpp',
+            'heap/MarkStackSymbian.cpp',
+            'heap/MarkStackWin.cpp',
+            'heap/MarkedBlock.cpp',
+            'heap/MarkedBlock.h',
+            'heap/MarkedSpace.cpp',
+            'heap/MarkedSpace.h',
             'debugger/Debugger.cpp',
-            'debugger/Debugger.h',
             'debugger/DebuggerActivation.cpp',
-            'debugger/DebuggerActivation.h',
             'debugger/DebuggerCallFrame.cpp',
-            'debugger/DebuggerCallFrame.h',
+            'dfg/DFGAliasTracker.h',
+            'dfg/DFGByteCodeParser.cpp',
+            'dfg/DFGByteCodeParser.h',
+            'dfg/DFGGenerationInfo.h',
+            'dfg/DFGGraph.cpp',
+            'dfg/DFGGraph.h',
+            'dfg/DFGJITCodeGenerator.cpp',
+            'dfg/DFGJITCodeGenerator.h',
+            'dfg/DFGJITCompiler.cpp',
+            'dfg/DFGJITCompiler.h',
+            'dfg/DFGNode.h',
+            'dfg/DFGNonSpeculativeJIT.cpp',
+            'dfg/DFGNonSpeculativeJIT.h',
+            'dfg/DFGOperations.cpp',
+            'dfg/DFGOperations.h',
+            'dfg/DFGRegisterBank.h',
+            'dfg/DFGScoreBoard.h',
+            'dfg/DFGSpeculativeJIT.cpp',
+            'dfg/DFGSpeculativeJIT.h',
             'icu/unicode/parseerr.h',
             'icu/unicode/platform.h',
             'icu/unicode/putil.h',
             'icu/unicode/uversion.h',
             'interpreter/CachedCall.h',
             'interpreter/CallFrame.cpp',
-            'interpreter/CallFrame.h',
             'interpreter/CallFrameClosure.h',
             'interpreter/Interpreter.cpp',
-            'interpreter/Interpreter.h',
-            'interpreter/Register.h',
             'interpreter/RegisterFile.cpp',
-            'interpreter/RegisterFile.h',
-            'JavaScriptCorePrefix.h',
             'jit/ExecutableAllocator.cpp',
-            'jit/ExecutableAllocator.h',
             'jit/ExecutableAllocatorFixedVMPool.cpp',
-            'jit/ExecutableAllocatorPosix.cpp',
-            'jit/ExecutableAllocatorWin.cpp',
             'jit/JIT.cpp',
             'jit/JIT.h',
             'jit/JITArithmetic.cpp',
             'jit/JITArithmetic32_64.cpp',
             'jit/JITCall.cpp',
-            'jit/JITCode.h',
+            'jit/JITCall32_64.cpp',
             'jit/JITInlineMethods.h',
             'jit/JITOpcodes.cpp',
             'jit/JITOpcodes32_64.cpp',
             'jit/JITPropertyAccess32_64.cpp',
             'jit/JITStubCall.h',
             'jit/JITStubs.cpp',
-            'jit/JITStubs.h',
-            'jsc.cpp',
+            'jit/JSInterfaceJIT.h',
+            'jit/SpecializedThunkJIT.h',
+            'jit/ThunkGenerators.cpp',
+            'os-win32/WinMain.cpp',
+            'os-win32/inttypes.h',
             'os-win32/stdbool.h',
             'os-win32/stdint.h',
+            'parser/ASTBuilder.h',
+            'parser/JSParser.cpp',
+            'parser/JSParser.h',
             'parser/Lexer.cpp',
             'parser/Lexer.h',
             'parser/NodeConstructors.h',
             'parser/Parser.h',
             'parser/ParserArena.cpp',
             'parser/ParserArena.h',
-            'parser/ResultType.h',
-            'parser/SourceCode.h',
-            'parser/SourceProvider.h',
-            'pcre/pcre.h',
-            'pcre/pcre_compile.cpp',
-            'pcre/pcre_exec.cpp',
-            'pcre/pcre_internal.h',
-            'pcre/pcre_tables.cpp',
-            'pcre/pcre_ucp_searchfuncs.cpp',
-            'pcre/pcre_xclass.cpp',
-            'pcre/ucpinternal.h',
-            'pcre/ucptable.cpp',
-            'profiler/CallIdentifier.h',
+            'parser/SourceProviderCache.cpp',
+            'parser/SourceProviderCacheItem.h',
+            'parser/SyntaxChecker.h',
             'profiler/Profile.cpp',
-            'profiler/Profile.h',
             'profiler/ProfileGenerator.cpp',
             'profiler/ProfileGenerator.h',
             'profiler/ProfileNode.cpp',
-            'profiler/ProfileNode.h',
             'profiler/Profiler.cpp',
-            'profiler/Profiler.h',
             'profiler/ProfilerServer.h',
+            'profiler/ProfilerServer.mm',
+            'qt/api/qscriptconverter_p.h',
+            'qt/api/qscriptengine.cpp',
+            'qt/api/qscriptengine.h',
+            'qt/api/qscriptengine_p.cpp',
+            'qt/api/qscriptengine_p.h',
+            'qt/api/qscriptfunction.cpp',
+            'qt/api/qscriptfunction_p.h',
+            'qt/api/qscriptoriginalglobalobject_p.h',
+            'qt/api/qscriptprogram.cpp',
+            'qt/api/qscriptprogram.h',
+            'qt/api/qscriptprogram_p.h',
+            'qt/api/qscriptstring.cpp',
+            'qt/api/qscriptstring.h',
+            'qt/api/qscriptstring_p.h',
+            'qt/api/qscriptsyntaxcheckresult.cpp',
+            'qt/api/qscriptsyntaxcheckresult.h',
+            'qt/api/qscriptsyntaxcheckresult_p.h',
+            'qt/api/qscriptvalue.cpp',
+            'qt/api/qscriptvalue.h',
+            'qt/api/qscriptvalue_p.h',
+            'qt/api/qscriptvalueiterator.cpp',
+            'qt/api/qscriptvalueiterator.h',
+            'qt/api/qscriptvalueiterator_p.h',
+            'qt/api/qtscriptglobal.h',
+            'qt/benchmarks/qscriptengine/tst_qscriptengine.cpp',
+            'qt/benchmarks/qscriptvalue/tst_qscriptvalue.cpp',
+            'qt/tests/qscriptengine/tst_qscriptengine.cpp',
+            'qt/tests/qscriptstring/tst_qscriptstring.cpp',
+            'qt/tests/qscriptvalue/tst_qscriptvalue.cpp',
+            'qt/tests/qscriptvalue/tst_qscriptvalue.h',
+            'qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp',
+            'qt/tests/qscriptvalue/tst_qscriptvalue_generated_init.cpp',
+            'qt/tests/qscriptvalue/tst_qscriptvalue_generated_istype.cpp',
+            'qt/tests/qscriptvalue/tst_qscriptvalue_generated_totype.cpp',
+            'qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp',
             'runtime/ArgList.cpp',
-            'runtime/ArgList.h',
             'runtime/Arguments.cpp',
             'runtime/Arguments.h',
             'runtime/ArrayConstructor.cpp',
             'runtime/ArrayConstructor.h',
             'runtime/ArrayPrototype.cpp',
-            'runtime/ArrayPrototype.h',
             'runtime/BatchedTransitionOptimizer.h',
             'runtime/BooleanConstructor.cpp',
             'runtime/BooleanConstructor.h',
             'runtime/BooleanObject.cpp',
-            'runtime/BooleanObject.h',
             'runtime/BooleanPrototype.cpp',
             'runtime/BooleanPrototype.h',
             'runtime/CallData.cpp',
-            'runtime/CallData.h',
-            'runtime/ClassInfo.h',
-            'runtime/Collector.cpp',
-            'runtime/Collector.h',
-            'runtime/CollectorHeapIterator.h',
             'runtime/CommonIdentifiers.cpp',
-            'runtime/CommonIdentifiers.h',
             'runtime/Completion.cpp',
-            'runtime/Completion.h',
             'runtime/ConstructData.cpp',
-            'runtime/ConstructData.h',
             'runtime/DateConstructor.cpp',
             'runtime/DateConstructor.h',
             'runtime/DateConversion.cpp',
             'runtime/DateConversion.h',
             'runtime/DateInstance.cpp',
-            'runtime/DateInstance.h',
-            'runtime/DateInstanceCache.h',
             'runtime/DatePrototype.cpp',
             'runtime/DatePrototype.h',
             'runtime/Error.cpp',
-            'runtime/Error.h',
             'runtime/ErrorConstructor.cpp',
             'runtime/ErrorConstructor.h',
             'runtime/ErrorInstance.cpp',
             'runtime/ErrorPrototype.cpp',
             'runtime/ErrorPrototype.h',
             'runtime/ExceptionHelpers.cpp',
-            'runtime/ExceptionHelpers.h',
+            'runtime/Executable.cpp',
+            'runtime/Executable.h',
             'runtime/FunctionConstructor.cpp',
-            'runtime/FunctionConstructor.h',
             'runtime/FunctionPrototype.cpp',
-            'runtime/FunctionPrototype.h',
+            'runtime/GCActivityCallback.cpp',
+            'runtime/GCActivityCallbackCF.cpp',
             'runtime/GetterSetter.cpp',
             'runtime/GetterSetter.h',
-            'runtime/GlobalEvalFunction.cpp',
-            'runtime/GlobalEvalFunction.h',
             'runtime/Identifier.cpp',
-            'runtime/Identifier.h',
             'runtime/InitializeThreading.cpp',
-            'runtime/InitializeThreading.h',
             'runtime/InternalFunction.cpp',
-            'runtime/InternalFunction.h',
+            'runtime/JSAPIValueWrapper.cpp',
             'runtime/JSActivation.cpp',
             'runtime/JSActivation.h',
             'runtime/JSArray.cpp',
-            'runtime/JSArray.h',
             'runtime/JSByteArray.cpp',
-            'runtime/JSByteArray.h',
             'runtime/JSCell.cpp',
-            'runtime/JSCell.h',
             'runtime/JSFunction.cpp',
-            'runtime/JSFunction.h',
             'runtime/JSGlobalData.cpp',
-            'runtime/JSGlobalData.h',
             'runtime/JSGlobalObject.cpp',
-            'runtime/JSGlobalObject.h',
             'runtime/JSGlobalObjectFunctions.cpp',
             'runtime/JSGlobalObjectFunctions.h',
-            'runtime/JSImmediate.cpp',
-            'runtime/JSImmediate.h',
             'runtime/JSLock.cpp',
-            'runtime/JSLock.h',
             'runtime/JSNotAnObject.cpp',
             'runtime/JSNotAnObject.h',
             'runtime/JSNumberCell.cpp',
-            'runtime/JSNumberCell.h',
-            'runtime/JSObject.cpp',
-            'runtime/JSObject.h',
             'runtime/JSONObject.cpp',
             'runtime/JSONObject.h',
+            'runtime/JSObject.cpp',
+            'runtime/JSObjectWithGlobalObject.cpp',
             'runtime/JSPropertyNameIterator.cpp',
             'runtime/JSPropertyNameIterator.h',
             'runtime/JSStaticScopeObject.cpp',
             'runtime/JSStaticScopeObject.h',
             'runtime/JSString.cpp',
-            'runtime/JSString.h',
-            'runtime/JSType.h',
-            'runtime/JSTypeInfo.h',
+            'runtime/JSStringBuilder.h',
             'runtime/JSValue.cpp',
-            'runtime/JSValue.h',
             'runtime/JSVariableObject.cpp',
-            'runtime/JSVariableObject.h',
             'runtime/JSWrapperObject.cpp',
-            'runtime/JSWrapperObject.h',
+            'runtime/JSZombie.cpp',
+            'runtime/JSZombie.h',
             'runtime/LiteralParser.cpp',
             'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
-            'runtime/Lookup.h',
-            'runtime/MarkStack.cpp',
-            'runtime/MarkStack.h',
-            'runtime/MarkStackWin.cpp',
             'runtime/MathObject.cpp',
-            'runtime/MathObject.h',
+            'runtime/MemoryStatistics.cpp',
             'runtime/NativeErrorConstructor.cpp',
             'runtime/NativeErrorConstructor.h',
             'runtime/NativeErrorPrototype.cpp',
             'runtime/NativeErrorPrototype.h',
-            'runtime/NativeFunctionWrapper.h',
             'runtime/NumberConstructor.cpp',
             'runtime/NumberConstructor.h',
             'runtime/NumberObject.cpp',
-            'runtime/NumberObject.h',
             'runtime/NumberPrototype.cpp',
-            'runtime/NumberPrototype.h',
             'runtime/ObjectConstructor.cpp',
             'runtime/ObjectConstructor.h',
             'runtime/ObjectPrototype.cpp',
-            'runtime/ObjectPrototype.h',
             'runtime/Operations.cpp',
-            'runtime/Operations.h',
             'runtime/PropertyDescriptor.cpp',
-            'runtime/PropertyDescriptor.h',
-            'runtime/PropertyMapHashTable.h',
             'runtime/PropertyNameArray.cpp',
-            'runtime/PropertyNameArray.h',
             'runtime/PropertySlot.cpp',
-            'runtime/PropertySlot.h',
-            'runtime/Protect.h',
-            'runtime/PrototypeFunction.cpp',
-            'runtime/PrototypeFunction.h',
-            'runtime/PutPropertySlot.h',
             'runtime/RegExp.cpp',
-            'runtime/RegExp.h',
             'runtime/RegExpCache.cpp',
-            'runtime/RegExpCache.h',
             'runtime/RegExpConstructor.cpp',
             'runtime/RegExpConstructor.h',
-            'runtime/RegExpKey.h',
             'runtime/RegExpMatchesArray.h',
             'runtime/RegExpObject.cpp',
-            'runtime/RegExpObject.h',
             'runtime/RegExpPrototype.cpp',
             'runtime/RegExpPrototype.h',
+            'runtime/RopeImpl.cpp',
             'runtime/ScopeChain.cpp',
-            'runtime/ScopeChain.h',
             'runtime/ScopeChainMark.h',
             'runtime/SmallStrings.cpp',
-            'runtime/SmallStrings.h',
+            'runtime/StrictEvalActivation.cpp',
+            'runtime/StrictEvalActivation.h',
             'runtime/StringConstructor.cpp',
             'runtime/StringConstructor.h',
             'runtime/StringObject.cpp',
-            'runtime/StringObject.h',
-            'runtime/StringObjectThatMasqueradesAsUndefined.h',
             'runtime/StringPrototype.cpp',
-            'runtime/StringPrototype.h',
+            'runtime/StringRecursionChecker.cpp',
+            'runtime/StringRecursionChecker.h',
             'runtime/Structure.cpp',
-            'runtime/Structure.h',
             'runtime/StructureChain.cpp',
-            'runtime/StructureChain.h',
-            'runtime/StructureTransitionTable.h',
-            'runtime/SymbolTable.h',
-            'runtime/Terminator.h',
             'runtime/TimeoutChecker.cpp',
-            'runtime/TimeoutChecker.h',
+            'runtime/Tracing.d',
             'runtime/Tracing.h',
             'runtime/UString.cpp',
-            'runtime/UString.h',
-            'runtime/WeakRandom.h',
-            'wtf/AlwaysInline.h',
-            'wtf/ASCIICType.h',
+            'runtime/UStringConcatenate.h',
             'wtf/Assertions.cpp',
-            'wtf/Assertions.h',
-            'wtf/Atomics.h',
-            'wtf/AVLTree.h',
             'wtf/ByteArray.cpp',
-            'wtf/ByteArray.h',
-            'wtf/chromium/ChromiumThreading.h',
-            'wtf/chromium/MainThreadChromium.cpp',
-            'wtf/CrossThreadRefCounted.h',
+            'wtf/CryptographicallyRandomNumber.cpp',
             'wtf/CurrentTime.cpp',
-            'wtf/CurrentTime.h',
             'wtf/DateMath.cpp',
-            'wtf/DateMath.h',
-            'wtf/Deque.h',
-            'wtf/DisallowCType.h',
-            'wtf/dtoa.cpp',
-            'wtf/dtoa.h',
-            'wtf/FastAllocBase.h',
+            'wtf/DecimalNumber.cpp',
+            'wtf/DynamicAnnotations.cpp',
+            'wtf/DynamicAnnotations.h',
             'wtf/FastMalloc.cpp',
-            'wtf/FastMalloc.h',
-            'wtf/Forward.h',
-            'wtf/GetPtr.h',
-            'wtf/gobject/GOwnPtr.cpp',
-            'wtf/gobject/GOwnPtr.h',
-            'wtf/gtk/MainThreadGtk.cpp',
-            'wtf/gtk/ThreadingGtk.cpp',
-            'wtf/HashCountedSet.h',
-            'wtf/HashFunctions.h',
-            'wtf/HashIterators.h',
-            'wtf/HashMap.h',
-            'wtf/HashSet.h',
             'wtf/HashTable.cpp',
-            'wtf/HashTable.h',
-            'wtf/HashTraits.h',
-            'wtf/ListHashSet.h',
-            'wtf/ListRefPtr.h',
-            'wtf/Locker.h',
             'wtf/MD5.cpp',
-            'wtf/MD5.h',
             'wtf/MainThread.cpp',
-            'wtf/MainThread.h',
             'wtf/MallocZoneSupport.h',
-            'wtf/MathExtras.h',
-            'wtf/MessageQueue.h',
-            'wtf/Noncopyable.h',
-            'wtf/NotFound.h',
-            'wtf/OwnArrayPtr.h',
-            'wtf/OwnFastMallocPtr.h',
-            'wtf/OwnPtr.h',
-            'wtf/OwnPtrCommon.h',
-            'wtf/PassOwnPtr.h',
-            'wtf/PassRefPtr.h',
-            'wtf/Platform.h',
-            'wtf/PtrAndFlags.h',
+            'wtf/NullPtr.cpp',
+            'wtf/OSAllocatorPosix.cpp',
+            'wtf/OSAllocatorSymbian.cpp',
+            'wtf/OSAllocatorWin.cpp',
+            'wtf/OSRandomSource.cpp',
+            'wtf/OSRandomSource.h',
+            'wtf/PageAllocationAligned.cpp',
+            'wtf/PageAllocatorSymbian.h',
+            'wtf/PageBlock.cpp',
             'wtf/RandomNumber.cpp',
-            'wtf/RandomNumber.h',
             'wtf/RandomNumberSeed.h',
-            'wtf/RefCounted.h',
             'wtf/RefCountedLeakCounter.cpp',
-            'wtf/RefCountedLeakCounter.h',
-            'wtf/RefPtr.h',
-            'wtf/RefPtrHashMap.h',
-            'wtf/RetainPtr.h',
+            'wtf/SHA1.cpp',
+            'wtf/SHA1.h',
             'wtf/SegmentedVector.h',
-            'wtf/StaticConstructors.h',
-            'wtf/StdLibExtras.h',
-            'wtf/StringExtras.h',
-            'wtf/StringHashFunctions.h',
+            'wtf/SizeLimits.cpp',
+            'wtf/StackBounds.cpp',
+            'wtf/StringExtras.cpp',
             'wtf/TCPackedCache.h',
-            'wtf/qt/MainThreadQt.cpp',
-            'wtf/qt/StringQt.cpp',
-            'wtf/qt/ThreadingQt.cpp',
             'wtf/TCPageMap.h',
             'wtf/TCSpinLock.h',
             'wtf/TCSystemAlloc.cpp',
             'wtf/TCSystemAlloc.h',
+            'wtf/ThreadFunctionInvocation.h',
             'wtf/ThreadIdentifierDataPthreads.cpp',
             'wtf/ThreadIdentifierDataPthreads.h',
+            'wtf/ThreadSpecificWin.cpp',
             'wtf/Threading.cpp',
-            'wtf/Threading.h',
             'wtf/ThreadingNone.cpp',
-            'wtf/ThreadingPrimitives.h',
             'wtf/ThreadingPthreads.cpp',
             'wtf/ThreadingWin.cpp',
-            'wtf/ThreadSafeShared.h',
-            'wtf/ThreadSpecific.h',
-            'wtf/ThreadSpecificWin.cpp',
             'wtf/TypeTraits.cpp',
-            'wtf/TypeTraits.h',
+            'wtf/WTFThreadData.cpp',
+            'wtf/android/AndroidThreading.h',
+            'wtf/android/MainThreadAndroid.cpp',
+            'wtf/brew/MainThreadBrew.cpp',
+            'wtf/brew/OwnPtrBrew.cpp',
+            'wtf/brew/RefPtrBrew.h',
+            'wtf/brew/ShellBrew.h',
+            'wtf/brew/StringBrew.cpp',
+            'wtf/brew/SystemMallocBrew.h',
+            'wtf/chromium/ChromiumThreading.h',
+            'wtf/chromium/MainThreadChromium.cpp',
+            'wtf/dtoa.cpp',
+            'wtf/efl/MainThreadEfl.cpp',
+            'wtf/gobject/GOwnPtr.cpp',
+            'wtf/gobject/GOwnPtr.h',
+            'wtf/gobject/GRefPtr.cpp',
+            'wtf/gobject/GRefPtr.h',
+            'wtf/gobject/GTypedefs.h',
+            'wtf/gtk/MainThreadGtk.cpp',
+            'wtf/gtk/ThreadingGtk.cpp',
+            'wtf/haiku/MainThreadHaiku.cpp',
+            'wtf/haiku/StringHaiku.cpp',
+            'wtf/mac/MainThreadMac.mm',
+            'wtf/qt/MainThreadQt.cpp',
+            'wtf/qt/StringQt.cpp',
+            'wtf/qt/ThreadingQt.cpp',
             'wtf/text/AtomicString.cpp',
-            'wtf/text/AtomicString.h',
-            'wtf/text/AtomicStringImpl.h',
             'wtf/text/CString.cpp',
-            'wtf/text/CString.h',
-            'wtf/text/StringHash.h',
+            'wtf/text/StringBuilder.cpp',
             'wtf/text/StringImpl.cpp',
-            'wtf/text/StringImpl.h',
             'wtf/text/StringStatics.cpp',
             'wtf/text/WTFString.cpp',
-            'wtf/text/WTFString.h',
-            'wtf/unicode/Collator.h',
             'wtf/unicode/CollatorDefault.cpp',
+            'wtf/unicode/UTF8.cpp',
+            'wtf/unicode/UnicodeMacrosFromICU.h',
+            'wtf/unicode/brew/UnicodeBrew.cpp',
+            'wtf/unicode/brew/UnicodeBrew.h',
             'wtf/unicode/glib/UnicodeGLib.cpp',
             'wtf/unicode/glib/UnicodeGLib.h',
-            'wtf/unicode/glib/UnicodeMacrosFromICU.h',
             'wtf/unicode/icu/CollatorICU.cpp',
-            'wtf/unicode/icu/UnicodeIcu.h',
             'wtf/unicode/qt4/UnicodeQt4.h',
-            'wtf/unicode/Unicode.h',
-            'wtf/unicode/UTF8.cpp',
-            'wtf/unicode/UTF8.h',
-            'wtf/UnusedParam.h',
-            'wtf/ValueCheck.h',
-            'wtf/Vector.h',
-            'wtf/VectorTraits.h',
-            'wtf/VMTags.h',
-            'wtf/WTFThreadData.cpp',
-            'wtf/WTFThreadData.h',
+            'wtf/unicode/wince/UnicodeWinCE.cpp',
+            'wtf/unicode/wince/UnicodeWinCE.h',
+            'wtf/url/api/ParsedURL.cpp',
+            'wtf/url/api/ParsedURL.h',
+            'wtf/url/api/URLString.h',
+            'wtf/url/src/RawURLBuffer.h',
+            'wtf/url/src/URLBuffer.h',
+            'wtf/url/src/URLCharacterTypes.cpp',
+            'wtf/url/src/URLCharacterTypes.h',
+            'wtf/url/src/URLComponent.h',
+            'wtf/url/src/URLEscape.cpp',
+            'wtf/url/src/URLEscape.h',
+            'wtf/url/src/URLParser.h',
+            'wtf/url/src/URLQueryCanonicalizer.h',
+            'wtf/url/src/URLSegments.cpp',
+            'wtf/url/src/URLSegments.h',
             'wtf/win/MainThreadWin.cpp',
             'wtf/win/OwnPtrWin.cpp',
+            'wtf/wince/FastMallocWinCE.h',
+            'wtf/wince/MemoryManager.cpp',
+            'wtf/wince/MemoryManager.h',
             'wtf/wx/MainThreadWx.cpp',
-            'yarr/RegexCompiler.cpp',
-            'yarr/RegexCompiler.h',
-            'yarr/RegexInterpreter.cpp',
-            'yarr/RegexInterpreter.h',
-            'yarr/RegexJIT.cpp',
-            'yarr/RegexJIT.h',
-            'yarr/RegexParser.h',
-            'yarr/RegexPattern.h',
-        ]
+            'wtf/wx/StringWx.cpp',
+            'yarr/YarrInterpreter.cpp',
+            'yarr/YarrJIT.cpp',
+            'yarr/YarrJIT.h',
+            'yarr/YarrParser.h',
+            'yarr/YarrPattern.cpp',
+            'yarr/YarrSyntaxChecker.cpp',
+            'yarr/YarrSyntaxChecker.h',
+        ],
+        'javascriptcore_derived_source_files': [
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/Lexer.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpJitTables.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/TracingDtrace.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ArrayConstructor.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ArrayPrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/BooleanPrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/DateConstructor.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/DatePrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ErrorPrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/JSGlobalObject.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/JSONObject.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/MathObject.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/NumberConstructor.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/NumberPrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ObjectConstructor.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/ObjectPrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpConstructor.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpObject.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/RegExpPrototype.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/StringConstructor.lut.h',
+            '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/StringPrototype.lut.h',
+        ],
+        'minidom_files': [
+            'API/tests/JSNode.c',
+            'API/tests/JSNode.h',
+            'API/tests/JSNodeList.c',
+            'API/tests/JSNodeList.h',
+            'API/tests/Node.c',
+            'API/tests/Node.h',
+            'API/tests/NodeList.c',
+            'API/tests/NodeList.h',
+            'API/tests/minidom.c',
+        ],
+        'minidom_support_files': [
+            'API/tests/minidom.js',
+        ],
+        'testapi_files': [
+            'API/tests/testapi.c',
+        ],
+        'testapi_support_files': [
+            'API/tests/testapi.js',
+        ],
+        'jsc_files': [
+            'jsc.cpp',
+        ],
     }
 }
index 3cb3d1dc440dc2fe5e444548f5f4eaadd50cd913..275f35cda6843e1eda7d8cc41da4cb0cff43e390 100644 (file)
@@ -10,338 +10,616 @@ __ZN3WTF25TCMalloc_Central_FreeList18FetchFromSpansSafeEv
 __ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
 __ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
 __ZN3WTF17TCMalloc_PageHeap6DeleteEPNS_4SpanE
+__ZN3WTF16fastZeroedMallocEm
 __ZN3WTF8fastFreeEPv
 __ZN3WTF19initializeThreadingEv
-__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
-__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3WTFL14threadMapMutexEv
+__ZN3WTF20initializeMainThreadEv
+__ZN3WTFL24initializeMainThreadOnceEv
+__ZN3WTF5MutexC1Ev
+__ZN3WTF28initializeMainThreadPlatformEv
 __ZN3JSC19initializeThreadingEv
 __ZN3JSCL23initializeThreadingOnceEv
+__ZN3WTF10StringImpl5emptyEv
 __ZN3WTF13WTFThreadDataC1Ev
-__ZN3JSC17initializeUStringEv
-__ZN7WebCore10StringImpl5emptyEv
+__ZN3WTF11StackBounds10initializeEv
 __ZN3JSC12JSGlobalData10storeVPtrsEv
-__ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoEj
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3WTF16fastZeroedMallocEm
-__ZN3JSC7JSArrayD1Ev
-__ZN3JSC7JSArrayD2Ev
-__ZN3JSC9StructureD1Ev
-__ZN3JSC9StructureD2Ev
-__ZN3JSC11JSByteArray15createStructureENS_7JSValueE
-__ZN3JSC11JSByteArrayD1Ev
-__ZN3JSC8JSStringD1Ev
-__ZN3JSC10JSFunctionC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC10JSFunctionC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC10JSFunctionD1Ev
-__ZN3JSC10JSFunctionD2Ev
-__ZN3JSC18VPtrHackExecutableD0Ev
-__ZN3WTF5MutexC1Ev
+__ZN3JSC7JSArrayC1ENS_6JSCell20VPtrStealingHackTypeE
+__ZN3JSC10JSFunctionC1ENS_6JSCell20VPtrStealingHackTypeE
 __ZN3WTF15initializeDatesEv
 __ZN3WTF11currentTimeEv
 __ZN3WTF8msToYearEd
+__ZN3JSC12RegisterFile19initializeThreadingEv
 __ZN3WTF39initializeMainThreadToProcessMainThreadEv
-__ZN3WTFL43initializeMainThreadToProcessMainThreadOnceEv
-__ZN3WTF47initializeMainThreadToProcessMainThreadPlatformEv
-__ZN3WTF20initializeMainThreadEv
-__ZN3WTF15ThreadConditionC1Ev
-__ZN7WebCore10StringImpl6createEPKtj
-__ZN7WebCore10StringImpl19createUninitializedEjRPt
+__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3WTF6StringC1EPKc
+__ZN3WTF10StringImpl6createEPKc
+__ZN3WTF10StringImpl6createEPKcj
+__ZN3WTF10StringImpl19createUninitializedEjRPt
+__ZN3WTF5equalEPKNS_10StringImplES2_
+__ZN3WTF10StringImpl6createEPKtj
+__ZN3WTF12isMainThreadEv
+__ZN3WTF10StringImplD1Ev
+__ZN3WTF10StringImplD2Ev
 __ZN3WTF5Mutex4lockEv
+__ZNK3WTF6String14threadsafeCopyEv
+__ZNK3WTF10StringImpl14threadsafeCopyEv
 __ZN3WTF5Mutex6unlockEv
-__ZNK7WebCore6String17crossThreadStringEv
-__ZN7WebCore10StringImpl17crossThreadStringEv
-__ZN7WebCore10StringImpl12sharedBufferEv
-__ZN7WebCore6StringC1EPKc
-__ZN7WebCore10StringImpl6createEPKc
-__ZN7WebCore10StringImpl6createEPKcj
-__ZNK7WebCore6String14threadsafeCopyEv
-__ZNK7WebCore10StringImpl14threadsafeCopyEv
-__ZN7WebCore10StringImpl8endsWithEPS0_b
-__ZN7WebCore10StringImpl4findEPS0_ib
-__ZN7WebCore10StringImplD1Ev
-__ZN7WebCore10StringImplD2Ev
-__ZN7WebCoreplERKNS_6StringEPKc
-__ZN7WebCore6String6appendERKS0_
-__ZN7WebCoreplERKNS_6StringES2_
+__ZN3WTF10StringImpl8endsWithEPS0_b
+__ZN3WTF13tryFastMallocEm
+__ZN3WTF7CString16newUninitializedEmRPc
+__ZN3WTF15ThreadConditionC1Ev
 __ZN3WTF12createThreadEPFPvS0_ES0_PKc
 __ZN3WTF20createThreadInternalEPFPvS0_ES0_PKc
 __ZN3WTFL35establishIdentifierForPthreadHandleERKP17_opaque_pthread_t
-__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTrai
+__ZN3WTF9HashTableIjSt4pairIjP17_opaque_pthread_tENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSA_IS3_EEEESB_E6rehashEi
+__ZN3WTF15ThreadCondition6signalEv
 __ZN3WTFL16threadEntryPointEPv
 __ZN3WTF31initializeCurrentThreadInternalEPKc
 __ZN3WTF20ThreadIdentifierData10initializeEj
 __ZN3WTF20ThreadIdentifierData23initializeKeyOnceHelperEv
 __ZN3WTF5MutexD1Ev
-__ZN3WTF12isMainThreadEv
-__ZN3WTF7CString16newUninitializedEmRPc
-__ZNK3WTF7CString4dataEv
-__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
-__ZN7WebCore6String29charactersWithNullTerminationEv
-__ZN7WebCore10StringImpl34createWithTerminatingNullCharacterERKS0_
+__ZNK3WTF6String4utf8Eb
+__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
+__ZN3WTF7CStringC1EPKcm
+__ZN3WTF7CString4initEPKcm
+__ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
+__ZN3WTF12AtomicString4initEv
+__ZN3WTF12AtomicString3addEPKc
+__ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_10StringHashENS_10HashTraitsIS2_EES7_E6rehashEi
+__ZNK3WTF6String9substringEjj
+__ZNK3WTF6String5lowerEv
+__ZN3WTF10StringImpl5lowerEv
+__ZN3WTF5equalEPKNS_10StringImplEPKc
+__ZN3WTF6StringC1EPKcj
+__ZN3WTF12AtomicString3addEPKtj
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKc
+__ZN3WTF6String6appendERKS0_
+__ZN3WTF6StringC1EPKtj
+__ZN3WTF18charactersToDoubleEPKtmPbS2_
+__ZN3WTF6strtodEPKcPPc
+__ZN3WTF10StringImpl22containsOnlyWhitespaceEv
+__ZN3WTF12AtomicString11addSlowCaseEPNS_10StringImplE
+__ZN3WTF12AtomicString6removeEPNS_10StringImplE
+__ZN3WTF6String6numberEy
+__ZN3WTF6String6formatEPKcz
+__ZN3WTF6VectorIcLm256EE4growEm
+__ZN3WTF10StringImpl11reverseFindEtj
+__ZN3WTF10StringImpl9substringEjj
+__ZN3WTF7CString11mutableDataEv
+__ZN3WTF7CString18copyBufferIfNeededEv
+__ZNK3WTF6String17crossThreadStringEv
+__ZN3WTF10StringImpl17crossThreadStringEv
+__ZN3WTF10StringImpl12sharedBufferEv
+__ZN3WTF6String29charactersWithNullTerminationEv
+__ZN3WTF10StringImpl34createWithTerminatingNullCharacterERKS0_
 __ZN3WTF13currentThreadEv
 __ZN3WTF20ThreadIdentifierData10identifierEv
-__ZNK7WebCore6String15stripWhiteSpaceEv
-__ZN7WebCore10StringImpl15stripWhiteSpaceEv
-__ZN7WebCore5equalEPKNS_10StringImplES2_
-__ZN7WebCoreplEPKcRKNS_6StringE
-__ZN7WebCore6StringC1EPKt
-__ZN7WebCore6StringC2EPKt
-__ZNK7WebCore6String7isEmptyEv
+__ZNK3WTF6String15stripWhiteSpaceEv
+__ZN3WTF10StringImpl15stripWhiteSpaceEv
+_JSStringCreateWithCFString
+_JSStringRetain
+_JSStringRelease
+__ZN3WTF6String6numberEi
 __ZN3WTF16callOnMainThreadEPFvPvES0_
-__ZN3WTF5DequeINS_19FunctionWithContextEE14expandCapacityEv
+__ZN3WTF5DequeINS_19FunctionWithContextELm0EE14expandCapacityEv
 __ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
-__ZN3WTF17TCMalloc_PageHeap3NewEm
-__ZN7WebCore12AtomicString4initEv
-__ZN3WTF7HashSetIPN7WebCore10StringImplENS1_10StringHashENS_10HashTraitsIS3_EEE3addIPKcNS1_17CStringTranslatorEEESt4pairINS_24H
-__ZN3WTF9HashTableIPN7WebCore10StringImplES3_NS_17IdentityExtractorIS3_EENS1_10StringHashENS_10HashTraitsIS3_EES8_E6rehashEi
-__ZN7WebCore12AtomicString3addEPKc
-__ZN7WebCore12AtomicString3addEPNS_10StringImplE
-__ZN7WebCore6StringC1EPKcj
-__ZN7WebCore5equalEPKNS_10StringImplEPKc
-__ZNK7WebCore6String6lengthEv
-__ZNK7WebCore6StringixEj
-__ZNK7WebCore6String9substringEjj
-__ZN7WebCore10StringImpl9substringEjj
-__ZNK7WebCore6String5lowerEv
-__ZN7WebCore10StringImpl5lowerEv
-__ZN7WebCore10StringImpl4findEti
-__ZNK7WebCore6String10charactersEv
-__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplES1_
-__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplEPKc
-__ZN7WebCore12AtomicString3addEPKtj
-__ZN3WTF7HashSetIPN7WebCore10StringImplENS1_10StringHashENS_10HashTraitsIS3_EEE3addINS1_11UCharBufferENS1_21UCharBufferTranslat
-__ZN7WebCore18charactersToDoubleEPKtmPb
-__ZN3WTF6strtodEPKcPPc
+__ZN3WTF6String8fromUTF8EPKc
+__ZN3WTF6String8fromUTF8EPKcm
+__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
+__ZN3WTF7CStringC1EPKc
+__ZN3WTF11fastReallocEPvm
+-[WTFMainThreadCaller call]
+__ZN3WTF31dispatchFunctionsFromMainThreadEv
+__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
+__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
 __ZN3WTF15ThreadCondition9broadcastEv
-__ZN3WTF15ThreadCondition6signalEv
-__ZN7WebCore12AtomicString6removeEPNS_10StringImplE
-__ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
-__ZN3JSC9Structure18startIgnoringLeaksEv
+__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
+__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
+__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
+__ZN3WTF20ThreadIdentifierData8destructEPv
+__ZN3WTF31clearPthreadHandleForIdentifierEj
+__ZN3WTF12detachThreadEj
+__ZN3WTFL26pthreadHandleForIdentifierEj
+__ZN3WTF14FastMallocZone4sizeEP14_malloc_zone_tPKv
+__ZN3WTF10StringImpl4findEtj
+___initializeScavenger_block_invoke_1
+__ZN3WTF23waitForThreadCompletionEjPPv
+__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_
+__ZN3WTF6StringC1EPKt
+__ZN3WTF6StringC2EPKt
+__ZNK3WTF6String5splitEtRNS_6VectorIS0_Lm0EEE
+__ZNK3WTF6String5splitERKS0_bRNS_6VectorIS0_Lm0EEE
+__ZN3WTF10StringImpl4findEPS0_j
+__ZN3WTF6VectorINS_6StringELm0EE14expandCapacityEm
+_JSGlobalContextCreate
+__ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
+__ZN3JSCL17createJSLockCountEv
+__ZN3JSC12JSGlobalData14sharedInstanceEv
 __ZN3JSC12JSGlobalDataC2ENS0_14GlobalDataTypeENS_15ThreadStackTypeE
+__ZN3JSC21createIdentifierTableEv
 __ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
 __ZN3JSC17CommonIdentifiersC2EPNS_12JSGlobalDataE
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc
-__ZN3WTF7HashSetIPN7WebCore10StringImplENS1_10StringHashENS_10HashTraitsIS3_EEE3addIPKcN3JSC27IdentifierCStringTranslatorEEESt4
-__ZN3WTF9HashTableIPN7WebCore10StringImplES3_NS_17IdentityExtractorIS3_EENS1_10StringHashENS_10HashTraitsIS3_EES8_E6expandEv
-__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrIN7WebCore10StringImplEEEENS_18PairFirstExtractorIS8_EENS_7PtrHashIS2_EENS_14PairHas
+__ZN3JSC15IdentifierTable3addIPKcNS_27IdentifierCStringTranslatorEEESt4pairIN3WTF29HashTableConstIteratorAdapterINS6_9HashTableIPNS6_10StringImplESA_NS6_17IdentityExtractorISA_EENS6_10StringHashENS6_10HashTraitsISA_EESF_EESA_EEbET_
+__ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_10StringHashENS_10HashTraitsIS2_EES7_E6expandEv
+__ZN3WTF9HashTableIPKcSt4pairIS2_NS_6RefPtrINS_10StringImplEEEENS_18PairFirstExtractorIS7_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSD_IS6_EEEESE_E6expandEv
+__ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_10StringHashENS_10HashTraitsIS2_EES7_E4findIS2_NS_22IdentityHashTranslatorIS2_S2_S5_EEEENS_17HashTableIteratorIS2_S2_S4_S5_S7_S7_EERKT_
 __ZN3JSC10IdentifierC1EPNS_12JSGlobalDataEPKc
 __ZN3JSC12SmallStringsC1Ev
 __ZN3JSC19ExecutableAllocator17intializePageSizeEv
+__ZNK3JSC19ExecutableAllocator7isValidEv
+__ZN3WTF11OSAllocator18reserveUncommittedEmNS0_5UsageEbb
 __ZN3JSC14ExecutablePool11systemAllocEm
+__ZN3WTF11OSAllocator6commitEPvmbb
 __ZN3JSC5LexerC1EPNS_12JSGlobalDataE
 __ZN3JSC11ParserArenaC1Ev
 __ZN3JSC11ParserArenaC2Ev
-__ZN3JSC11InterpreterC1Ev
-__ZN3JSC11InterpreterC2Ev
+__ZN3JSC14TimeoutCheckerC1Ev
+__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
+__ZN3JSC4HeapC2EPNS_12JSGlobalDataE
+__ZN3JSC11MarkedSpaceC1EPNS_12JSGlobalDataE
+__ZN3JSC25DefaultGCActivityCallbackC1EPNS_4HeapE
+__ZN3JSC25DefaultGCActivityCallback17commonConstructorEPNS_4HeapEP11__CFRunLoop
+__ZN3JSC14MachineThreadsC1EPNS_4HeapE
+__ZN3JSC9MarkStack18initializePagesizeEv
+__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbb
+__ZN3JSC10HandleHeapC1EPNS_12JSGlobalDataE
+__ZN3WTF10BlockStackIN3JSC10HandleHeap4NodeEE4growEv
+__ZN3WTF6VectorIPN3JSC10HandleHeap4NodeELm0EE15reserveCapacityEm
+__ZN3JSC11HandleStackC1Ev
+__ZN3WTF10BlockStackIN3JSC7JSValueEE4growEv
+__ZN3WTF6VectorIPN3JSC7JSValueELm0EE15reserveCapacityEm
+__ZN3JSC25DefaultGCActivityCallbackclEv
+__ZN3JSC11RegExpCacheC1EPNS_12JSGlobalDataE
+__ZN3JSC11InterpreterC1ERNS_12JSGlobalDataE
+__ZN3JSC10HandleHeap12writeBarrierEPNS_7JSValueERKS1_
+__ZN3JSC12RegisterFile23addToCommittedByteCountEl
+__ZN3JSC11MarkedSpace21allocateFromSizeClassERNS0_9SizeClassE
+__ZN3JSC11MarkedSpace13allocateBlockERNS0_9SizeClassE
+__ZN3JSC11MarkedBlock6createEPNS_12JSGlobalDataEm
+__ZN3WTF21PageAllocationAligned8allocateEmmNS_11OSAllocator5UsageEbb
+__ZN3WTF9HashTableIPN3JSC11MarkedBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC6JSCellD1Ev
+__ZN3JSC9StructureC1ERNS_12JSGlobalDataE
+__ZN3JSC6StrongINS_9StructureEE3setERNS_12JSGlobalDataEPS1_
+__ZN3JSC9Structure6createERNS_12JSGlobalDataENS_7JSValueERKNS_8TypeInfoEjPKNS_9ClassInfoE
+__ZN3JSC9StructureC1ERNS_12JSGlobalDataENS_7JSValueERKNS_8TypeInfoEjPKNS_9ClassInfoE
+__ZN3WTF13wtfThreadDataEv
+__ZN3JSC27startProfilerServerIfNeededEv
++[ProfilerServer sharedProfileServer]
+-[ProfilerServer init]
 __ZN3JSC9JITThunksC1EPNS_12JSGlobalDataE
+__ZN3JSC9JITThunksC2EPNS_12JSGlobalDataE
 __ZN3JSC3JITC1EPNS_12JSGlobalDataEPNS_9CodeBlockE
 __ZN3JSC3JITC2EPNS_12JSGlobalDataEPNS_9CodeBlockE
-__ZN3JSC3JIT35privateCompileCTIMachineTrampolinesEPN3WTF6RefPtrINS_14ExecutablePoolEEEPNS_12JSGlobalDataEPNS_19TrampolineStruct
-__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common9ConditionENS_12X86Registers10RegisterIDES4_
+__ZN3JSC3JIT35privateCompileCTIMachineTrampolinesEPN3WTF6RefPtrINS_14ExecutablePoolEEEPNS_12JSGlobalDataEPNS_19TrampolineStructureE
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common15ResultConditionENS_12X86Registers10RegisterIDES4_
 __ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDE
 __ZN3JSC12X86Assembler3jCCENS0_9ConditionE
+__ZN3JSC15AssemblerBuffer11ensureSpaceEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_12X86Registers10RegisterIDEi
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_19RelationalConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32E
 __ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDE
-__ZN3JSC15AssemblerBuffer11ensureSpaceEi
-__ZN3JSC20MacroAssemblerX86_644callEv
-__ZN3JSC20MacroAssemblerX86_647loadPtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE15ImplicitAddressENS_12X86Registers10Regi
-__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDENS_12X86Registers10RegisterIDE
 __ZN3JSC3JIT32compileOpCallInitializeCallFrameEv
-__ZN3JSC15AssemblerBuffer4growEi
-__ZN3WTF11fastReallocEPvm
-__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common15ResultConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32E
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDENS_12X86Registers10RegisterIDE
+__ZN3WTF6VectorIcLm128EE14expandCapacityEm
+__ZN3WTF6VectorIcLm128EE4growEm
+__ZN3JSC3JIT27privateCompileCTINativeCallEPNS_12JSGlobalDataEb
+__ZNK3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE4Jump4linkEPS2_
 __ZN3WTF10RefCountedIN3JSC14ExecutablePoolEE5derefEv
-__ZN3JSC14TimeoutCheckerC1Ev
-__ZN3JSC4HeapC1EPNS_12JSGlobalDataE
-__ZN3JSC4Heap13allocateBlockEv
-__ZN3JSC9MarkStack18initializePagesizeEv
-__ZN3JSC9MarkStack13allocateStackEm
-__ZN3JSC27startProfilerServerIfNeededEv
-+[ProfilerServer sharedProfileServer]
--[ProfilerServer init]
-__ZN3JSC9Structure17stopIgnoringLeaksEv
-__ZNK7WebCore6String6latin1Ev
-__ZNK3WTF7CString6lengthEv
-__ZN7WebCore10StringImpl22containsOnlyWhitespaceEv
-__ZN7WebCore12AtomicString3addEPKt
-__ZN7WebCore10StringImpl11reverseFindEPS0_ib
-__ZN7WebCore10StringImpl5adoptERNS_12StringBufferE
-__ZNK7WebCore6String5splitEtRN3WTF6VectorIS0_Lm0EEE
-__ZNK7WebCore6String5splitERKS0_bRN3WTF6VectorIS0_Lm0EEE
--[WTFMainThreadCaller call]
-__ZN3WTF31dispatchFunctionsFromMainThreadEv
-__ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
-__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
-__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
-__ZN3WTF20TCMalloc_ThreadCache18DestroyThreadCacheEPv
-__ZN3WTF20TCMalloc_ThreadCache11DeleteCacheEPS0_
-__ZN3WTF25TCMalloc_Central_FreeList11InsertRangeEPvS1_i
-__ZN3WTF25TCMalloc_Central_FreeList18ReleaseListToSpansEPv
-__ZN3WTF20ThreadIdentifierData8destructEPv
-__ZN3WTF31clearPthreadHandleForIdentifierEj
-__ZN3WTF12detachThreadEj
-__ZN3WTFL26pthreadHandleForIdentifierEj
-__ZN7WebCore6StringC1EPKtj
-__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
-__ZL30calculateCompiledPatternLengthPKti24JSRegExpIgnoreCaseOptionR11CompileDataR9ErrorCode
-__ZL11checkEscapePPKtS0_P9ErrorCodeib
-__ZL13compileBranchiPiPPhPPKtS3_P9ErrorCodeS_S_R11CompileData
-__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
-__ZL5matchPKtPKhiR9MatchData
-__ZN7WebCore6String6formatEPKcz
-__ZNK7WebCore6String19characterStartingAtEj
-__ZN7WebCore10StringImpl19characterStartingAtEj
-__ZN3WTF25TCMalloc_Central_FreeList11ShrinkCacheEib
-__ZNK7WebCore6String16removeCharactersEPFbtE
-__ZN7WebCore10StringImpl16removeCharactersEPFbtE
-__ZN7WebCore10StringImpl7replaceEtt
-__ZNK7WebCore6String4utf8Ev
-__ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
-__ZN3WTF7CStringC1EPKcj
-__ZN3WTF7CString4initEPKcj
-__ZN7WebCore10StringImpl4findEPFbtEi
-__ZN3JSC4Heap8allocateEm
-__ZN3JSC6JSCellD1Ev
-__ZN3JSC4Heap7protectENS_7JSValueE
-__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraits
+__ZN3JSC14MachineThreads29makeUsableFromMultipleThreadsEv
+_JSGlobalContextCreateInGroup
+__ZN3JSC4Heap16activityCallbackEv
+__ZN3JSC25DefaultGCActivityCallback11synchronizeEv
+__ZN3JSC14TimeoutChecker5resetEv
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3WTF12randomNumberEv
+__ZN3WTF29cryptographicallyRandomNumberEv
+__ZN3WTF35cryptographicallyRandomValuesFromOSEPhm
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject5resetENS_7JSValueE
-__ZN3JSC17FunctionPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3JSC17FunctionPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC17FunctionPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureERKNS_10IdentifierE
+__ZN3JSC24JSObjectWithGlobalObjectC2EPNS_14JSGlobalObjectEPNS_9StructureE
 __ZN3JSC7UStringC1EPKc
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
-__ZN3JSC8JSObject17putDirectInternalERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotEPNS_6JSCellE
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
-__ZN3JSC9Structure3getEPKN7WebCore10StringImplERjRPNS_6JSCellE
-__ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
-__ZN3JSC9Structure3putERKNS_10IdentifierEjPNS_6JSCellE
-__ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE
-__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_9StructureEPPNS_10JSFunctionES7_
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjec
-__ZN3JSC10JSFunctionC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjec
-__ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_16InternalFunctionEj
-__ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
-__ZN3JSC15ObjectPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC15ObjectPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC9Structure26rehashPropertyMapHashTableEj
-__ZN3JSC8JSObject17createInheritorIDEv
-__ZN3JSC14ArrayPrototypeC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC15StringPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC16BooleanPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC16BooleanPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC13BooleanObjectC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC15NumberPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC15NumberPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC12NumberObjectC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC13DatePrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC12DateInstanceC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC15RegExpPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC14ErrorPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_
-__ZN3JSC13ErrorInstanceC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC20NativeErrorPrototypeC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringES9_
-__ZN3JSC20NativeErrorPrototypeC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringES9_
-__ZN3JSC17ObjectConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeEPS5_
-__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15ObjectPrototypeEPS5_
-__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
-__ZN3JSC19FunctionConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
-__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_17FunctionPrototypeE
-__ZNK3JSC16InternalFunction9classInfoEv
-__ZN3JSC16ArrayConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeEPS5_
-__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ArrayPrototypeEPS5_
-__ZNK3JSC14ArrayPrototype9classInfoEv
-__ZN3JSC17StringConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
-__ZN3JSC17StringConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_15StringPrototypeE
-__ZNK3JSC15StringPrototype9classInfoEv
-__ZN3JSC9JITThunks16specializedThunkEPNS_12JSGlobalDataEPFN3WTF10PassRefPtrINS_16NativeExecutableEEES2_PNS_14ExecutablePoolEE
-__ZN3JSC26fromCharCodeThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList6appendENS2_4JumpE
-__ZN3JSCL12charToStringERNS_19SpecializedThunkJITEPNS_12JSGlobalDataENS_12X86Registers10RegisterIDES5_S5_
-__ZN3JSC19SpecializedThunkJIT8finalizeEv
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPNS_16NativeExecutableEPFNS_7
-__ZN3JSC10JSFunctionC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPNS_16NativeExecutableEPFNS_7
+__ZN3JSC9Structure3getERNS_12JSGlobalDataEPN3WTF10StringImplERjRPNS_6JSCellE
+__ZN3JSC9Structure21addPropertyTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
+__ZN3JSC9Structure17createPropertyMapEj
+__ZN3WTF14deleteOwnedPtrIN3JSC13PropertyTableEEEvPT_
+__ZN3JSC9Structure16putSpecificValueERNS_12JSGlobalDataERKNS_10IdentifierEjPNS_6JSCellE
+__ZN3JSC24StructureTransitionTable3addERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC9Structure28addPropertyWithoutTransitionERNS_12JSGlobalDataERKNS_10IdentifierEjPNS_6JSCellE
 __ZN3JSC8JSObject23allocatePropertyStorageEmm
-__ZN3JSC18BooleanConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
-__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_16BooleanPrototypeE
-__ZNK3JSC13BooleanObject9classInfoEv
-__ZN3JSC17NumberConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
-__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15NumberPrototypeE
-__ZN3JSC15DateConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
-__ZN3JSC15DateConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPS5_PNS_13DatePrototypeE
-__ZNK3JSC13DatePrototype9classInfoEv
-__ZN3JSC17RegExpConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
-__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_15RegExpPrototypeE
-__ZN3JSC16ErrorConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
-__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_14ErrorPrototypeE
-__ZNK3JSC13ErrorInstance9classInfoEv
-__ZN3JSC22NativeErrorConstructorC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
-__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_20NativeErrorPrototypeE
-__ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
-__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN7WebCore10StringImplE
-__ZN3WTF7HashSetIPN7WebCore10StringImplENS1_10StringHashENS_10HashTraitsIS3_EEE3addERKS3_
-__ZN3JSC10MathObjectC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC10MathObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC17FunctionPrototype21addFunctionPropertiesEPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPPNS_10JSFunctionES9_
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPFPvS2_E
+__ZN3JSC10JSFunctionC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPFPvS2_E
+__ZN3JSC12JSGlobalData15getHostFunctionEPFPvPNS_9ExecStateEE
+__ZN3JSC9JITThunks16hostFunctionStubEPNS_12JSGlobalDataEPFPvPNS_9ExecStateEE
+__ZN3WTF7HashMapIPFPvPN3JSC9ExecStateEENS2_4WeakINS2_16NativeExecutableEEENS_7PtrHashIS6_EENS_10HashTraitsIS6_EENSC_IS9_EEE3addERKS6_RKS9_
+__ZN3WTF9HashTableIPFPvPN3JSC9ExecStateEESt4pairIS6_NS2_4WeakINS2_16NativeExecutableEEEENS_18PairFirstExtractorISB_EENS_7PtrHashIS6_EENS_14PairHashTraitsINS_10HashTraitsIS6_EENSH_ISA_EEEESI_E6expandEv
+__ZN3JSC3JIT27privateCompileCTINativeCallEN3WTF10PassRefPtrINS_14ExecutablePoolEEEPNS_12JSGlobalDataEPFPvPNS_9ExecStateEE
+__ZN3JSC16NativeExecutable6createERNS_12JSGlobalDataENS_21MacroAssemblerCodePtrEPFPvPNS_9ExecStateEES3_S8_
+__ZN3JSC8JSObject34putDirectFunctionWithoutTransitionEPNS_9ExecStateEPNS_10JSFunctionEj
+__ZN3JSC10JSFunction4nameEPNS_9ExecStateE
+__ZN3JSC15ObjectPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC8JSObject17createInheritorIDERNS_12JSGlobalDataE
+__ZN3JSC14ArrayPrototypeC1EPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC15StringPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC15StringPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEPNS_9StructureE
+__ZN3JSC16BooleanPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC13BooleanObjectC2ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC15NumberPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC12NumberObjectC2ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC13DatePrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC12DateInstanceC2EPNS_9ExecStateEPNS_9StructureE
+__ZN3JSC12nonInlineNaNEv
+__ZN3JSC15RegExpPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC15RegExpPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE
+__ZN3JSC6RegExp7compileEPNS_12JSGlobalDataE
+__ZN3JSC4Yarr11YarrPatternC1ERKNS_7UStringEbbPPKc
+__ZN3JSC4Yarr11YarrPattern7compileERKNS_7UStringE
+__ZN3WTF6VectorIPN3JSC4Yarr18PatternAlternativeELm0EE14expandCapacityEm
+__ZN3JSC4Yarr6ParserINS0_22YarrPatternConstructorEE5parseEv
+__ZN3JSC4Yarr10jitCompileERNS0_11YarrPatternEPNS_12JSGlobalDataERNS0_13YarrCodeBlockE
+__ZN3JSC4Yarr13YarrGenerator13opCompileBodyEPNS0_18PatternDisjunctionE
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EED1Ev
+__ZN3JSC4Yarr13YarrGenerator20opCompileAlternativeEPNS0_18PatternAlternativeE
+__ZN3JSC4Yarr13YarrGenerator8generateEv
+__ZN3JSC4Yarr13YarrGenerator22jumpIfNoAvailableInputEj
+__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList6appendENS2_4JumpE
+__ZN3JSC4Yarr13YarrGenerator9backtrackEv
+__ZN3JSC4Yarr13YarrGenerator17BacktrackingState4linkEPNS_14MacroAssemblerE
+__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList4linkEPS2_
+__ZN3JSC12X86Assembler7addl_irEiNS_12X86Registers10RegisterIDE
+__ZN3JSC14MacroAssembler4jumpENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelE
+__ZN3WTF15deleteAllValuesIPN3JSC4Yarr18PatternDisjunctionELm4EEEvRKNS_6VectorIT_XT0_EEE
+__ZN3WTF15deleteAllValuesIPN3JSC4Yarr14CharacterClassELm0EEEvRKNS_6VectorIT_XT0_EEE
+__ZN3JSC12RegExpObjectC2EPNS_14JSGlobalObjectEPNS_9StructureEN3WTF17NonNullPassRefPtrINS_6RegExpEEE
+__ZN3JSC14ErrorPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC13ErrorInstanceC2EPNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC17ObjectConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15ObjectPrototypeE
+__ZN3JSC17ObjectConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15ObjectPrototypeE
+__ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
+__ZN3JSC19FunctionConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_17FunctionPrototypeE
+__ZN3JSC19FunctionConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_17FunctionPrototypeE
+__ZN3JSC16ArrayConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_14ArrayPrototypeE
+__ZN3JSC16ArrayConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_14ArrayPrototypeE
+__ZN3JSC17StringConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15StringPrototypeE
+__ZN3JSC17StringConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15StringPrototypeE
+__ZN3JSC18BooleanConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_16BooleanPrototypeE
+__ZN3JSC18BooleanConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_16BooleanPrototypeE
+__ZN3JSC17NumberConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15NumberPrototypeE
+__ZN3JSC17NumberConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15NumberPrototypeE
+__ZN3JSC15DateConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_13DatePrototypeE
+__ZN3JSC15DateConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_13DatePrototypeE
+__ZN3JSC17RegExpConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15RegExpPrototypeE
+__ZN3JSC17RegExpConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_15RegExpPrototypeE
+__ZN3JSC16ErrorConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_14ErrorPrototypeE
+__ZN3JSC16ErrorConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEPNS_14ErrorPrototypeE
+__ZN3JSC22NativeErrorConstructorC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureES6_RKNS_7UStringE
+__ZN3JSC22NativeErrorConstructorC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureES6_RKNS_7UStringE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN3WTF10StringImplE
+__ZN3JSC15IdentifierTable3addEPN3WTF10StringImplE
+__ZN3JSC20NativeErrorPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureERKNS_7UStringEPNS_22NativeErrorConstructorE
+__ZN3JSC20NativeErrorPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureERKNS_7UStringEPNS_22NativeErrorConstructorE
+__ZN3JSC10IdentifierC1EPNS_9ExecStateEPKc
+__ZN3JSC10MathObjectC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC10MathObjectC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE
 __ZN3JSC12SmallStrings24singleCharacterStringRepEh
 __ZN3JSC19SmallStringsStorageC2Ev
-__ZN3JSC18GlobalEvalFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_
-__ZN3JSC17PrototypeFunctionC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8
-__ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE
-__ZN3JSC9Structure17copyPropertyTableEv
-__ZN3WTF10RefCountedIN3JSC9StructureEE5derefEv
+__ZN3JSC10JSONObjectC1EPNS_14JSGlobalObjectEPNS_9StructureE
+__ZN3JSC14JSGlobalObject16addStaticGlobalsEPNS0_18GlobalPropertyInfoEi
+__ZN3WTF7HashMapINS_6RefPtrINS_10StringImplEEEN3JSC16SymbolTableEntryENS4_17IdentifierRepHashENS_10HashTraitsIS3_EENS4_26SymbolTableIndexHashTraitsEE3addEPS2_RKS5_
+__ZN3JSC9Structure25changePrototypeTransitionERNS_12JSGlobalDataEPS0_NS_7JSValueE
+__ZN3JSC9Structure17copyPropertyTableERNS_12JSGlobalDataEPS0_
 __ZN3JSC14JSGlobalObject10globalExecEv
-__ZN3JSC4Heap9unprotectENS_7JSValueE
-__ZN3JSC14TimeoutChecker5resetEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
+_JSGlobalContextRetain
+__ZN3JSC14MachineThreads16addCurrentThreadEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
-__ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
-__ZN3JSC17ProgramExecutable7compileEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCod
-__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
-__ZN3JSC5Lexer7setCodeERKNS_10SourceCodeERNS_11ParserArenaE
-__Z10jscyyparsePv
-__ZN3JSC5Lexer3lexEPvS1_
+__ZN3JSC4Heap7protectENS_7JSValueE
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E4findIS3_NS_22IdentityHashTranslatorIS3_S5_S9_EEEENS_17HashTableIteratorIS3_S5_S7_S9_SE_SC_EERKT_
+__ZN3WTF9HashTableIPN3JSC6JSCellESt4pairIS3_jENS_18PairFirstExtractorIS5_EENS_7PtrHashIS3_EENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
+_JSValueMakeFromJSONString
+__ZNK14OpaqueJSString7ustringEv
+__ZN3JSC7UStringC1EPKtj
+__ZN3JSC13LiteralParser5Lexer3lexERNS1_18LiteralParserTokenE
+__ZN3JSC13LiteralParser5parseENS0_11ParserStateE
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3WTF13StringBuilder6appendEPKtj
+__ZN3WTF13StringBuilder19appendUninitializedEj
+__ZN3WTF13StringBuilder14allocateBufferEPKtj
+__ZN3WTF13StringBuilder11shrinkToFitEv
+__ZN3WTF13StringBuilder11reifyStringEv
+__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
+__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC7JSArray20increaseVectorLengthEj
+__ZN3WTF14tryFastReallocEPvm
+_JSValueIsNull
+_JSValueIsUndefined
+_JSValueIsBoolean
+_JSValueIsNumber
+_JSValueIsString
+_JSValueToObject
+__ZN3JSC12APIEntryShimC1EPNS_9ExecStateEb
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
+_JSContextGetGlobalObject
+__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+_JSStringCreateWithUTF8CString
+_JSObjectGetProperty
+__ZNK14OpaqueJSString10identifierEPN3JSC12JSGlobalDataE
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKti
-__ZN3WTF7HashSetIPN7WebCore10StringImplENS1_10StringHashENS_10HashTraitsIS3_EEE3addIN3JSC11UCharBufferENS9_31IdentifierUCharBuf
+__ZN3JSC14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_JSValueIsInstanceOfConstructor
+__ZN3JSC16ArrayConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
+__ZN3JSC6JSCell9getObjectEv
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_JSValueToNumber
+_JSObjectGetPropertyAtIndex
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+_JSValueToStringCopy
+__ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
+__ZN14OpaqueJSString6createERKN3JSC7UStringE
+_JSStringCopyCFString
+_JSObjectCopyPropertyNames
+__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9Structure16getPropertyNamesERNS_12JSGlobalDataERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9ExecState20objectPrototypeTableEPS0_
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
+_JSPropertyNameArrayGetCount
+_JSPropertyNameArrayRelease
+_JSGlobalContextRelease
+__ZN3JSC4Heap9unprotectENS_7JSValueE
+__ZN3JSC10HandleHeap4growEv
+__ZN3JSC37DefaultGCActivityCallbackPlatformData7triggerEP16__CFRunLoopTimerPv
+__ZN3JSC4Heap17collectAllGarbageEv
+__ZN3JSC12JSGlobalData23recompileAllJSFunctionsEv
+__ZN3JSC4Heap5resetENS0_11SweepToggleE
+__ZN3JSC4Heap9markRootsEv
+__ZN3JSC14MachineThreads23gatherConservativeRootsERNS_17ConservativeRootsEPv
+__ZN3JSC14MachineThreads23gatherFromCurrentThreadERNS_17ConservativeRootsEPv
+__ZN3JSC17ConservativeRoots3addEPvS1_
+__ZN3JSC12RegisterFile23gatherConservativeRootsERNS_17ConservativeRootsE
+__ZN3JSC11MarkedSpace10clearMarksEv
+__ZN3JSC9MarkStack6appendERNS_17ConservativeRootsE
+__ZN3JSC9MarkStack5drainEv
+__ZN3JSC4Heap20markProtectedObjectsERNS_15HeapRootVisitorE
+__ZN3JSC4Heap19markTempSortVectorsERNS_15HeapRootVisitorE
+__ZN3JSC10HandleHeap17markStrongHandlesERNS_15HeapRootVisitorE
+__ZN3JSC9MarkStack13visitChildrenEPNS_6JSCellE
+__ZN3JSC9Structure13visitChildrenERNS_9MarkStackE
+__ZN3JSC11HandleStack4markERNS_15HeapRootVisitorE
+__ZN3JSC12SmallStrings13visitChildrenERNS_15HeapRootVisitorE
+__ZN3JSC10HandleHeap15markWeakHandlesERNS_15HeapRootVisitorE
+__ZN3JSC9MarkStack5resetEv
+__ZN3JSC10HandleHeap19finalizeWeakHandlesEv
+__ZN3JSC11MarkedSpace5resetEv
+__ZN3JSC11MarkedSpace5sweepEv
+__ZN3JSC11MarkedBlock5sweepEv
+__ZN3JSC9StructureD1Ev
+__ZN3JSC8JSStringD1Ev
+__ZN3JSC10JSFunctionD1Ev
+__ZN3JSC14ArrayPrototypeD1Ev
+__ZN3JSC7JSArrayD2Ev
+__ZN3JSC13DatePrototypeD1Ev
+__ZN3JSC13JSFinalObjectD1Ev
+__ZN3JSC7JSArrayD1Ev
+__ZN3JSC14ScopeChainNodeD1Ev
+__ZN3JSC15ObjectPrototypeD1Ev
+__ZN3JSC15StringPrototypeD1Ev
+__ZN3JSC16BooleanPrototypeD1Ev
+__ZN3JSC15NumberPrototypeD1Ev
+__ZN3JSC15RegExpPrototypeD1Ev
+__ZN3JSC12RegExpObjectD2Ev
+__ZN3JSC6RegExpD1Ev
+__ZN3JSC14ErrorPrototypeD1Ev
+__ZN3JSC17RegExpConstructorD1Ev
+__ZN3JSC22NativeErrorConstructorD1Ev
+__ZN3JSC17FunctionPrototypeD1Ev
+__ZN3JSC17ObjectConstructorD1Ev
+__ZN3JSC19FunctionConstructorD1Ev
+__ZN3JSC16ArrayConstructorD1Ev
+__ZN3JSC17StringConstructorD1Ev
+__ZN3JSC18BooleanConstructorD1Ev
+__ZN3JSC17NumberConstructorD1Ev
+__ZN3JSC15DateConstructorD1Ev
+__ZN3JSC16ErrorConstructorD1Ev
+__ZN3JSC20NativeErrorPrototypeD1Ev
+__ZN3JSC10MathObjectD1Ev
+__ZN3JSC10JSONObjectD1Ev
+__ZN3JSC16NativeExecutableD1Ev
+__ZN3JSC14JSGlobalObjectD1Ev
+__ZN3JSC14JSGlobalObjectD2Ev
+__ZN3WTF9HashTableINS_6RefPtrI21OpaqueJSWeakObjectMapEES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E15deallocateTableEPS3_i
+__ZN3WTF9HashTableINS_6RefPtrI21OpaqueJSWeakObjectMapEES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3JSC11MarkedSpace6shrinkEv
+__ZN3JSC11MarkedSpace10freeBlocksERN3WTF16DoublyLinkedListINS_11MarkedBlockEEE
+__ZN3JSC11MarkedBlock7destroyEPS0_
+__ZN3WTF21PageAllocationAligned10deallocateEv
+__ZNK3JSC11MarkedSpace4sizeEv
+__Z22TCMalloc_SystemReleasePvm
+__Z21TCMalloc_SystemCommitPvm
+__ZN3WTFL10timerFiredEP16__CFRunLoopTimerPv
+__ZN3WTF15ThreadConditionD1Ev
+__ZNK3WTF6String5toIntEPb
+__ZN3WTF10StringImpl5toIntEPb
+__ZN3WTF15charactersToIntEPKtmPb
+__ZN3WTF22charactersToUIntStrictEPKtmPbi
+__ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEm
+__ZN3JSC4Yarr6ParserINS0_22YarrPatternConstructorEE28CharacterClassParserDelegate20atomPatternCharacterEtb
+__ZN3JSC4Yarr25CharacterClassConstructor14addSortedRangeERN3WTF6VectorINS0_14CharacterRangeELm0EEEtt
+__ZN3WTF6VectorIN3JSC4Yarr14CharacterRangeELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIN3JSC4Yarr14CharacterRangeELm0EE14expandCapacityEm
+__ZN3JSC4Yarr6ParserINS0_22YarrPatternConstructorEE11parseEscapeILb1ENS3_28CharacterClassParserDelegateEEEbRT0_
+__ZN3JSC4Yarr25CharacterClassConstructor7putCharEt
+__ZN3WTF6VectorItLm0EE14expandCapacityEm
+__ZN3JSC4Yarr22YarrPatternConstructor21atomCharacterClassEndEv
+__ZN3WTF6VectorIPN3JSC4Yarr14CharacterClassELm0EE14expandCapacityEm
+__ZN3JSC4Yarr22YarrPatternConstructor20atomPatternCharacterEt
+__ZN3JSC4Yarr6ParserINS0_22YarrPatternConstructorEE11parseEscapeILb0ES2_EEbRT0_
+__ZN3JSC4Yarr11byteCompileERNS0_11YarrPatternEPN3WTF20BumpPointerAllocatorE
+__ZN3WTF6VectorIN3JSC4Yarr8ByteTermELm0EE14expandCapacityEm
+__ZN3JSC4Yarr12ByteCompiler15emitDisjunctionEPNS0_18PatternDisjunctionEjj
+__ZN3JSC4Yarr13newlineCreateEv
+__ZN3JSC4Yarr14wordcharCreateEv
+__ZN3JSC4Yarr9interpretEPNS0_15BytecodePatternEPKtjjPi
+__ZN3JSC4Yarr11Interpreter16matchDisjunctionEPNS0_15ByteDisjunctionEPNS1_18DisjunctionContextEb
+__ZN3WTF10StringImpl23reverseFindIgnoringCaseEPS0_j
+__ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
+__ZN3WTF10StringImpl5adoptERNS_12StringBufferE
+__ZN3WTF10StringImpl7replaceEtt
+__ZNK3WTF6String16removeCharactersEPFbtE
+__ZN3WTF10StringImpl16removeCharactersEPFbtE
+__ZN3WTF10StringImpl4findEPFbtEj
+__ZN3JSC24JSObjectWithGlobalObjectC2ERNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureE
+_JSContextGetGlobalContext
+_JSWeakObjectMapCreate
+__ZN3JSC14JSGlobalObject17weakMapsFinalizerEv
+_JSWeakObjectMapGet
+_JSClassCreate
+__ZN13OpaqueJSClass6createEPK17JSClassDefinition
+__ZN13OpaqueJSClassC2EPK17JSClassDefinitionPS_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_P16StaticValueEntryENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E6expandEv
+_JSClassRetain
+_JSObjectMake
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEEC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEP13OpaqueJSClassPv
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE4initEPNS_9ExecStateE
+__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
+_JSObjectGetPrivate
+__ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN13OpaqueJSClass9prototypeEPN3JSC9ExecStateE
+__ZN13OpaqueJSClass11contextDataEPN3JSC9ExecStateE
+__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS5_EEEESD_E6expandEv
+__ZN24OpaqueJSClassContextDataC2ERN3JSC12JSGlobalDataEP13OpaqueJSClass
+_JSWeakObjectMapSet
+__ZN3WTF9HashTableIPvSt4pairIS1_PN3JSC7JSValueEENS_18PairFirstExtractorIS6_EENS_7PtrHashIS1_EENS_14PairHashTraitsINS_10HashTraitsIS1_EENSC_IS5_EEEESD_E6rehashEi
+_JSObjectSetProperty
+__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC10Identifier8toUInt32ERKNS_7UStringERb
+__ZN3WTF12AtomicString4findEPKtjj
+__ZNK3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_10StringHashENS_10HashTraitsIS2_EES7_E4findINS_17HashAndCharactersENS_24HashSetTranslatorAdapterIS2_S7_SA_NS_27HashAndCharactersTranslatorEEEEENS_22HashTableConstIteratorIS2_S2_S4_S5_S7_S7_EERKT_
+__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
+__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8evaluateEPNS_9ExecStateEPNS_14ScopeChainNodeERKNS_10SourceCodeENS_7JSValueE
+__ZN3JSC17ProgramExecutableC1EPNS_9ExecStateERKNS_10SourceCodeE
+__ZN3JSC11Interpreter7executeEPNS_17ProgramExecutableEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectE
+__ZN3JSC24DynamicGlobalObjectScopeC1ERNS_12JSGlobalDataEPNS_14JSGlobalObjectE
+__ZN3JSC19ExecutableAllocator19underMemoryPressureEv
+__ZN3JSC12JSGlobalData14resetDateCacheEv
+__ZN3JSC17ProgramExecutable15compileInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_11ProgramNodeEEEN3WTF10PassRefPtrIT_EEPNS_14JSGlobalObjectEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPNS_18FunctionParametersENS_18JSParserStrictnessEPPNS_8JSObjectE
+__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPNS_18FunctionParametersENS_18JSParserStrictnessENS_12JSParserModeEPiPNS_7UStringE
+__ZN3JSC5Lexer7setCodeERKNS_10SourceCodeERNS_11ParserArenaE
+__ZN3JSC7jsParseEPNS_12JSGlobalDataEPNS_18FunctionParametersENS_18JSParserStrictnessENS_12JSParserModeEPKNS_10SourceCodeE
+__ZN3JSC8JSParserC2EPNS_5LexerEPNS_12JSGlobalDataEPNS_18FunctionParametersEbbPNS_14SourceProviderE
+__ZN3JSC8JSParser9pushScopeEv
+__ZN3JSC8JSParser4nextENS_5Lexer7LexTypeE
+__ZN3JSC5Lexer3lexEPNS_11JSTokenDataEPNS_11JSTokenInfoENS0_7LexTypeEb
+__ZN3WTF15SegmentedVectorIN3JSC10IdentifierELm64EE6appendIS2_EEvRKT_
+__ZN3JSC8JSParser12parseProgramEv
+__ZNK3JSC19SourceProviderCache8byteSizeEv
+__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE15reserveCapacityEm
+__ZN3JSC8JSParser19parseSourceElementsILNS0_18SourceElementsModeE0ENS_10ASTBuilderEEENT0_14SourceElementsERS4_
+__ZN3JSC8JSParser14parseStatementINS_10ASTBuilderEEENT_9StatementERS3_RPKNS_10IdentifierE
+__ZN3JSC8JSParser24parseFunctionDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE1ELb1ENS_10ASTBuilderEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC8JSParser16declareParameterEPKNS_10IdentifierE
+__ZN3JSC11ParserArena16allocateFreeableEm
 __ZN3JSC11ParserArena20allocateFreeablePoolEv
-__ZL20makeFunctionCallNodePN3JSC12JSGlobalDataENS_8NodeInfoIPNS_14ExpressionNodeEEENS2_IPNS_13ArgumentsNodeEEEiii
-__ZNK3JSC15DotAccessorNode10isLocationEv
-__ZNK3JSC14ExpressionNode13isResolveNodeEv
-__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
-__ZL14makeAssignNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeENS_8OperatorES3_bbiii
-__ZNK3JSC11ResolveNode10isLocationEv
-__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZN3JSC8JSParser19parseSourceElementsILNS0_18SourceElementsModeE0ENS_13SyntaxCheckerEEENT0_14SourceElementsERS4_
+__ZN3JSC8JSParser14parseStatementINS_13SyntaxCheckerEEENT_9StatementERS3_RPKNS_10IdentifierE
+__ZN3JSC8JSParser17parseForStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser5Scope15declareVariableEPKNS_10IdentifierE
+__ZN3JSC5Lexer7record8Ei
+__ZN3JSC8JSParser25parseAssignmentExpressionINS_13SyntaxCheckerEEENT_10ExpressionERS3_
+__ZN3JSC8JSParser21parseMemberExpressionINS_13SyntaxCheckerEEENT_10ExpressionERS3_
+__ZN3JSC8JSParser15parseExpressionINS_13SyntaxCheckerEEENT_10ExpressionERS3_
+__ZN3WTF7HashSetINS_6RefPtrINS_10StringImplEEEN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3JSC8JSParser16parseIfStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser31parseExpressionOrLabelStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC5Lexer16nextTokenIsColonEv
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEb
+__ZN3JSC11ParserArena14derefWithArenaEN3WTF10PassRefPtrINS_21ParserArenaRefCountedEEE
+__ZN3WTF14deleteOwnedPtrIN3JSC23SourceProviderCacheItemEEEvPT_
+__ZN3JSC8JSParser5Scope29copyCapturedVariablesToVectorERKN3WTF7HashSetINS2_6RefPtrINS2_10StringImplEEENS_17IdentifierRepHashENS2_10HashTraitsIS6_EEEERNS2_6VectorIS6_Lm0EEE
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEES3_NS_17IdentityExtractorIS3_EEN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EES9_E13isEmptyBucketERKS3_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEES3_NS_17IdentityExtractorIS3_EEN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EES9_E15deallocateTableEPS3_i
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEES3_NS_17IdentityExtractorIS3_EEN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EES9_E6expandEv
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEES3_NS_17IdentityExtractorIS3_EEN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EES9_E6rehashEi
+__ZN3WTF6VectorINS_6RefPtrINS_10StringImplEEELm0EE14expandCapacityEm
+__ZN3JSC8JSParser5ScopeD1Ev
+__ZN3JSC19SourceProviderCache3addEiN3WTF10PassOwnPtrINS_23SourceProviderCacheItemEEEj
+__ZN3WTF9HashTableIiSt4pairIiPN3JSC23SourceProviderCacheItemEENS_18PairFirstExtractorIS5_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIiEENSB_IS4_EEEESC_E6expandEv
+__ZN3JSC5Lexer10sourceCodeEiii
+__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeERKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
+__ZN3JSC16FunctionBodyNode13finishParsingEN3WTF10PassRefPtrINS_18FunctionParametersEEERKNS_10IdentifierE
+__ZN3WTF6VectorIPN3JSC16FunctionBodyNodeELm0EE15reserveCapacityEm
 __ZN3JSC13StatementNode6setLocEii
-__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE14expandCapacityEm
 __ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
 __ZNK3JSC13StatementNode16isEmptyStatementEv
 __ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
-__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEEEP
+__ZN3JSC8JSParser21parseConstDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3WTF6VectorISt4pairIPKN3JSC10IdentifierEjELm0EE15reserveCapacityEm
+__ZN3JSC8JSParser25parseAssignmentExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
+__ZN3JSC8JSParser21parseMemberExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
+__ZN3JSC5Lexer10scanRegExpERPKNS_10IdentifierES4_t
+__ZN3JSC4Yarr11checkSyntaxERKNS_7UStringE
+__ZN3JSC4Yarr6ParserINS0_13SyntaxCheckerEE5parseEv
+__ZN3JSC4Yarr6ParserINS0_13SyntaxCheckerEE11parseEscapeILb1ENS3_28CharacterClassParserDelegateEEEbRT0_
+__ZN3JSC8JSParser20parseReturnStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3WTF6VectorIiLm0EE14expandCapacityEm
+__ZN3JSC8JSParser19parseVarDeclarationINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE0ELb0ENS_13SyntaxCheckerEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC8JSParser19parseWhileStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC10ASTBuilder20makeFunctionCallNodeEPNS_14ExpressionNodeEPNS_13ArgumentsNodeEiii
+__ZNK3JSC11ResolveNode10isLocationEv
+__ZNK3JSC11ResolveNode13isResolveNodeEv
+__ZN3WTF6VectorISt4pairIiiELm0EE14expandCapacityEm
+__ZN3JSC8JSParser22parseContinueStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseTryStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC6Parser16didFinishParsingEPNS_14SourceElementsEPNS_15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEEEPNS3_INS5_IPNS_16FunctionBodyNodeELm0EEEEEjiiRNS4_7HashSetINS4_6RefPtrINS4_10StringImplEEENS_17IdentifierRepHashENS4_10HashTraitsISM_EEEE
+__ZN3JSC11ParserArenaD1Ev
 __ZN3JSC5Lexer5clearEv
-__ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_
-__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEE
-__ZN3JSC11ParserArena14derefWithArenaEN3WTF10PassRefPtrINS_21ParserArenaRefCountedEEE
+__ZN3JSC11ProgramNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16FunctionBodyNodeELm0EEERNS5_7HashSetINS5_6RefPtrINS5_10StringImplEEENS_17IdentifierRepHashENS5_10HashTraitsISL_EEEERKNS_10SourceCodeEji
+__ZN3JSC9ScopeNodeC2EPNS_12JSGlobalDataERKNS_10SourceCodeEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS9_IPNS_16FunctionBodyNodeELm0EEERNS8_7HashSetINS8_6RefPtrINS8_10StringImplEEENS_17IdentifierRepHashENS8_10HashTraitsISO_EEEEji
 __ZN3JSC11ParserArena10removeLastEv
 __ZN3JSC11ParserArena5resetEv
 __ZN3WTF6VectorIN3JSC10IdentifierELm64EE14shrinkCapacityEm
-__ZN3JSC9CodeBlockC2EPNS_16ScriptExecutableENS_8CodeTypeEN3WTF10PassRefPtrINS_14SourceProviderEEEjPNS4_7HashMapINS4_6RefPtrIN7W
-__ZN3WTF7HashSetIPN3JSC15GlobalCodeBlockENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
-__ZN3WTF9HashTableIPN3JSC15GlobalCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZN3JSC17BytecodeGeneratorC1EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrIN7WebCore10StringIm
-__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrIN7WebCore10StringIm
+__ZN3JSC9CodeBlockC2EPNS_16ScriptExecutableENS_8CodeTypeEPNS_14JSGlobalObjectEN3WTF10PassRefPtrINS_14SourceProviderEEEjPNS6_7HashMapINS6_6RefPtrINS6_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS6_10HashTraitsISD_EENS_26SymbolTableIndexHashTraitsEEEb
+__ZN3JSC17BytecodeGeneratorC1EPNS_11ProgramNodeEPNS_14ScopeChainNodeEPN3WTF7HashMapINS5_6RefPtrINS5_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS5_10HashTraitsIS9_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
+__ZN3JSC17BytecodeGeneratorC2EPNS_11ProgramNodeEPNS_14ScopeChainNodeEPN3WTF7HashMapINS5_6RefPtrINS5_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS5_10HashTraitsIS9_EENS_26SymbolTableIndexHashTraitsEEEPNS_16ProgramCodeBlockE
+__ZN3JSC17BytecodeGenerator10emitOpcodeENS_8OpcodeIDE
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE15reserveCapacityEm
-__ZN3JSC9Structure31toCacheableDictionaryTransitionEPS0_
-__ZN3JSC9Structure22toDictionaryTransitionEPS0_NS0_14DictionaryKindE
-__ZN3JSC9Structure26flattenDictionaryStructureEPNS_8JSObjectE
+__ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EE13ensureSegmentEmm
+__ZN3JSC8JSObject12removeDirectERNS_12JSGlobalDataERKNS_10IdentifierE
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC16SymbolTableEntryEENS_18PairFirstExtractorIS7_EENS5_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENS5_26SymbolTableIndexHashTraitsEEESD_E13isEmptyBucketERKS7_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC16SymbolTableEntryEENS_18PairFirstExtractorIS7_EENS5_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENS5_26SymbolTableIndexHashTraitsEEESD_E6expandEv
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC16SymbolTableEntryEENS_18PairFirstExtractorIS7_EENS5_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENS5_26SymbolTableIndexHashTraitsEEESD_E6rehashEi
+__ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EEN3JSC17IdentifierRepHashENS_10HashTraitsIS2_EES8_E6rehashEi
+__ZN3JSC14JSGlobalObject15resizeRegistersEii
+__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZN3JSC18FunctionExecutableC1EPNS_9ExecStateERKNS_10IdentifierERKNS_10SourceCodeEbPNS_18FunctionParametersEbii
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_18FunctionExecutableEPNS_14ScopeChainNodeE
+__ZN3JSC10JSFunctionC2EPNS_9ExecStateEPNS_18FunctionExecutableEPNS_14ScopeChainNodeE
 __ZN3JSC17BytecodeGenerator8generateEv
 __ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
@@ -349,1787 +627,1589 @@ __ZN3JSC17BytecodeGenerator12newTemporaryEv
 __ZN3JSC17BytecodeGenerator11newRegisterEv
 __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDENS_7JSValueE
 __ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
-__ZN3WTF9HashTableIPvSt4pairIS1_jENS_18PairFirstExtractorIS3_EENS_7PtrHashIS1_EENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTr
-__ZN3WTF6VectorIN3JSC8RegisterELm0EE15reserveCapacityEm
-__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
-__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF9HashTableIPvSt4pairIS1_jENS_18PairFirstExtractorIS3_EENS_7PtrHashIS1_EENS_14PairHashTraitsIN3JSC24EncodedJSValueHashTraitsENS_10HashTraitsIjEEEESA_E6expandEv
+__ZN3WTF6VectorIN3JSC12WriteBarrierINS1_7UnknownEEELm0EE14expandCapacityEm
+__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18ConstStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitNodeEPNS_10RegisterIDEPNS_4NodeE
+__ZN3JSC13ConstDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13ConstDeclNode14emitCodeSingleERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator16constRegisterForERKNS_10IdentifierE
+__ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC11regExpFlagsERKNS_7UStringE
+__ZN3JSC11RegExpCache14lookupOrCreateERKNS_7UStringENS_11RegExpFlagsE
+__ZN3WTF9HashTableIN3JSC9RegExpKeyESt4pairIS2_NS_6RefPtrINS1_6RegExpEEEENS_18PairFirstExtractorIS7_EENS_10RegExpHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSD_IS6_EEEESE_E6rehashEi
+__ZN3JSC11RegExpCache6createERKNS_7UStringENS_11RegExpFlagsEN3WTF24HashTableIteratorAdapterINS5_9HashTableINS_9RegExpKeyESt4pairIS8_NS5_6RefPtrINS_6RegExpEEEENS5_18PairFirstExtractorISD_EENS5_10RegExpHashIS8_EENS5_14PairHashTraitsINS5_10HashTraitsIS8_EENSJ_ISC_EEEESK_EESD_EE
+__ZN3JSC4Yarr13YarrGenerator12generateTermEm
+__ZN3JSC4Yarr13YarrGenerator13readCharacterEiNS_12X86Registers10RegisterIDE
+__ZN3JSC4Yarr13YarrGenerator19matchCharacterClassENS_12X86Registers10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEPKNS0_14CharacterClassE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32ENS_12X86Registers10RegisterIDE
+__ZN3JSC4Yarr13YarrGenerator12atEndOfInputEv
+__ZN3JSC14MacroAssembler4pokeENS_12X86Registers10RegisterIDEi
+__ZN3JSC4Yarr13YarrGenerator19jumpIfCharNotEqualsEti
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
+__ZN3JSC12X86Assembler7subl_irEiNS_12X86Registers10RegisterIDE
+__ZN3JSC4Yarr13YarrGenerator13backtrackTermEm
+__ZN3JSC4Yarr13YarrGenerator20backtrackTermDefaultEm
+__ZN3JSC4Yarr13YarrGenerator17BacktrackingState6linkToENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelEPNS_14MacroAssemblerE
+__ZN3JSC17BytecodeGenerator13emitNewRegExpEPNS_10RegisterIDEN3WTF10PassRefPtrINS_6RegExpEEE
+__ZN3JSC17BytecodeGenerator9addRegExpEN3WTF10PassRefPtrINS_6RegExpEEE
+__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
+__ZN3WTF16VectorBufferBaseIcE14allocateBufferEm
+__ZN3WTF6VectorIcLm128EE15reserveCapacityEm
+__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator11registerForERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRbRPNS_8JSObjectE
-__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
-__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEESt4pairIS4_iENS_18PairFirstExtractorIS6_EEN3JSC17IdentifierRepHashENS_14P
-__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC10IdentifierELm0EE15reserveCapacityEm
-__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_PNS_13ArgumentsNodeEjjj
-__ZN3WTF6VectorIN3JSC20GetByIdExceptionInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC12CallLinkInfoELm0EE15reserveCapacityEm
-__ZN3JSC17BytecodeGenerator15emitMethodCheckEv
-__ZN3JSC17BytecodeGenerator8emitCallEPNS_10RegisterIDES2_S2_PNS_13ArgumentsNodeEjjj
-__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_S3_PNS_13ArgumentsNodeEjjj
-__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC13CallArgumentsC2ERNS_17BytecodeGeneratorEPNS_13ArgumentsNodeE
+__ZN3JSC17BytecodeGenerator8emitCallEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
+__ZN3JSC17BytecodeGenerator8emitCallENS_8OpcodeIDEPNS_10RegisterIDES3_RNS_13CallArgumentsEjjj
+__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3WTF9HashTableIPNS_10StringImplESt4pairIS2_PN3JSC8JSStringEENS_18PairFirstExtractorIS7_EENS4_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS2_EENSC_IS6_EEEESD_E6rehashEi
+__ZN3WTF6VectorIN3JSC12CallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC11ResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
+__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
 __ZN3JSC17BytecodeGenerator16emitUnaryNoDstOpENS_8OpcodeIDEPNS_10RegisterIDE
-__ZN3JSC12JSGlobalData22numericCompareFunctionEPNS_9ExecStateE
-__ZNK3JSC21UStringSourceProvider6lengthEv
-__ZN3JSC18FunctionExecutable14fromGlobalCodeERKNS_10IdentifierEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPiPNS_7UStringE
-__ZNK3JSC21UStringSourceProvider4dataEv
-__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataE
-__ZN3JSC5Lexer10sourceCodeEiii
-__ZN3JSC16FunctionBodyNode13finishParsingERKNS_10SourceCodeEPNS_13ParameterNodeERKNS_10IdentifierE
-__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEm
-__ZN3JSC16FunctionBodyNode13finishParsingEN3WTF10PassRefPtrINS_18FunctionParametersEEERKNS_10IdentifierE
-__ZNK3JSC9ScopeNode15singleStatementEv
-__ZNK3JSC17ExprStatementNode15isExprStatementEv
-__ZNK3JSC12FuncExprNode14isFuncExprNodeEv
-__ZThn16_N3JSC11ProgramNodeD0Ev
-__ZN3JSC11ProgramNodeD0Ev
-__ZN3JSC11ParserArenaD1Ev
-__ZN3JSC14SourceElementsD1Ev
-__ZThn16_N3JSC16FunctionBodyNodeD0Ev
-__ZN3JSC16FunctionBodyNodeD0Ev
-__ZN3JSC18FunctionExecutable7compileEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3JSC6Parser5parseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPNS_8DebuggerEPNS_9ExecStateERKNS_10Sour
-__ZL11makeSubNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
-__ZN3JSC14ExpressionNode14stripUnaryPlusEv
-__ZNK3JSC14ExpressionNode8isNumberEv
-__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_
-__ZN3JSC17BytecodeGeneratorC1EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrIN7WebCore10Str
-__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrIN7WebCore10Str
-__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierE
-__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC17BytecodeGenerator7isLocalERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
-__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
-__ZNK3JSC9BlockNode7isBlockEv
-__ZNK3JSC10ReturnNode12isReturnNodeEv
 __ZN3JSC9CodeBlock11shrinkToFitEv
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
-__ZN3JSC17BytecodeGeneratorD2Ev
-__ZN3WTF6VectorIN3JSC11InstructionELm0EEaSERKS3_
-__ZN3JSC18FunctionExecutableD0Ev
-__ZN3JSC17FunctionCodeBlockD0Ev
-__ZN3JSC9CodeBlockD2Ev
-__ZN3JSC21UStringSourceProviderD0Ev
-__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
-__ZN3JSC11Interpreter7executeEPNS_17ProgramExecutableEPNS_9ExecStateEPNS_14ScopeChainNodeEPNS_8JSObjectEPNS_7JSValueE
-__ZN3JSC12JSGlobalData14resetDateCacheEv
-__ZN3JSC12RegisterFile12globalObjectEv
-__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
-__ZN3JSC12RegisterFile15setGlobalObjectEPNS_14JSGlobalObjectE
-__ZN3JSC17ProgramExecutable15generateJITCodeEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3JSC3JIT14privateCompileEv
+__ZN3WTF6VectorIN3JSC12WriteBarrierINS1_18FunctionExecutableEEELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC12WriteBarrierINS1_7UnknownEEELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14shrinkCapacityEm
+__ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEED1Ev
+__ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_16FunctionBodyNodeELm0EEEED1Ev
+__ZN3JSC14SourceElementsD1Ev
+__ZThn16_N3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC16FunctionBodyNodeD0Ev
+__ZN3JSC3JIT14privateCompileEPNS_21MacroAssemblerCodePtrE
 __ZN3JSC3JIT22privateCompileMainPassEv
 __ZN3JSC3JIT13emit_op_enterEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_movEPNS_11InstructionE
-__ZN3JSC3JIT22emit_op_resolve_globalEPNS_11InstructionEb
-__ZN3JSC23MacroAssemblerX86Common4moveENS_12X86Registers10RegisterIDES2_
-__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
-__ZN3JSC3JIT17emit_op_get_by_idEPNS_11InstructionE
-__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj
-__ZN3JSC3JIT17emit_op_constructEPNS_11InstructionE
-__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
-__ZN3JSC11JITStubCall4callEv
-__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEm
-__ZN3JSC3JIT24emit_op_construct_verifyEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_method_checkEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC25MethodCallCompilationInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT18emit_op_new_regexpEPNS_11InstructionE
+__ZN3JSC11JITStubCall4callEj
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE15reserveCapacityEm
 __ZN3JSC3JIT12emit_op_callEPNS_11InstructionE
-__ZN3JSC3JIT17emit_op_put_by_idEPNS_11InstructionE
+__ZN3JSC3JIT13compileOpCallENS_8OpcodeIDEPNS_11InstructionEj
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEm
+__ZN3JSC3JIT23emit_op_call_put_resultEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_new_arrayEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_endEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14shrinkCapacityEm
+__ZN3JSC3JIT22privateCompileLinkPassEv
 __ZN3JSC3JIT23privateCompileSlowCasesEv
-__ZN3JSC3JIT26emitSlow_op_resolve_globalEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC20MacroAssemblerX86_648storePtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE6ImmPtrENS3_15ImplicitAddressE
-__ZN3JSC11JITStubCall4callEj
-__ZN3JSC3JIT21emitSlow_op_get_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEb
-__ZN3JSC3JIT21emitSlow_op_constructEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE
-__ZN3JSC3JIT27compileOpConstructSetupArgsEPNS_11InstructionE
-__ZN3JSC3JIT28emitSlow_op_construct_verifyEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT24emitSlow_op_method_checkEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT16emitSlow_op_callEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT22compileOpCallSetupArgsEPNS_11InstructionE
-__ZN3JSC3JIT21emitSlow_op_put_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3WTF6VectorIN3JSC18MethodCallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE
+__ZN3WTF6VectorIN3JSC18MethodCallLinkInfoELm0EE4growEm
 __ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv
+__ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
+__ZN3JSC17BytecodeGeneratorD2Ev
+__ZThn16_N3JSC11ProgramNodeD0Ev
+__ZN3JSC11ProgramNodeD0Ev
+__ZN3JSC12RegisterFile12globalObjectEv
+__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
+__ZN3JSC12RegisterFile15setGlobalObjectEPNS_14JSGlobalObjectE
 _ctiTrampoline
-_cti_op_resolve_global
-_cti_op_get_by_id
-__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-_cti_op_construct_NotJSConstruct
-__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC13constructDateEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd
-__ZN3JSC12DateInstanceC2EPNS_9ExecStateEd
-__ZN3WTF8timeClipEd
+_cti_op_new_regexp
+__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEPNS_9StructureEN3WTF17NonNullPassRefPtrINS_6RegExpEEE
+_cti_vm_lazyLinkCall
+__ZN3JSC18FunctionExecutable22compileForCallInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_16FunctionBodyNodeEEEN3WTF10PassRefPtrIT_EEPNS_14JSGlobalObjectEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPNS_18FunctionParametersENS_18JSParserStrictnessEPPNS_8JSObjectE
+__ZN3JSC8JSParser19parseSourceElementsILNS0_18SourceElementsModeE1ENS_10ASTBuilderEEENT0_14SourceElementsERS4_
+__ZN3JSC8JSParser20parseReturnStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser15parseExpressionINS_10ASTBuilderEEENT_10ExpressionERS3_
+__ZNK3JSC15DotAccessorNode10isLocationEv
+__ZNK3JSC14ExpressionNode13isResolveNodeEv
+__ZNK3JSC14ExpressionNode21isBracketAccessorNodeEv
+__ZN3JSC16FunctionBodyNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPS0_Lm0EEERNS5_7HashSetINS5_6RefPtrINS5_10StringImplEEENS_17IdentifierRepHashENS5_10HashTraitsISK_EEEERKNS_10SourceCodeEji
+__ZN3JSC17BytecodeGeneratorC1EPNS_16FunctionBodyNodeEPNS_14ScopeChainNodeEPN3WTF7HashMapINS5_6RefPtrINS5_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS5_10HashTraitsIS9_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
+__ZN3JSC17BytecodeGeneratorC2EPNS_16FunctionBodyNodeEPNS_14ScopeChainNodeEPN3WTF7HashMapINS5_6RefPtrINS5_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS5_10HashTraitsIS9_EENS_26SymbolTableIndexHashTraitsEEEPNS_9CodeBlockE
+__ZN3WTF15SegmentedVectorIN3JSC10RegisterIDELm32EEC1Ev
+__ZN3WTF6VectorIN3JSC11InstructionELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator12addParameterERKNS_10IdentifierEi
+__ZN3JSC16FunctionBodyNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9BlockNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC10ReturnNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC19FunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitResolveEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator18findScopedPropertyERKNS_10IdentifierERiRmbRbRPNS_8JSObjectE
+__ZNK3JSC16JSVariableObject16isVariableObjectEv
+__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
+__ZN3JSC17BytecodeGenerator15emitMethodCheckEv
+__ZN3JSC17BytecodeGenerator11emitGetByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11addConstantERKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC10IdentifierELm0EE15reserveCapacityEm
+__ZN3JSC17BytecodeGenerator10emitReturnEPNS_10RegisterIDE
+__ZNK3JSC9ScopeNode15singleStatementEv
+__ZNK3JSC9BlockNode7isBlockEv
+__ZNK3JSC10ReturnNode12isReturnNodeEv
+__ZNK3JSC14SourceElements15singleStatementEv
+__ZNK3JSC14ExpressionNode10isSubtractEv
+__ZN3JSC3JIT22emit_op_get_global_varEPNS_11InstructionE
+__ZN3JSC3JIT20emit_op_method_checkEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC25MethodCallCompilationInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT21compileGetByIdHotPathEiiPNS_10IdentifierEj
+__ZN3WTF6VectorIN3JSC13SlowCaseEntryELm0EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC10CallRecordELm0EE14expandCapacityEmPKS2_
+__ZN3JSC3JIT11emit_op_retEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_method_checkEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT22compileGetByIdSlowCaseEiiPNS_10IdentifierERPNS_13SlowCaseEntryEb
+__ZN3JSC11JITStubCall4callEv
+_cti_register_file_check
 _cti_op_get_by_id_method_check
-__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC9Structure13hasTransitionEPN7WebCore10StringImplEj
-_cti_vm_lazyLinkCall
-__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12DateInstance9classInfoEv
-_cti_op_put_by_id
-__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC17ProgramExecutableD0Ev
-__ZN3JSC16ProgramCodeBlockD0Ev
-__ZN3WTF9HashTableIPN3JSC15GlobalCodeBlockES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS
+__ZNK3WTF12AtomicString5lowerEv
+__ZNK3JSC8JSObject24getPropertySpecificValueEPNS_9ExecStateERKNS_10IdentifierERPNS_6JSCellE
+__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_11FunctionPtrE
+__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockES4_NS_21MacroAssemblerCodePtrEPNS_12CallLinkInfoEiPNS_12JSGlobalDataE
+_cti_op_get_by_id
+_cti_op_new_array
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureERKNS_7ArgListE
+__ZN3JSC18FunctionExecutable11discardCodeEv
+__ZN3JSC17FunctionCodeBlockD0Ev
+__ZN3JSC9CodeBlockD2Ev
 __ZN3JSC17StructureStubInfo5derefEv
-__ZN7WebCore6String8truncateEj
-__ZN3JSC5Lexer10skipRegExpEv
-__ZNK3JSC14ExpressionNode10isLocationEv
-__ZN3WTF6VectorIPN3JSC16FunctionBodyNodeELm0EE14expandCapacityEm
-__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
-__ZN3WTF6VectorISt4pairIPKN3JSC10IdentifierEjELm0EE14expandCapacityEm
-__ZN3JSC8JSObject12removeDirectERKNS_10IdentifierE
-__ZN3JSC9Structure24removePropertyTransitionEPS0_RKNS_10IdentifierERm
-__ZN3JSC9Structure6removeERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator12addGlobalVarERKNS_10IdentifierEbRPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
-__ZN3WTF6VectorINS_6RefPtrIN3JSC18FunctionExecutableEEELm0EE14expandCapacityEm
-__ZN3JSC9Structure31removePropertyWithoutTransitionERKNS_10IdentifierE
-__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3JSC7UString14toStrictUInt32EPb
-__ZN7WebCore12AtomicString4findEPKtjj
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEESt4pairIS4_N3JSC16SymbolTableEntryEENS_18PairFirstExtractorIS8_EENS6_17Id
-__ZN3JSCL30comparePropertyMapEntryIndicesEPKvS1_
+__ZN3JSC8JSObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC9MarkStack14MarkStackArrayIPNS_6JSCellEE6appendERKS3_
+__ZN3JSC10JSFunction13visitChildrenERNS_9MarkStackE
+__ZN3JSC12RegExpObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC15JSWrapperObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC7JSArray13visitChildrenERNS_9MarkStackE
+__ZN3JSC22NativeErrorConstructor13visitChildrenERNS_9MarkStackE
+__ZN3JSC14ScopeChainNode13visitChildrenERNS_9MarkStackE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE13visitChildrenERNS_9MarkStackE
+__ZN3JSC18FunctionExecutable13visitChildrenERNS_9MarkStackE
+__ZN3JSC17ProgramExecutableD1Ev
+__ZN3JSC16ProgramCodeBlockD0Ev
+__ZN3JSC8JSParser31parseExpressionOrLabelStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE0ELb0ENS_10ASTBuilderEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC10ASTBuilder14makeAssignNodeEPNS_14ExpressionNodeENS_8OperatorES2_bbiii
+__ZN3JSC8JSParser19parseBreakStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC17ExprStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
-__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator13emitNewObjectEPNS_10RegisterIDE
-__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
-__ZN3JSC12FuncDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator15isLocalConstantERKNS_10IdentifierE
-__ZN3JSC16ArgumentListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEb
-__ZN3JSC9ArrayNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator12emitNewArrayEPNS_10RegisterIDEPNS_11ElementNodeE
-__ZN3JSC23FunctionCallResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
-__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsId
-__ZN3JSC10StringNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDERKNS_10IdentifierE
-__ZN3WTF9HashTableIPN7WebCore10StringImplESt4pairIS3_PN3JSC8JSStringEENS_18PairFirstExtractorIS8_EENS5_17IdentifierRepHashENS_1
-__ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
-__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC15ParserArenaDataIN3WTF6VectorIPNS_16FunctionBodyNodeELm0EEEED1Ev
-__ZN3JSC15ParserArenaDataIN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEED1Ev
-__ZN3JSC3JIT16emit_op_new_funcEPNS_11InstructionE
-__ZN3JSC3JIT18emit_op_new_objectEPNS_11InstructionE
+__ZN3JSC18FunctionExecutableC1EPNS_12JSGlobalDataERKNS_10IdentifierERKNS_10SourceCodeEbPNS_18FunctionParametersEbii
+__ZN3WTF6VectorIN3JSC12WriteBarrierINS1_18FunctionExecutableEEELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator11emitPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC3JIT17emit_op_get_by_idEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_new_func_expEPNS_11InstructionE
-__ZN3JSC3JIT17emit_op_new_arrayEPNS_11InstructionE
-__ZN3JSC3JIT25emit_op_resolve_with_baseEPNS_11InstructionE
-_cti_op_new_func
-__ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEEPNS_14ScopeChainNodeE
-_cti_op_new_object
-_cti_op_new_func_exp
-_cti_op_call_JSFunction
-__ZN3JSC18FunctionExecutable15generateJITCodeEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3WTF7HashSetINS_6RefPtrIN7WebCore10StringImplEEEN3JSC17IdentifierRepHashENS_10HashTraitsIS4_EEE3addERKS4_
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEES4_NS_17IdentityExtractorIS4_EEN3JSC17IdentifierRepHashENS_10HashTraitsIS
-__ZN3JSC17BytecodeGenerator6addVarERKNS_10IdentifierEbRPNS_10RegisterIDE
-__ZNK3JSC16JSVariableObject16isVariableObjectEv
-__ZN3JSC17BytecodeGenerator16emitGetScopedVarEPNS_10RegisterIDEmiNS_7JSValueE
-__ZNK3JSC13StatementNode12isReturnNodeEv
-__ZN3JSC3JIT29emit_op_enter_with_activationEPNS_11InstructionE
-__ZN3JSC3JIT22emit_op_get_global_varEPNS_11InstructionE
-__ZN3JSC3JIT29emitGetVariableObjectRegisterENS_12X86Registers10RegisterIDEiS2_
-__ZN3JSC3JIT27emit_op_tear_off_activationEPNS_11InstructionE
-__ZN3JSC11JITStubCall11addArgumentEjNS_12X86Registers10RegisterIDE
-__ZN3JSC3JIT11emit_op_retEPNS_11InstructionE
-_cti_register_file_check
-_cti_op_push_activation
-__ZN3JSC12JSActivationC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEE
-__ZN3JSC12JSActivationC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_18FunctionExecutableEEE
-_cti_op_tear_off_activation
-_cti_op_ret_scopeChain
+__ZN3JSC20MacroAssemblerX86_648storePtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE13TrustedImmPtrENS3_15ImplicitAddressE
+__ZN3JSC3JIT17emit_op_put_by_idEPNS_11InstructionE
+__ZN3JSC3JIT21emitSlow_op_get_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_put_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC10JSFunction18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC9Structure18transitionTableAddERKSt4pairIN3WTF6RefPtrIN7WebCore10StringImplEEEjEPS0_PNS_6JSCellE
-__ZN3WTF7HashMapISt4pairINS_6RefPtrIN7WebCore10StringImplEEEjES1_IPN3JSC9StructureES9_ENS7_28StructureTransitionTableHashENS7_3
-__ZN3WTF9HashTableISt4pairINS_6RefPtrIN7WebCore10StringImplEEEjES1_IS6_S1_IPN3JSC9StructureES9_EENS_18PairFirstExtractorISB_EEN
-_cti_op_new_array
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE
-_cti_op_construct_JSConstruct
-__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT20emit_op_convert_thisEPNS_11InstructionE
-__ZN3JSC3JIT24emitSlow_op_convert_thisEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_resolve_with_base
-__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
-__ZNK3JSC7ArgList8getSliceEiRS0_
-__ZN3JSC9Structure22materializePropertyMapEv
-_cti_op_end
-__ZNK7WebCore6String7toFloatEPb
-__ZN7WebCore10StringImpl7toFloatEPb
-__ZN7WebCore17charactersToFloatEPKtmPb
-__ZN7WebCoreeqERKNS_12AtomicStringEPKc
-__ZNK7WebCore6String5toIntEPb
-__ZN7WebCore10StringImpl5toIntEPb
-__ZN7WebCore15charactersToIntEPKtmPb
-__ZN7WebCore6String6numberEi
-__ZNK7WebCore6String11toIntStrictEPbi
-__ZN7WebCore10StringImpl11toIntStrictEPbi
-__ZN7WebCore21charactersToIntStrictEPKtmPbi
-__ZN7WebCore10StringImpl7replaceEPS0_S1_
-__ZN7WebCore6String6numberEt
-__ZL11makeDivNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
-__ZNK3JSC10NumberNode8isNumberEv
+__ZN3JSC9Structure22materializePropertyMapERNS_12JSGlobalDataE
+__ZN3WTF9HashTableISt4pairINS_6RefPtrINS_10StringImplEEEjES1_IS5_PN3JSC7JSValueEENS_18PairFirstExtractorIS9_EENS6_24StructureTransitionTable4HashENS_14PairHashTraitsINSC_10HashTraitsENS_10HashTraitsIS8_EEEESF_E6rehashEi
+_cti_op_new_func_exp
+_cti_op_put_by_id
+__ZN3JSC8JSParser20parseSwitchStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser18parseSwitchClausesINS_13SyntaxCheckerEEENT_10ClauseListERS3_
 __ZN3WTF6VectorIPvLm0EE14expandCapacityEm
-__ZN3WTF6VectorIjLm16EE6resizeEm
-__ZN3WTFL7multaddERNS_6BigIntEii
-__ZN3WTF6VectorIjLm16EEaSERKS1_
-__ZN3WTFL4multERNS_6BigIntERKS0_
-__ZL11makeAddNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
-__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE15reserveCapacityEm
-__ZL14makePrefixNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeENS_8OperatorEiii
-__ZN3WTF6VectorIPN3JSC10RegisterIDELm32EE15reserveCapacityEm
+__ZN3JSC8JSParser17parseForStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser19parseVarDeclarationINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser21parseDoWhileStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZNK3JSC19BracketAccessorNode10isLocationEv
+__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
+__ZN3JSC10ASTBuilder14makeBinaryNodeEiSt4pairIPNS_14ExpressionNodeENS0_12BinaryOpInfoEES5_
+__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC16PropertyListNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitNewObjectEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator17emitDirectPutByIdEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_iENS_18PairFirstExtractorIS5_EEN3JSC17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENS8_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESC_E4findIS3_NS_22IdentityHashTranslatorIS3_S5_S9_EEEENS_17HashTableIteratorIS3_S5_S7_S9_SF_SC_EERKT_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_iENS_18PairFirstExtractorIS5_EEN3JSC17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENS8_17BytecodeGenerator28IdentifierMapIndexHashTraitsEEESC_E6rehashEi
+__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator8newLabelEv
-__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
-__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator20emitGetPropertyNamesEPNS_10RegisterIDES2_S2_S2_PNS_5LabelE
 __ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
 __ZN3JSC17BytecodeGenerator9emitLabelEPNS_5LabelE
-__ZN3WTF6VectorIjLm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator14emitPutByIndexEPNS_10RegisterIDEjS2_
-__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC14LogicalNotNode26hasConditionContextCodegenEv
-__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator11emitUnaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_
-__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
-__ZNK3JSC14ExpressionNode5isAddEv
-__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator13newLabelScopeENS_10LabelScope4TypeEPKNS_10IdentifierE
+__ZN3WTF6VectorIjLm0EE15reserveCapacityEm
+__ZN3WTF6VectorIN3JSC12ForInContextELm0EE14expandCapacityEm
+__ZN3JSC16VarStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17AssignResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15isLocalConstantERKNS_10IdentifierE
+__ZN3WTF6VectorIN3JSC17GlobalResolveInfoELm0EE14expandCapacityEm
+__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC11ResolveNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator7isLocalERKNS_10IdentifierE
+__ZN3JSC8ThisNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator10emitPreIncEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
+__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
+__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
 __ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
-__ZN3JSC3JIT11emit_op_divEPNS_11InstructionE
-__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common9ConditionENS_12X86Registers10RegisterIDES4_
-__ZN3JSC12X86Assembler11cvtsi2sd_rrENS_12X86Registers10RegisterIDENS1_13XMMRegisterIDE
-__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDE
-__ZN3JSC12X86Assembler7movq_rrENS_12X86Registers10RegisterIDENS1_13XMMRegisterIDE
-__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5Imm32ENS_12X86Registers10RegisterIDE
-__ZN3JSC15AssemblerBuffer7putByteEi
-__ZN3JSC3JIT14emit_op_jfalseEPNS_11InstructionE
-__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common9ConditionENS_12X86Registers10RegisterIDENS_22AbstractMacr
+__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_S2_S2_S2_PNS_5LabelE
+__ZN3JSC3JIT18emit_op_new_objectEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_get_pnamesEPNS_11InstructionE
 __ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEmPKS2_
 __ZN3WTF6VectorIN3JSC9JumpTableELm0EE14expandCapacityEm
 __ZN3JSC3JIT11emit_op_jmpEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_put_by_indexEPNS_11InstructionE
-__ZN3JSC3JIT13emit_op_jtrueEPNS_11InstructionE
-__ZN3JSC3JIT11emit_op_addEPNS_11InstructionE
-__ZN3JSC3JIT18emit_op_get_by_valEPNS_11InstructionE
-__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE
-__ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
-__ZN3JSC3JIT15emit_op_pre_incEPNS_11InstructionE
+__ZN3JSC3JIT22emit_op_resolve_globalEPNS_11InstructionEb
+__ZN3JSC3JIT20emit_op_get_by_pnameEPNS_11InstructionE
+__ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
+__ZN3JSC3JIT18emit_op_get_by_valEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common19RelationalConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS5_13TrustedImmPtrE
+__ZN3JSC3JIT18emit_op_put_by_valEPNS_11InstructionE
+__ZN3JSC3JIT16emit_op_stricteqEPNS_11InstructionE
+__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
+__ZN3JSC12X86Assembler6orl_irEiNS_12X86Registers10RegisterIDE
 __ZN3JSC3JIT16emitTimeoutCheckEv
-__ZN3JSC3JIT13emit_op_jlessEPNS_11InstructionE
-__ZN3JSC3JIT15emitSlow_op_divEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT18emitSlow_op_jfalseEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_9ConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X
-__ZN3JSC3JIT17emitSlow_op_jtrueEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT13emit_op_jtrueEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_649branchPtrENS_23MacroAssemblerX86Common19RelationalConditionENS_12X86Registers10RegisterIDES4_
+__ZN3JSC3JIT18emit_op_next_pnameEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common15ResultConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS5_12TrustedImm32E
+__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_15ResultConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32E
+__ZN3JSC3JIT26emitSlow_op_resolve_globalEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT24emitSlow_op_get_by_pnameEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC11JITStubCall11addArgumentEjNS_12X86Registers10RegisterIDE
 __ZN3JSC3JIT22emitSlow_op_get_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC9JITThunks7ctiStubEPNS_12JSGlobalDataEPFNS_21MacroAssemblerCodePtrES2_PNS_14ExecutablePoolEE
+__ZN3WTF9HashTableIPFN3JSC21MacroAssemblerCodePtrEPNS1_12JSGlobalDataEPNS1_14ExecutablePoolEESt4pairIS8_S2_ENS_18PairFirstExtractorISA_EENS_7PtrHashIS8_EENS_14PairHashTraitsINS_10HashTraitsIS8_EENSG_IS2_EEEESH_E6expandEv
 __ZN3JSC3JIT27stringGetByValStubGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__ZN3JSC15AssemblerBuffer14executableCopyEPNS_14ExecutablePoolE
-__ZN3JSC3JIT19emitSlow_op_pre_incEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC11JITStubCall11addArgumentENS_12X86Registers10RegisterIDE
-__ZN3JSC3JIT17emitSlow_op_jlessEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC23MacroAssemblerX86Common12branchDoubleENS0_15DoubleConditionENS_12X86Registers13XMMRegisterIDES3_
-__ZNK3JSC13LogicalOpNode26hasConditionContextCodegenEv
-__ZN3JSC13LogicalOpNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
-__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT11emit_op_subEPNS_11InstructionE
-__ZN3JSC3JIT20compileBinaryArithOpENS_8OpcodeIDEjjjNS_12OperandTypesE
-__ZN3JSC3JIT15emitSlow_op_subEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT28compileBinaryArithOpSlowCaseENS_8OpcodeIDERPNS_13SlowCaseEntryEjjjNS_12OperandTypesEbb
-__ZN3JSC3JIT15emitSlow_op_addEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZNK3JSC14JSGlobalObject14isDynamicScopeERb
-_cti_op_jtrue
-__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
-__ZNK3JSC8JSObject24getPropertySpecificValueEPNS_9ExecStateERKNS_10IdentifierERPNS_6JSCellE
-__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_11FunctionPtrE
-__ZN3JSC3JIT8linkCallEPNS_10JSFunctionEPNS_9CodeBlockES4_RNS_7JITCodeEPNS_12CallLinkInfoEiPNS_12JSGlobalDataE
-_cti_op_add
-__ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
-__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZNK3JSC7JSValue8toStringEPNS_9ExecStateE
-__ZN3JSC7UString4fromEi
-__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
-__ZN3WTF13tryFastMallocEm
-__ZN7WebCore10StringImpl4findEPKcib
-__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZNK3JSC14ExpressionNode6isNullEv
-__ZN3JSC3JIT11emit_op_neqEPNS_11InstructionE
-__ZN3JSC12X86Assembler8shll_i8rEiNS_12X86Registers10RegisterIDE
-__ZN3JSC12X86Assembler6orl_irEiNS_12X86Registers10RegisterIDE
-__ZN3JSC3JIT15emitSlow_op_neqEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_call_arityCheck
-_cti_op_eq
-__ZN3JSC9JITThunks15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_10IdentifierERKNS_12Pr
-__ZN3JSC14StructureChainC1EPNS_9StructureE
-__ZN3JSC14StructureChainC2EPNS_9StructureE
-__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12
-__ZN3JSC3JIT22compileGetDirectOffsetEPNS_8JSObjectENS_12X86Registers10RegisterIDES4_m
+__ZN3JSC21roundUpAllocationSizeEmm
+__ZN3JSC3JIT22emitSlow_op_put_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT20emitSlow_op_stricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT17emitSlow_op_jtrueEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_new_object
+_cti_op_put_by_id_direct
+__ZN3JSC9Structure22toDictionaryTransitionERNS_12JSGlobalDataEPS0_NS0_14DictionaryKindE
+_cti_op_get_pnames
+__ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
+_cti_has_property
+_cti_op_resolve_global
+_cti_op_get_by_val
+_cti_op_put_by_val
+__ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSParser20parseSwitchStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser18parseSwitchClausesINS_10ASTBuilderEEENT_10ClauseListERS3_
+__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
+__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
+__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
+__ZNK3JSC14ExpressionNode8isNumberEv
+__ZNK3JSC10StringNode8isStringEv
+__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
+__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
+__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
+__ZNK3JSC13StatementNode12isReturnNodeEv
+__ZN3JSC15StringJumpTableC1ERKS0_
+__ZN3JSC3JIT21emit_op_switch_stringEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm
+_cti_op_switch_string
+__ZN3JSC9JITThunks15tryCacheGetByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_10IdentifierERKNS_12PropertySlotEPNS_17StructureStubInfoE
 _cti_op_get_by_id_self_fail
-__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureERKNS_1
+__ZN3JSC3JIT29privateCompileGetByIdSelfListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureERKNS_10IdentifierERKNS_12PropertySlotEm
 _cti_op_get_by_id_custom_stub
-__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZL17combineCommaNodesPN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_
-__ZNK3JSC14ExpressionNode11isCommaNodeEv
-__ZNK3JSC9CommaNode11isCommaNodeEv
-__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
-__ZN3JSC9CommaNodeD1Ev
+__ZN3JSC8JSParser16parseIfStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC5Lexer19getUnicodeCharacterEv
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm0EE14expandCapacityEm
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE15reserveCapacityEm
+__ZN3JSC9Structure26flattenDictionaryStructureERNS_12JSGlobalDataEPNS_8JSObjectE
+__ZN3JSC6IfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC11BooleanNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEb
+__ZN3JSC10NumberNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEd
+__ZN3WTF9HashTableIdSt4pairIdN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_9FloatHashIdEENS_14PairHashTraitsINS_10HashTraitsIdEENSA_IS3_EEEESB_E6expandEv
+__ZN3JSC11NewExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator13emitConstructEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
+__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12BinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC10NumberNode6isPureERNS_17BytecodeGeneratorE
+__ZN3JSC17BytecodeGenerator12emitBinaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_NS_12OperandTypesE
+__ZN3JSC3JIT14emit_op_jfalseEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_constructEPNS_11InstructionE
 __ZN3JSC3JIT14emit_op_jnlessEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_jfalseEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_constructEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT18emitSlow_op_jnlessEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12X86Assembler7movq_rrENS_12X86Registers10RegisterIDENS1_13XMMRegisterIDE
+__ZN3JSC12X86Assembler11cvtsi2sd_rrENS_12X86Registers10RegisterIDENS1_13XMMRegisterIDE
+__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDE
+__ZN3JSC23MacroAssemblerX86Common12branchDoubleENS0_15DoubleConditionENS_12X86Registers13XMMRegisterIDES3_
+__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC15RegExpPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateE
+__ZN3JSC12RegExpObject4testEPNS_9ExecStateE
+__ZN3JSC12RegExpObject5matchEPNS_9ExecStateE
+__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
+__ZN3JSC4Yarr7executeERNS0_13YarrCodeBlockEPKtjjPi
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE17staticValueGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+_JSValueIsObjectOfClass
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_P19StaticFunctionEntryENS_18PairFirstExtractorIS7_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSC_IS6_EEEESD_E6expandEv
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+_JSValueCreateJSONString
+__ZN3JSC13JSONStringifyEPNS_9ExecStateENS_7JSValueEj
+__ZN3JSC11StringifierC2EPNS_9ExecStateERKNS_5LocalINS_7UnknownEEES7_
+__ZN3JSC11Stringifier9stringifyENS_6HandleINS_7UnknownEEE
+__ZN3JSC11Stringifier22appendStringifiedValueERNS_14UStringBuilderENS_7JSValueEPNS_8JSObjectERKNS_27PropertyNameForFunctionCallE
+__ZN3WTF13StringBuilder6appendEPKcj
+__ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
+_cti_vm_lazyLinkConstruct
+__ZN3JSC18FunctionExecutable27compileForConstructInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC3JIT18emit_op_get_calleeEPNS_11InstructionE
+__ZN3JSC3JIT19emit_op_create_thisEPNS_11InstructionE
+_cti_op_create_this
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE20staticFunctionGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSC18JSCallbackFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPFPK13OpaqueJSValuePK15OpaqueJSContextPS5_SB_mPKS7_PS7_ERKNS_10IdentifierE
+_cti_op_call_NotJSFunction
+__ZN3JSC18JSCallbackFunction11getCallDataERNS_8CallDataE
+__ZN3JSC18JSCallbackFunction4callEPNS_9ExecStateE
+_JSValueToBoolean
+_JSValueProtect
+_JSValueMakeUndefined
 _cti_op_jless
-__ZN3JSC3JIT33privateCompilePatchGetArrayLengthENS_16ReturnAddressPtrE
-__ZN3JSC3JIT16patchGetByIdSelfEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrE
+__ZN3JSC7UString6numberEd
+__ZN3WTF14numberToStringEdPt
+__ZN3WTF4dtoaILb1ELb0ELb0ELb1EEEvPcdiRbRiRj
+__ZNK3WTF13DecimalNumber15toStringDecimalEPtj
+__ZN3WTF6String6appendEPKtj
+__ZN3WTF10StringImpl11reverseFindEPS0_j
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
+__ZN3WTF6String8truncateEj
+__ZN3JSC14JSGlobalObject15copyGlobalsFromERNS_12RegisterFileE
+__ZN3JSC8JSParser24parseFunctionDeclarationINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE1ELb1ENS_13SyntaxCheckerEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC17BytecodeGenerator21emitResolveBaseForPutEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator15emitResolveBaseEPNS_10RegisterIDERKNS_10IdentifierE
+__ZN3JSC17StringConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL27objectProtoFuncDefineGetterEPNS_9ExecStateE
+__ZN3JSC10JSFunction11getCallDataERNS_8CallDataE
+__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
+__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC8JSParser21parseConstDeclarationINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC8JSParser17parseFunctionInfoILNS0_20FunctionRequirementsE1ELb0ENS_10ASTBuilderEEEbRT1_RPKNS_10IdentifierERNS4_19FormalParameterListERNS4_12FunctionBodyERiSE_SE_
+__ZN3JSC8JSParser5Scope19restoreFunctionInfoEPKNS_23SourceProviderCacheItemE
+__ZN3WTF7HashMapINS_6RefPtrINS_10StringImplEEEjN3JSC17IdentifierRepHashENS_10HashTraitsIS3_EENS6_IjEEE3addEPS2_RKj
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_jENS_18PairFirstExtractorIS5_EEN3JSC17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSB_IjEEEESC_E6rehashEi
+__ZN3JSC17BytecodeGenerator13emitPutGetterEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC17BytecodeGenerator13emitPutSetterEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3JSC8NullNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT18emit_op_put_getterEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_put_setterEPNS_11InstructionE
+_cti_op_put_getter
+_cti_op_put_setter
+__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
+__ZNK3JSC12GetterSetter14isGetterSetterEv
+__ZNK3JSC18EmptyStatementNode16isEmptyStatementEv
+__ZN3JSC10ASTBuilder11makeAddNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC9ScopeNode8capturesERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator6addVarERKNS_10IdentifierEbRPNS_10RegisterIDE
+__ZNK3JSC13LogicalOpNode26hasConditionContextCodegenEv
+__ZN3JSC13LogicalOpNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
+__ZNK3JSC14LogicalNotNode26hasConditionContextCodegenEv
+__ZN3JSC11UnaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitUnaryOpENS_8OpcodeIDEPNS_10RegisterIDES3_
+__ZNK3JSC10StringNode6isPureERNS_17BytecodeGeneratorE
+__ZNK3JSC14ExpressionNode5isAddEv
+__ZNK3JSC14JSGlobalObject14isDynamicScopeERb
 __ZNK3JSC7AddNode5isAddEv
-__ZN3JSC9JITThunks15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_15PutPropertySlotEPNS_
-_cti_op_negate
-__ZN3JSC7UString4fromEj
-__ZL12makeMultNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
-__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
-__ZN3JSC3JIT11emit_op_notEPNS_11InstructionE
-__ZN3JSC3JIT11emit_op_mulEPNS_11InstructionE
-__ZN3JSC3JIT10emit_op_eqEPNS_11InstructionE
-__ZN3JSC3JIT15emitSlow_op_notEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT15emitSlow_op_mulEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT14emitSlow_op_eqEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_not
-__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator10emitPreDecEPNS_10RegisterIDE
-__ZN3JSC3JIT16emit_op_jnlesseqEPNS_11InstructionE
-__ZN3JSC3JIT15emit_op_jlesseqEPNS_11InstructionEb
-__ZN3JSC3JIT15emit_op_pre_decEPNS_11InstructionE
-__ZN3JSC3JIT22emit_op_loop_if_lesseqEPNS_11InstructionE
-__ZN3JSC3JIT20emitSlow_op_jnlesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT19emitSlow_op_jlesseqEPNS_11InstructionERPNS_13SlowCaseEntryEb
-__ZN3JSC3JIT19emitSlow_op_pre_decEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT26emitSlow_op_loop_if_lesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC17powThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__ZN3JSC19SpecializedThunkJIT12returnDoubleENS_12X86Registers13XMMRegisterIDE
-__ZN3JSC19SpecializedThunkJITD1Ev
-__ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC3JIT20patchMethodCallProtoEPNS_9CodeBlockERNS_18MethodCallLinkInfoEPNS_10JSFunctionEPNS_9StructureEPNS_8JSObjectENS_16R
-__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainENS_16ReturnAddres
-__ZN3JSC3JIT13testPrototypeEPNS_9StructureERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListE
-__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_jlesseq
-__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE15reserveCapacityEm
-__ZN3JSC10IfElseNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
-__ZN3JSC9CodeBlock25createRareDataIfNecessaryEv
-__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERKNS_10IdentifierES2_
-__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
-__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSCeqERKNS_7UStringEPKc
-__ZN3JSC17BytecodeGenerator12emitPopScopeEv
-__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14shrinkCapacityEm
-__ZN3JSC3JIT13emit_op_catchEPNS_11InstructionE
-__ZN3JSC3JIT22emit_op_push_new_scopeEPNS_11InstructionE
-__ZN3JSC3JIT15emit_op_resolveEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_resolve_baseEPNS_11InstructionE
-__ZN3JSC3JIT17emit_op_pop_scopeEPNS_11InstructionE
-__ZL15makePostfixNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeENS_8OperatorEiii
 __ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
-__ZNK3JSC10StringNode8isStringEv
 __ZNK3JSC14ExpressionNode8isStringEv
 __ZN3JSC17BytecodeGenerator15emitToPrimitiveEPNS_10RegisterIDES2_
 __ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
-__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT11emit_op_modEPNS_11InstructionE
-__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_9ConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86Ass
+__ZN3JSC3JIT11emit_op_addEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_to_primitiveEPNS_11InstructionE
-__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE6ImmPtrENS_12X86Registers10RegisterIDE
 __ZN3JSC3JIT14emit_op_strcatEPNS_11InstructionE
-__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT24emitSlow_op_to_primitiveEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+_JSValueMakeString
+_cti_op_jtrue
+__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
 _cti_op_strcat
-__ZNK3JSC19BracketAccessorNode10isLocationEv
-__ZNK3JSC19BracketAccessorNode21isBracketAccessorNodeEv
-__ZN3JSC17AssignBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC3JIT18emit_op_put_by_valEPNS_11InstructionE
-__ZN3JSC3JIT22emitSlow_op_put_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC14LogicalNotNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
+__ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
+__ZNK3JSC8JSString19resolveRopeSlowCaseEPNS_9ExecStateEPt
+__ZN3JSC8RopeImpl20destructNonRecursiveEv
+__ZN3JSC8RopeImpl23derefFibersNonRecursiveERN3WTF6VectorIPS0_Lm32EEE
+_cti_op_construct_NotJSConstruct
+__ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateE
+__ZN3WTF21charactersToIntStrictEPKtmPbi
+__ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZNK3JSC21UStringSourceProvider6lengthEv
+__ZN3JSC18FunctionExecutable14fromGlobalCodeERKNS_10IdentifierEPNS_9ExecStateEPNS_8DebuggerERKNS_10SourceCodeEPPNS_8JSObjectE
+__ZNK3JSC21UStringSourceProvider4dataEv
+__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
+__ZN3JSC11Interpreter11executeCallEPNS_9ExecStateEPNS_8JSObjectENS_8CallTypeERKNS_8CallDataENS_7JSValueERKNS_7ArgListE
+__ZN3JSC10ASTBuilder15makePostfixNodeEPNS_14ExpressionNodeENS_8OperatorEiii
+__ZN3JSC7ForNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18PostfixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator10emitPreIncEPNS_10RegisterIDE
+__ZN3JSC9EqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC14ExpressionNode6isNullEv
+__ZN3JSC3JIT15emit_op_pre_incEPNS_11InstructionE
+__ZN3JSC3JIT13emit_op_jlessEPNS_11InstructionE
+__ZN3JSC3JIT10emit_op_eqEPNS_11InstructionE
+__ZN3JSC3JIT19emitSlow_op_pre_incEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT17emitSlow_op_jlessEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT14emitSlow_op_eqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF11emptyStringEv
+__ZN3JSC13LogicalOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+_cti_op_stricteq
+_cti_op_eq
+__ZN3JSC10ASTBuilder14makePrefixNodeEPNS_14ExpressionNodeENS_8OperatorEiii
+__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
+_cti_op_in
+__ZN3JSC9JITThunks15tryCachePutByIDEPNS_9ExecStateEPNS_9CodeBlockENS_16ReturnAddressPtrENS_7JSValueERKNS_15PutPropertySlotEPNS_17StructureStubInfoEb
+_cti_op_get_by_id_generic
+_cti_op_put_by_id_generic
+__ZN3JSC3JIT16patchGetByIdSelfEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrE
+__ZNK3JSC6JSCell14isGetterSetterEv
+_JSObjectIsFunction
+_JSObjectCallAsFunction
+__ZN3JSC3JIT20emit_op_convert_thisEPNS_11InstructionE
+__ZN3JSC23MacroAssemblerX86Common11branchTest8ENS0_15ResultConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_12TrustedImm32E
+__ZN3JSC3JIT24emitSlow_op_convert_thisEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_16WriteBarrierBaseINS_7UnknownEEE
+__ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
+__ZN3JSC17ReadModifyDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15ConditionalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT20compileBinaryArithOpENS_8OpcodeIDEjjjNS_12OperandTypesE
+__ZN3JSC3JIT15emitSlow_op_addEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT28compileBinaryArithOpSlowCaseENS_8OpcodeIDERPNS_13SlowCaseEntryEjjjNS_12OperandTypesEbb
+__ZNK3JSC10NumberNode8isNumberEv
+__ZN3JSC3JIT17emit_op_nstricteqEPNS_11InstructionE
+__ZN3JSC3JIT21emitSlow_op_nstricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC15StringPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateE
+_cti_op_add
+__ZN3JSC10ASTBuilder12makeMultNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC14ExpressionNode14stripUnaryPlusEv
+__ZN3JSC17BytecodeGenerator20emitInitLazyRegisterEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator29uncheckedRegisterForArgumentsEv
+__ZN3JSC17BytecodeGenerator20emitGetArgumentByValEPNS_10RegisterIDES2_S2_
+__ZN3JSC17BytecodeGenerator22emitGetArgumentsLengthEPNS_10RegisterIDES2_
+__ZN3JSC3JIT21emit_op_init_lazy_regEPNS_11InstructionE
+__ZN3JSC3JIT11emit_op_mulEPNS_11InstructionE
+__ZN3JSC3JIT27emit_op_get_argument_by_valEPNS_11InstructionE
+__ZN3JSC3JIT28emit_op_get_arguments_lengthEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_mulEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT31emitSlow_op_get_argument_by_valEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT32emitSlow_op_get_arguments_lengthEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_call_arityCheck
+_cti_op_convert_this
+__ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
+__ZN3JSC12StringObjectC1ERNS_12JSGlobalDataEPNS_9StructureEPNS_8JSStringE
+__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
+__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC11jsSubstringEPNS_12JSGlobalDataERKNS_7UStringEjj
+__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSC14ArrayPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateE
+__ZNK3JSC8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
-__ZN7WebCore10StringImpl6createEN3WTF10PassRefPtrIS0_EEjj
-__ZN3WTF6RefPtrIN7WebCore10StringImplEED1Ev
-__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
-__ZN3WTF7HashSetIPN3JSC8JSObjectENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
+__ZN3JSC7JSArray9setLengthEj
+__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
+__ZN3JSCL18arrayProtoFuncJoinEPNS_9ExecStateE
 __ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZNK3JSC8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC15JSStringBuilder5buildEPNS_9ExecStateE
-__ZN3WTF6VectorItLm64EE17tryExpandCapacityEm
-__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7JSArray4pushEPNS_9ExecStateENS_7JSValueE
-__ZN3WTF14tryFastReallocEPvm
-__ZN3JSC4Heap15recordExtraCostEm
-__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
-__ZN3JSC3JIT22emit_op_put_scoped_varEPNS_11InstructionE
-__ZN3JSC3JIT29emitPutVariableObjectRegisterENS_12X86Registers10RegisterIDES2_i
-__ZN3JSC3JIT22emit_op_put_global_varEPNS_11InstructionE
-_cti_op_put_by_index
-__ZN3JSC7JSArray3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC7JSArray11putSlowCaseEPNS_9ExecStateEjNS_7JSValueE
-__ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC10JSFunction3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZNK7WebCore12AtomicString5lowerEv
+__ZN3JSC3JIT20patchMethodCallProtoERNS_12JSGlobalDataEPNS_9CodeBlockERNS_18MethodCallLinkInfoEPNS_10JSFunctionEPNS_9StructureEPNS_8JSObjectENS_16ReturnAddressPtrE
+__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_21MacroAssemblerCodePtrE
+__ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC3JIT16emit_op_jneq_ptrEPNS_11InstructionE
+__ZN3JSC3JIT24emit_op_create_argumentsEPNS_11InstructionE
+__ZN3JSC3JIT25emit_op_create_activationEPNS_11InstructionE
+__ZN3JSC3JIT27emit_op_tear_off_activationEPNS_11InstructionE
+_cti_op_create_arguments
+__ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateE
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+_cti_op_push_activation
+__ZN3JSC12JSActivationC1EPNS_9ExecStateEPNS_18FunctionExecutableE
+_cti_op_tear_off_activation
+__ZN3JSCL18arrayProtoFuncPushEPNS_9ExecStateE
+__ZN3JSC5Lexer9setOffsetEi
+__ZN3WTF7HashMapIjPN3JSC16FunctionBodyNodeENS_7IntHashIjEENS_29UnsignedWithZeroKeyHashTraitsIjEENS_10HashTraitsIS3_EEE3setERKjRKS3_
+__ZN3WTF9HashTableIjSt4pairIjPN3JSC16FunctionBodyNodeEENS_18PairFirstExtractorIS5_EENS_7IntHashIjEENS_14PairHashTraitsINS_29UnsignedWithZeroKeyHashTraitsIjEENS_10HashTraitsIS4_EEEESC_E6rehashEi
+__ZN3JSC17BytecodeGenerator19emitLazyNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
+__ZN3JSC17BytecodeGenerator23emitNewFunctionInternalEPNS_10RegisterIDEjb
+__ZN3JSC3JIT16emit_op_new_funcEPNS_11InstructionE
+__ZN3JSC8JSParser19parseWhileStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+_JSValueMakeNumber
+_JSObjectMakeArray
+_JSValueMakeBoolean
+__ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
+_JSValueUnprotect
+__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6expandEv
+_cti_op_new_func
+__ZN3JSC3JIT26privateCompileGetByIdProtoEPNS_17StructureStubInfoEPNS_9StructureES4_RKNS_10IdentifierERKNS_12PropertySlotEmNS_16ReturnAddressPtrEPNS_9ExecStateE
+__ZN3JSC3JIT22compileGetDirectOffsetEPNS_8JSObjectENS_12X86Registers10RegisterIDEm
+__ZN3JSC10ASTBuilder11makeSubNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC8JSParser22parseContinueStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC8JSParser19parseBreakStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC17BytecodeGenerator15emitNewFunctionEPNS_10RegisterIDEPNS_16FunctionBodyNodeE
+__ZN3JSC15TypeOfValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCeqERKNS_7UStringEPKc
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
+__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE14expandCapacityEm
+__ZN3JSC19ReverseBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator14emitJumpScopesEPNS_5LabelEi
+__ZN3JSC9BreakNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11breakTargetERKNS_10IdentifierE
+__ZN3WTF6VectorISt4pairIiiELm8EE14expandCapacityEm
+__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator20emitCheckHasInstanceEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
+__ZN3JSC17BytecodeGenerator19emitResolveWithBaseEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT11emit_op_subEPNS_11InstructionE
+__ZN3JSC3JIT16emit_op_jnlesseqEPNS_11InstructionE
+__ZN3JSC3JIT15emit_op_jlesseqEPNS_11InstructionEb
+__ZN3JSC3JIT11emit_op_notEPNS_11InstructionE
+__ZN3JSC3JIT26emit_op_check_has_instanceEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_instanceofEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_subEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT20emitSlow_op_jnlesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT19emitSlow_op_jlesseqEPNS_11InstructionERPNS_13SlowCaseEntryEb
+__ZN3JSC3JIT15emitSlow_op_notEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT30emitSlow_op_check_has_instanceEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT22emitSlow_op_instanceofEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC7UString6numberEi
+_cti_op_is_function
+__ZN3JSC16jsIsFunctionTypeENS_7JSValueE
+__ZN3JSC3JIT33privateCompilePatchGetArrayLengthENS_16ReturnAddressPtrE
+__ZN3JSC14StructureChainC1ERNS_12JSGlobalDataEPNS_9StructureES4_
+__ZN3JSC14StructureChainC2ERNS_12JSGlobalDataEPNS_9StructureES4_
+__ZN3JSC3JIT31privateCompilePutByIdTransitionEPNS_17StructureStubInfoEPNS_9StructureES4_mPNS_14StructureChainENS_16ReturnAddressPtrEb
+__ZN3JSC3JIT13testPrototypeENS_7JSValueERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListE
+__ZN3JSC3JIT26privateCompileGetByIdChainEPNS_17StructureStubInfoEPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12PropertySlotEmNS_16ReturnAddressPtrEPNS_9ExecStateE
+__ZN3JSC17BytecodeGenerator10emitPreDecEPNS_10RegisterIDE
+__ZN3JSC3JIT15emit_op_pre_decEPNS_11InstructionE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_12X86Registers10RegisterIDES2_
+__ZN3JSC3JIT19emitSlow_op_pre_decEPNS_11InstructionERPNS_13SlowCaseEntryE
 _cti_op_get_by_id_proto_list
-__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_1
+__ZN3JSC3JIT30privateCompileGetByIdChainListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureEPNS_14StructureChainEmRKNS_10IdentifierERKNS_12PropertySlotEmPNS_9ExecStateE
+__ZN3WTF13StringBuilder15reserveCapacityEj
+__ZN3WTF4dtoaEPcdRbRiRj
+__ZNK3WTF13DecimalNumber28bufferLengthForStringDecimalEv
+__ZN3JSC18globalFuncParseIntEPNS_9ExecStateE
+__ZN3JSC7toInt32Ed
+__ZN3JSCL8parseIntERKNS_7UStringEi
+_cti_op_nstricteq
+__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC10ASTBuilder14makeDeleteNodeEPNS_14ExpressionNodeEiii
+__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
+__ZN3JSC3JIT17emit_op_del_by_idEPNS_11InstructionE
+_cti_op_del_by_id
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+_cti_op_not
+__ZN3WTF13tryFastCallocEmm
+__ZN3WTF9ByteArray6createEm
 __ZN3JSC3JIT22emit_op_get_scoped_varEPNS_11InstructionE
-_cti_op_put_by_val
-__ZNK3JSC12JSActivation14isDynamicScopeERb
+__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateE
+__ZNK3JSC7JSValue14toThisJSStringEPNS_9ExecStateE
+__ZN3JSC9ExecState8argumentEi
+__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
+__ZN3WTF6RefPtrINS_10StringImplEEaSERKS2_
+__ZNK3JSC7UString20substringSharingImplEjj
+__ZN3JSC4Heap8allocateEm
 __ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode13isSimpleArrayEv
 __ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
-__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_
+__ZNK3JSC12JSActivation14isDynamicScopeERb
+__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_S2_
 __ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
-__ZN3JSC3JIT16emit_op_jneq_ptrEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_load_varargsEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_call_varargsEPNS_11InstructionE
 __ZN3JSC3JIT20compileOpCallVarargsEPNS_11InstructionE
-__ZN3JSC3JIT29compileOpCallVarargsSetupArgsEPNS_11InstructionE
+__ZN3JSC3JIT24emitSlow_op_load_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT24emitSlow_op_call_varargsEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT28compileOpCallVarargsSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC14ExecutablePool13systemReleaseERKNS0_10AllocationE
-_JSStringCreateWithCFString
-_JSStringRetain
-_JSStringRelease
-_JSEvaluateScript
-__ZN3JSC4Heap14registerThreadEv
-__ZNK14OpaqueJSString7ustringEv
-__ZN3JSC7UStringC1EPKtj
-__ZN3JSC5Lexer10scanRegExpERPKNS_10IdentifierES4_t
-__ZN3JSC18ConstStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC13ConstDeclNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC13ConstDeclNode14emitCodeSingleERNS_17BytecodeGeneratorE
-__ZN3JSC17BytecodeGenerator16constRegisterForERKNS_10IdentifierE
-__ZN3JSC10RegExpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringES5_
-__ZNK3JSC7UString4findEtj
-__ZN3JSC4Yarr15jitCompileRegexEPNS_12JSGlobalDataERNS0_14RegexCodeBlockERKNS_7UStringERjRPKcbb
-__ZN3JSC4Yarr12compileRegexERKNS_7UStringERNS0_12RegexPatternE
-__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE5parseEv
-__ZN3JSC4Yarr18PatternDisjunction17addNewAlternativeEv
-__ZN3WTF6VectorIPN3JSC4Yarr18PatternAlternativeELm0EE15reserveCapacityEm
-__ZN3JSC4Yarr23RegexPatternConstructor20atomPatternCharacterEt
+_cti_op_create_arguments_no_params
+__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateE
+_cti_op_load_varargs
+__ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
+_cti_op_call_jitCompile
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE14callbackGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
+__ZN3JSC11Stringifier6Holder18appendNextPropertyERS0_RNS_14UStringBuilderE
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC11Stringifier18appendQuotedStringERNS_14UStringBuilderERKNS_7UStringE
+__ZN3WTF10StringImpl4costEv
+__ZN3JSC7UStringC1EPKcj
+_JSObjectGetPrivateProperty
+_JSObjectSetPrivateProperty
+__ZN3JSC20JSCallbackObjectData18setPrivatePropertyERNS_12JSGlobalDataEPNS_6JSCellERKNS_10IdentifierENS_7JSValueE
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC12WriteBarrierINS5_7UnknownEEEENS_18PairFirstExtractorIS9_EENS5_17IdentifierRepHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSE_IS8_EEEESF_E6rehashEi
+__ZN3JSC17BytecodeGenerator16emitPutScopedVarEmiPNS_10RegisterIDENS_7JSValueE
+__ZN3JSC3JIT22emit_op_put_global_varEPNS_11InstructionE
+__ZN3JSC13LiteralParser5Lexer9lexNumberERNS1_18LiteralParserTokenE
+__ZN3JSC8JSParser17parseTryStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC7TryNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator9emitCatchEPNS_10RegisterIDEPNS_5LabelES4_
+__ZN3WTF6VectorIN3JSC11HandlerInfoELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator16emitPushNewScopeEPNS_10RegisterIDERKNS_10IdentifierES2_
+__ZN3WTF6VectorIN3JSC18ControlFlowContextELm0EE14expandCapacityEm
+__ZN3JSC17BytecodeGenerator12emitPopScopeEv
+__ZN3JSC3JIT13emit_op_catchEPNS_11InstructionE
+__ZN3JSC20MacroAssemblerX86_647loadPtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE15ImplicitAddressENS_12X86Registers10RegisterIDE
+__ZN3JSC3JIT22emit_op_push_new_scopeEPNS_11InstructionE
+__ZN3JSC3JIT18emit_op_jmp_scopesEPNS_11InstructionE
+__ZN3JSC3JIT17emit_op_pop_scopeEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC32CallReturnOffsetToBytecodeOffsetELm0EE15reserveCapacityEm
+_JSObjectDeletePrivateProperty
+__ZN3WTF6VectorIjLm16EE6resizeEm
+__ZN3WTFL7multaddERNS_6BigIntEii
+__ZN3WTFL4multERNS_6BigIntERKS0_
+__ZN3WTF6VectorIjLm16EEaSERKS1_
+__ZN3JSC4Yarr22YarrPatternConstructor23setupDisjunctionOffsetsEPNS0_18PatternDisjunctionEjj
+__ZN3JSC23MacroAssemblerX86Common4jumpEv
 __ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIN3JSC4Yarr11PatternTermELm0EE14expandCapacityEm
-__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE11parseEscapeILb0ES2_EEbRT0_
-__ZN3JSC4Yarr14RegexGenerator19generateDisjunctionEPNS0_18PatternDisjunctionE
-__ZN3JSC12X86Assembler7addl_irEiNS_12X86Registers10RegisterIDE
-__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_9ConditionENS_12X86Registers10RegisterIDES3_
-__ZN3JSC4Yarr14RegexGenerator12generateTermERNS1_19TermGenerationStateE
-__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDES4_ii
-__ZN3JSC4Yarr14RegexGenerator19TermGenerationState15jumpToBacktrackENS_22AbstractMacroAssemblerINS_12X86AssemblerEE4JumpEPNS_14
-__ZN3JSC4Yarr14RegexGenerator19jumpIfCharNotEqualsEti
-__ZN3JSC12X86Assembler7subl_irEiNS_12X86Registers10RegisterIDE
-__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList4linkEPS2_
-__ZN3WTF15deleteAllValuesIPN3JSC4Yarr18PatternDisjunctionELm4EEEvRKNS_6VectorIT_XT0_EEE
-__ZN3WTF15deleteAllValuesIPN3JSC4Yarr14CharacterClassELm0EEEvRKNS_6VectorIT_XT0_EEE
-__ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDEPNS_6RegExpE
-__ZN3JSC12RegExpObjectC1EN3WTF17NonNullPassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
-__ZN3JSC12RegExpObjectC2EN3WTF17NonNullPassRefPtrINS_9StructureEEENS2_INS_6RegExpEEE
-__ZN3JSC4Yarr23RegexPatternConstructor30atomParenthesesSubpatternBeginEb
-__ZN3JSC4Yarr25CharacterClassConstructor7putCharEt
-__ZN3JSC4Yarr25CharacterClassConstructor9addSortedERN3WTF6VectorItLm0EEEt
-__ZN3WTF6VectorItLm0EE14expandCapacityEm
-__ZN3JSC4Yarr23RegexPatternConstructor21atomCharacterClassEndEv
-__ZN3WTF6VectorIPN3JSC4Yarr14CharacterClassELm0EE14expandCapacityEmPKS4_
-__ZN3WTF6VectorIPN3JSC4Yarr14CharacterClassELm0EE14expandCapacityEm
+__ZN3JSC4Yarr18PatternDisjunction17addNewAlternativeEv
+__ZN3JSC4Yarr22YarrPatternConstructor15copyDisjunctionEPNS0_18PatternDisjunctionEb
 __ZN3WTF6VectorIPN3JSC4Yarr18PatternDisjunctionELm4EE14expandCapacityEm
-__ZN3JSC4Yarr23RegexPatternConstructor23setupDisjunctionOffsetsEPNS0_18PatternDisjunctionEjj
-__ZN3JSC4Yarr14RegexGenerator25generateParenthesesSingleERNS1_19TermGenerationStateE
-__ZN3JSC4Yarr14RegexGenerator30generateParenthesesDisjunctionERNS0_11PatternTermERNS1_19TermGenerationStateEj
-__ZN3WTF6VectorIN3JSC4Yarr14RegexGenerator26AlternativeBacktrackRecordELm0EE14expandCapacityEm
-__ZN3JSC4Yarr14RegexGenerator28generateCharacterClassGreedyERNS1_19TermGenerationStateE
-__ZN3JSC4Yarr14RegexGenerator19matchCharacterClassENS_12X86Registers10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86Assembler
-__ZN3JSC23MacroAssemblerX86Common4jumpEv
-__ZN3JSC4Yarr14RegexGenerator13readCharacterEiNS_12X86Registers10RegisterIDE
-__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-_JSContextGetGlobalObject
-__ZN3WTF13wtfThreadDataEv
-_JSClassCreate
-__ZN13OpaqueJSClass6createEPK17JSClassDefinition
-__ZN13OpaqueJSClassC2EPK17JSClassDefinitionPS_
-__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
-_JSClassRetain
-_JSObjectMake
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE4initEPNS_9ExecStateE
-__ZN13OpaqueJSClass9prototypeEPN3JSC9ExecStateE
-__ZN13OpaqueJSClass11contextDataEPN3JSC9ExecStateE
-__ZN3WTF9HashTableIP13OpaqueJSClassSt4pairIS2_P24OpaqueJSClassContextDataENS_18PairFirstExtractorIS6_EENS_7PtrHashIS2_EENS_14Pa
-__ZN24OpaqueJSClassContextDataC2EP13OpaqueJSClass
-_JSStringCreateWithUTF8CString
-_JSObjectSetProperty
-__ZN3JSC12APIEntryShimC1EPNS_9ExecStateEb
-__ZNK14OpaqueJSString10identifierEPN3JSC12JSGlobalDataE
-_JSClassRelease
-_JSContextGetGlobalContext
-_JSGlobalContextRetain
-_JSObjectGetProperty
-_JSValueToObject
-_JSValueProtect
-_JSObjectIsFunction
-_JSObjectCallAsFunction
-__ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
-__ZN3JSC10JSFunction4callEPNS_9ExecStateENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11Interpreter7executeEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEPNS_8JSObjectERKNS_7ArgListEPNS_14ScopeC
-__ZNK3JSC8NullNode6isNullEv
-__ZN3JSC3JIT16emit_op_neq_nullEPNS_11InstructionE
-__ZNK3JSC19JSStaticScopeObject14isDynamicScopeERb
-__ZN3JSC12RegExpObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL19regExpProtoFuncTestEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12RegExpObject9classInfoEv
-__ZN3JSC12RegExpObject4testEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC12RegExpObject5matchEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC6RegExp5matchERKNS_7UStringEiPN3WTF6VectorIiLm32EEE
-__ZN3JSC9WhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT16emit_op_stricteqEPNS_11InstructionE
-__ZN3JSC3JIT17compileOpStrictEqEPNS_11InstructionENS0_21CompileOpStrictEqTypeE
-__ZN3JSC3JIT17emit_op_nstricteqEPNS_11InstructionE
-__ZN3JSC3JIT20emitSlow_op_stricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT21emitSlow_op_nstricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC12ContinueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14continueTargetERKNS_10IdentifierE
-__ZN3JSCL7dateNowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_get_by_val
-__ZN7WebCore10StringImpl5upperEv
-_cti_op_get_by_id_generic
-_cti_op_put_by_id_fail
-__ZNK3JSC7UString8toUInt32EPbb
-__ZNK3JSC7UString8toDoubleEbb
-__ZNK3JSC7UString10UTF8StringEb
-__ZN3JSC18globalFuncParseIntEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12nonInlineNaNEv
-__ZN3JSC15toInt32SlowCaseEdRb
-__ZN3JSCL8parseIntERKNS_7UStringEi
-__ZN3JSC15globalFuncIsNaNEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK7WebCore6String8toDoubleEPb
-__ZN7WebCore10StringImpl8toDoubleEPb
-__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE11parseEscapeILb1ENS3_28CharacterClassParserDelegateEEEbRT0_
-__ZN3JSC4Yarr12spacesCreateEv
-__ZN3WTF6VectorIN3JSC4Yarr14CharacterRangeELm0EE14expandCapacityEmPKS3_
-__ZN3WTF6VectorIN3JSC4Yarr14CharacterRangeELm0EE14expandCapacityEm
-__ZN3JSC4Yarr25CharacterClassConstructor6appendEPKNS0_14CharacterClassE
-__ZN3JSC4Yarr25CharacterClassConstructor14addSortedRangeERN3WTF6VectorINS0_14CharacterRangeELm0EEEtt
-__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE28CharacterClassParserDelegate20atomPatternCharacterEt
-__ZN3JSC4Yarr14RegexGenerator24matchCharacterClassRangeENS_12X86Registers10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86Asse
-__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EED1Ev
-_cti_op_nstricteq
-__ZN3JSC27ctiPatchCallByReturnAddressEPNS_9CodeBlockENS_16ReturnAddressPtrENS_21MacroAssemblerCodePtrE
-__ZNK3JSC8JSString9toBooleanEPNS_9ExecStateE
-_cti_op_is_string
-__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_get_by_id_proto_list_full
-_cti_op_put_by_id_transition_realloc
-_cti_timeout_check
-__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
-_cti_op_mul
-__ZN3JSC4Yarr23RegexPatternConstructor25atomBuiltInCharacterClassENS0_23BuiltInCharacterClassIDEb
-_cti_op_convert_this
-__ZNK3JSC8JSString12toThisObjectEPNS_9ExecStateE
-__ZN3JSC12StringObjectC1EN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS_8JSStringE
-__ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue12toThisObjectEPNS_9ExecStateE
-__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
-__ZNK3JSC8JSObject11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
-__ZN3JSCL23stringProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12StringObject9classInfoEv
-__ZN7WebCore10StringImpl4costEv
-__ZN3JSC6JSCell11getCallDataERNS_8CallDataE
-__ZN3JSC24charCodeAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__ZN3JSCL14stringCharLoadERNS_19SpecializedThunkJITE
-_cti_op_get_by_val_string
-_JSValueToBoolean
-_JSValueUnprotect
-_JSGlobalContextRelease
-__ZN3JSC4Heap17collectAllGarbageEv
-__ZN3JSC4Heap9markRootsEv
-__ZN3JSC4Heap30markStackObjectsConservativelyERNS_9MarkStackE
-__ZN3JSC4Heap31markCurrentThreadConservativelyERNS_9MarkStackE
-__ZN3JSC4Heap39markCurrentThreadConservativelyInternalERNS_9MarkStackE
-__ZN3JSC4Heap18markConservativelyERNS_9MarkStackEPvS3_
-__ZN3JSC9MarkStack12markChildrenEPNS_6JSCellE
-__ZN3JSC8JSObject12markChildrenERNS_9MarkStackE
-__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
-__ZN3JSCL12markIfNeededERNS_9MarkStackENS_7JSValueE
-__ZN3JSC10JSFunction12markChildrenERNS_9MarkStackE
-__ZN3JSC18FunctionExecutable13markAggregateERNS_9MarkStackE
-__ZN3JSC12JSActivation12markChildrenERNS_9MarkStackE
-__ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE
-__ZN3JSC7JSArray12markChildrenERNS_9MarkStackE
-__ZN3JSC18GlobalEvalFunction12markChildrenERNS_9MarkStackE
-__ZN3JSC9CodeBlock13markAggregateERNS_9MarkStackE
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE12markChildrenERNS_9MarkStackE
-__ZN3JSC19JSStaticScopeObject12markChildrenERNS_9MarkStackE
-__ZN3JSC9MarkStack12releaseStackEPvm
-__ZN3JSC4Heap20markProtectedObjectsERNS_9MarkStackE
-__ZN3JSC12SmallStrings12markChildrenERNS_9MarkStackE
-__ZN3JSC9MarkStack7compactEv
-__ZN3JSC4Heap5sweepEv
-__ZN3JSC12DateInstanceD1Ev
-__ZN3JSC9CodeBlock13unlinkCallersEv
-__ZN3JSC8JSObjectD1Ev
-__ZN3JSC12JSActivationD1Ev
-__ZN3JSC12JSActivationD2Ev
-__ZN3JSC12StringObjectD1Ev
-__ZN3JSC4Heap12resizeBlocksEv
-__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm8EE14expandCapacityEm
-__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE14expandCapacityEmPKS4_
-__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE15reserveCapacityEm
-__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE15parseQuantifierEbjj
-__ZN3JSC4Yarr14RegexGenerator19TermGenerationState15jumpToBacktrackERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEP
-__ZN3JSC4Yarr14wordcharCreateEv
-__ZN3JSC4Yarr12digitsCreateEv
-__ZN3JSC4Yarr14RegexGenerator30generatePatternCharacterGreedyERNS1_19TermGenerationStateE
-__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE14expandCapacityEm
-___initializeScavenger_block_invoke_1
-__Z22TCMalloc_SystemReleasePvm
-__Z21TCMalloc_SystemCommitPvm
-__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
-__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
-__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSCL25numberConstructorMaxValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC18sqrtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__ZN3JSC3JIT26privateCompileGetByIdProtoEPNS_17StructureStubInfoEPNS_9StructureES4_RKNS_10IdentifierERKNS_12PropertySlotEmNS_16
-__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
-__ZN3JSC4Yarr13newlineCreateEv
-__ZN3JSC4Yarr14RegexGenerator29generateAssertionWordBoundaryERNS1_19TermGenerationStateE
-__ZN3JSC4Yarr14RegexGenerator22matchAssertionWordcharERNS1_19TermGenerationStateERNS_22AbstractMacroAssemblerINS_12X86Assembler
-__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL22stringProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7UString4findERKS0_j
-__ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC15constructRegExpEPNS_9ExecStateERKNS_7ArgListE
-__ZNK3JSC6JSCell9classInfoEv
-__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12RegExpObject4execEPNS_9ExecStateERKNS_7ArgListE
+__ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator17BacktrackingState19ReturnAddressRecordELm4EE14expandCapacityEm
+__ZN3JSCL19regExpProtoFuncExecEPNS_9ExecStateE
+__ZN3JSC12RegExpObject4execEPNS_9ExecStateE
 __ZNK3JSC17RegExpConstructor14arrayOfMatchesEPNS_9ExecStateE
 __ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
-__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEEj
+__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
 __ZN3JSC7JSArray15setSubclassDataEPv
-__ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZNK3JSC17RegExpConstructor10getBackrefEPNS_9ExecStateEj
-__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_put_by_id_generic
-__ZN3JSC17BytecodeGenerator29uncheckedRegisterForArgumentsEv
-__ZN3JSC3JIT22emit_op_init_argumentsEPNS_11InstructionE
-__ZN3JSC3JIT24emit_op_create_argumentsEPNS_11InstructionE
-__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common9ConditionENS_22AbstractMacroAssemblerINS_12X86Assemb
-_cti_op_load_varargs
-__ZN3JSC3JIT19patchPutByIdReplaceEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrE
-__ZN3JSC21ThrowableBinaryOpNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSCL20stringProtoFuncSplitEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_in
-__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue8toUInt32EPNS_9ExecStateE
-__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
-__ZN3JSC7JSArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC7JSArray9setLengthEj
-__ZN3JSC23CallFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator25emitJumpIfNotFunctionCallEPNS_10RegisterIDEPNS_5LabelE
-_cti_op_create_arguments
-__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC3JIT30privateCompileGetByIdProtoListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureES6_RK
-__ZN3JSC9ForInNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator20emitGetPropertyNamesEPNS_10RegisterIDES2_S2_S2_PNS_5LabelE
-__ZN3WTF6VectorIN3JSC12ForInContextELm0EE15reserveCapacityEm
-__ZN3JSC17BytecodeGenerator20emitNextPropertyNameEPNS_10RegisterIDES2_S2_S2_S2_PNS_5LabelE
-__ZN3JSC3JIT18emit_op_get_pnamesEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_get_by_pnameEPNS_11InstructionE
-__ZN3JSC3JIT22compileGetDirectOffsetENS_12X86Registers10RegisterIDES2_S2_S2_S2_
-__ZN3JSC3JIT18emit_op_next_pnameEPNS_11InstructionE
-__ZN3JSC3JIT24emitSlow_op_get_by_pnameEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_get_pnames
-__ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateEPNS_8JSObjectE
-__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC8JSObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC9Structure16getPropertyNamesERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSObject14hasOwnPropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-_cti_op_typeof
-__ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
-__ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE
-_cti_has_property
-__ZN3JSC3JIT26emit_op_tear_off_argumentsEPNS_11InstructionE
-__ZN3JSCL19arrayProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL11getPropertyEPNS_9ExecStateEPNS_8JSObjectEj
-__ZN3JSC9Arguments18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-_cti_op_tear_off_arguments
-__ZN3JSC10JSFunction19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZNK3JSC10JSFunction9classInfoEv
-__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-_cti_op_del_by_val
-__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-_cti_op_is_boolean
-__ZN3JSC10SwitchNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC13CaseBlockNode20emitBytecodeForBlockERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_
-__ZN3JSC13CaseBlockNode18tryOptimizedSwitchERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERiS7_
-__ZN3JSCL17processClauseListEPNS_14ClauseListNodeERN3WTF6VectorIPNS_14ExpressionNodeELm8EEERNS_10SwitchKindERbRiSB_
-__ZN3JSC17BytecodeGenerator11beginSwitchEPNS_10RegisterIDENS_10SwitchInfo10SwitchTypeE
-__ZN3WTF6VectorIN3JSC10SwitchInfoELm0EE14expandCapacityEm
-__ZN3JSC17BytecodeGenerator9endSwitchEjPN3WTF6RefPtrINS_5LabelEEEPPNS_14ExpressionNodeEPS3_ii
-__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
-__ZNK3JSC5Label4bindEii
-__ZN3JSC3JIT18emit_op_switch_immEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC12SwitchRecordELm0EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC17CodeLocationLabelELm0EE4growEm
-_cti_op_switch_imm
-__ZN3JSC4Yarr23RegexPatternConstructor8copyTermERNS0_11PatternTermE
-__ZL14compileBracketiPiPPhPPKtS3_P9ErrorCodeiS_S_R11CompileData
-__ZL32branchFindFirstAssertedCharacterPKhb
-__ZL20branchNeedsLineStartPKhjj
-__ZL17bracketIsAnchoredPKh
-_cti_op_get_by_id_array_fail
-__ZN3JSC17PropertyNameArray3addEPN7WebCore10StringImplE
-__ZN3WTF7HashSetIPN7WebCore10StringImplENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
-__ZN3WTF9HashTableIPN7WebCore10StringImplES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZN3WTF6VectorIN3JSC10IdentifierELm20EE14expandCapacityEm
-__ZN3JSCL28numberConstructorPosInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL28numberConstructorNegInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC4Heap5resetEv
-__ZN3JSC9Arguments12markChildrenERNS_9MarkStackE
-__ZN3JSC22JSPropertyNameIterator12markChildrenERNS_9MarkStackE
-__ZN3JSC3JIT10unlinkCallEPNS_12CallLinkInfoE
-__ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZNK3JSC7JSArray12subclassDataEv
+__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
+__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateE
+__ZN3JSC4Yarr22YarrPatternConstructor25atomBuiltInCharacterClassENS0_23BuiltInCharacterClassIDEb
+__ZN3JSC4Yarr12spacesCreateEv
+__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateE
+__ZN3JSCL6decodeEPNS_9ExecStateEPKcb
+__ZN3WTF6VectorItLm64EE9tryAppendItEEbPKT_m
+__ZN3WTF7Unicode18UTF8SequenceLengthEc
+__ZN3WTF7Unicode18decodeUTF8SequenceEPKc
+__ZN3WTF6VectorItLm64EE18tryReserveCapacityEm
+__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateE
+__ZN3JSC16globalFuncEscapeEPNS_9ExecStateE
+__ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateE
+__ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator11emitPostDecEPNS_10RegisterIDES2_
+__ZN3JSC3JIT16emit_op_post_decEPNS_11InstructionE
+__ZN3JSC3JIT20emitSlow_op_post_decEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT22emit_op_loop_if_lesseqEPNS_11InstructionE
+__ZN3JSC3JIT26emitSlow_op_loop_if_lesseqEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_pre_dec
+__ZN3JSC7JSArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC10Identifier4fromEPNS_9ExecStateEj
+__ZN3JSC7UString6numberEj
+__ZN3JSC17PropertyNameArray3addEPN3WTF10StringImplE
+__ZN3JSC9ExecState19arrayPrototypeTableEPS0_
+__ZN3JSC3JIT22emit_op_put_scoped_varEPNS_11InstructionE
+__ZN3JSC12JSGlobalData15getHostFunctionEPFPvPNS_9ExecStateEEPFNS_21MacroAssemblerCodePtrEPS0_PNS_14ExecutablePoolEE
+__ZN3JSC9JITThunks16hostFunctionStubEPNS_12JSGlobalDataEPFPvPNS_9ExecStateEEPFNS_21MacroAssemblerCodePtrES2_PNS_14ExecutablePoolEE
+__ZN3JSC20charAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSCL14stringCharLoadERNS_19SpecializedThunkJITE
+__ZN3JSCL12charToStringERNS_19SpecializedThunkJITEPNS_12JSGlobalDataENS_12X86Registers10RegisterIDES5_S5_
+__ZN3JSC19SpecializedThunkJIT8finalizeENS_21MacroAssemblerCodePtrE
+__ZN3JSC10JSFunctionC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPNS_16NativeExecutableE
+__ZN3JSC10JSFunctionC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureEiRKNS_10IdentifierEPNS_16NativeExecutableE
+__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateE
+__ZN3WTF14FastMallocZone9forceLockEP14_malloc_zone_t
+__ZN3WTF14FastMallocZone11forceUnlockEP14_malloc_zone_t
+__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm
+__ZN3JSCL21stringProtoFuncSearchEPNS_9ExecStateE
+__ZN3JSC3JIT30privateCompileGetByIdProtoListEPNS_17StructureStubInfoEPNS_30PolymorphicAccessStructureListEiPNS_9StructureES6_RKNS_10IdentifierERKNS_12PropertySlotEmPNS_9ExecStateE
+__ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
+__ZN3JSC4Yarr13YarrGenerator24matchCharacterClassRangeENS_12X86Registers10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListES8_PKNS0_14CharacterRangeEjPjPKtj
+__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_12X86Registers10RegisterIDES3_ii
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_19RelationalConditionENS_12X86Registers10RegisterIDES3_
+__ZN3JSC4Yarr13YarrGenerator17BacktrackingState24takeBacktracksToJumpListERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEPNS_14MacroAssemblerE
+_cti_op_get_by_id_proto_list_full
+__ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator6YarrOpELm128EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIN3JSC4Yarr13YarrGenerator6YarrOpELm128EE15reserveCapacityEm
+__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateE
+__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
+__ZN3JSC17RegExpConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithRegExpConstructorEPNS_9ExecStateE
+__ZN3JSC15constructRegExpEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListE
+__ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
+__ZN3JSC16BooleanPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC3JIT22compileGetDirectOffsetENS_12X86Registers10RegisterIDES2_PNS_9StructureEm
+__ZN3JSC3JIT15emit_op_resolveEPNS_11InstructionE
+_JSWeakObjectMapRemove
+__ZN3WTF7HashMapIPvPN3JSC7JSValueENS_7PtrHashIS1_EENS_10HashTraitsIS1_EENS7_IS4_EEE4takeERKS1_
+_JSObjectSetPrivate
+_cti_op_put_by_id_fail
+__ZN3JSC4Heap16allocateSlowCaseEm
+__ZN3JSC9CodeBlock14visitAggregateERNS_9MarkStackE
+__ZN3JSC13EvalCodeCache14visitAggregateERNS_9MarkStackE
+__ZN3JSC17StructureStubInfo14visitAggregateERNS_9MarkStackE
+__ZN3JSC14StructureChain13visitChildrenERNS_9MarkStackE
+__ZN3JSC12JSActivation13visitChildrenERNS_9MarkStackE
+__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_9MarkStackE
+__ZN3JSC9WeakGCMapIPvNS_8JSObjectENS_33DefaultWeakGCMapFinalizerCallbackIS1_S2_EEN3WTF7PtrHashIS1_EENS5_10HashTraitsIS1_EEE8finalizeENS_6HandleINS_7UnknownEEES1_
+__ZN3JSC20JSCallbackObjectData8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3WTF7HashMapISt4pairINS_6RefPtrINS_10StringImplEEEjEPN3JSC7JSValueENS6_24StructureTransitionTable4HashENS9_10HashTraitsENS_10HashTraitsIS8_EEE4takeERKS5_
 __ZN3JSC12RegExpObjectD1Ev
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEED1Ev
+__ZN3JSC20JSCallbackObjectDataD0Ev
+_JSClassRelease
+__ZN3JSC15WeakHandleOwnerD2Ev
+__ZN3JSC14ExecutablePool13systemReleaseERNS0_10AllocationE
+__ZN3WTF11OSAllocator8decommitEPvm
 __ZN3JSC18RegExpMatchesArrayD1Ev
-__ZNK3JSC7JSArray12subclassDataEv
-__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC22JSPropertyNameIteratorD1Ev
-__ZN3JSC22JSPropertyNameIteratorD2Ev
-__ZNK3JSC7JSArray9classInfoEv
-__ZN3JSC7JSArray15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
+__ZN3JSC14StructureChainD1Ev
+__ZN3JSC18JSCallbackFunctionD1Ev
+__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEE8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEED0Ev
+__ZN3JSC9WeakGCMapISt4pairIN3WTF6RefPtrINS2_10StringImplEEEjENS_9StructureENS_24StructureTransitionTable26WeakGCMapFinalizerCallbackENS8_4HashENS8_10HashTraitsEED1Ev
+__ZN3JSC18FunctionExecutableD1Ev
+_cti_op_put_by_id_transition_realloc
+__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC11makeUStringIPKcNS_7UStringES2_EES3_T_T0_T1_
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringES2_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
+__ZN3JSC15createTypeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC13ErrorInstance6createEPNS_12JSGlobalDataEPNS_9StructureERKNS_7UStringE
+__ZN3JSC13ErrorInstanceC2EPNS_12JSGlobalDataEPNS_9StructureERKNS_7UStringE
+__ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataENS_16ReturnAddressPtrERS2_
+_ctiVMThrowTrampoline
+_cti_vm_throw
+__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_7JSValueEj
+__ZNK3JSC13ErrorInstance15isErrorInstanceEv
+__ZNK3JSC8JSObject13exceptionTypeEv
+__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
+__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
+_ctiOpThrowNotCaught
+__ZN3JSC14ErrorPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateE
+__ZN3WTF13tryMakeStringIN3JSC7UStringEPKcS2_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
+__ZN3JSC13JSNotAnObjectD1Ev
+__ZN3JSC13ErrorInstanceD1Ev
+__ZN3WTF10StringImpl16findIgnoringCaseEPKcj
+_cti_op_is_undefined
+__ZN3JSC21ReadModifyResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17NumberConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC13jsAddSlowCaseEPNS_9ExecStateENS_7JSValueES2_
+__ZNK3JSC8JSString11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
+__ZN3JSC3JIT19patchPutByIdReplaceEPNS_9CodeBlockEPNS_17StructureStubInfoEPNS_9StructureEmNS_16ReturnAddressPtrEb
+_cti_op_get_by_id_getter_stub
+__ZN3JSC10ASTBuilder11makeDivNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT11emit_op_divEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_divEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_lesseq
+__ZN3JSC9Structure24removePropertyTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierERm
+__ZN3JSC9Structure6removeERKNS_10IdentifierE
+__ZN3WTF6VectorIjLm0EE14expandCapacityEm
+__ZN3JSC9Structure31removePropertyWithoutTransitionERNS_12JSGlobalDataERKNS_10IdentifierE
+__ZN3JSC12GetterSetter13visitChildrenERNS_9MarkStackE
+__ZN3JSC9Arguments13visitChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject17WeakMapsFinalizer8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC12StringObjectD1Ev
 __ZN3JSC9ArgumentsD1Ev
 __ZN3JSC9ArgumentsD2Ev
-__ZN3JSC7UString4fromEd
-__ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj
-__ZN3WTF4dtoaEPcdiPiS1_PS0_
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN7WebCore10StringImplE
-__ZN3WTF6VectorIPN3JSC9StructureELm8EE14expandCapacityEm
-_cti_op_resolve_base
-__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC20charAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
-__ZN3JSCL21stringProtoFuncCharAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator11emitPostIncEPNS_10RegisterIDES2_
-__ZN3JSC3JIT16emit_op_post_incEPNS_11InstructionE
-__ZN3JSC3JIT20emitSlow_op_post_incEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator18pushFinallyContextEPNS_5LabelEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator17popFinallyContextEv
-__ZN3JSC17BytecodeGenerator19highestUsedRegisterEv
-__ZN3JSC17BytecodeGenerator18emitJumpSubroutineEPNS_10RegisterIDEPNS_5LabelE
-__ZN3JSC17BytecodeGenerator20emitSubroutineReturnEPNS_10RegisterIDE
-__ZN3JSC3JIT11emit_op_jsrEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC3JIT7JSRInfoELm0EE14expandCapacityEm
+__ZN3JSC19SourceProviderCacheD1Ev
+__ZN3WTF20deleteAllPairSecondsIPN3JSC23SourceProviderCacheItemEKNS_7HashMapIiS3_NS_7IntHashIjEENS_10HashTraitsIiEENS7_IS3_EEEEEEvRT0_
+__ZN3WTF6VectorIN3JSC8LineInfoELm0EE14expandCapacityEm
+__ZN3WTF6VectorIN3JSC19ExpressionRangeInfoELm0EE14expandCapacityEm
+__ZNK3WTF6String8toDoubleEPbS1_
+__ZN3WTF6String6appendEc
+__ZN3WTF6String6numberEt
+__ZNK3WTF6String8foldCaseEv
+__ZN3WTF10StringImpl8foldCaseEv
+__ZN3JSC15NumberPrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL23numberProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC3JIT20emit_op_resolve_skipEPNS_11InstructionE
+_cti_op_resolve_skip
+__ZN3JSC19SourceProviderCache5clearEv
+__ZN3WTF11OSAllocator18releaseDecommittedEPvm
+__ZN3WTFeqERKNS_12AtomicStringEPKc
+_JSStringIsEqualToUTF8CString
+__ZN3JSC12RegisterFile17GlobalObjectOwner8finalizeENS_6HandleINS_7UnknownEEEPv
+__ZN3JSC12GetterSetterD1Ev
+__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
+__ZNK3WTF6String18simplifyWhiteSpaceEv
+__ZN3WTF10StringImpl18simplifyWhiteSpaceEv
+__ZN3JSC22JSPropertyNameIterator13visitChildrenERNS_9MarkStackE
+__ZN3WTFL43initializeMainThreadToProcessMainThreadOnceEv
+__ZN3WTF47initializeMainThreadToProcessMainThreadPlatformEv
+__ZN3WTF6String6numberEd
+__ZN3WTF10StringImpl5upperEv
+__ZN3WTF6String6removeEji
+__ZN3WTF6String6insertERKS0_j
+__ZN3WTF6String6insertEPKtjj
+__ZN3WTF10StringImpl7replaceEPS0_S1_
+__ZNK3WTF6String5splitEtbRNS_6VectorIS0_Lm0EEE
+__ZN3JSC12JSGlobalData18createContextGroupENS_15ThreadStackTypeE
+__ZN3JSC12JSGlobalData22clearBuiltinStructuresEv
+__ZN3JSC4Heap7destroyEv
+__ZN3JSC9JITThunks22clearHostFunctionStubsEv
+__ZN3JSC11MarkedSpace7destroyEv
+__ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC12JSGlobalDataD2Ev
+__ZN3JSC12RegisterFileD1Ev
+__ZN3JSC12RegisterFileD2Ev
+__ZNK3JSC9HashTable11deleteTableEv
+__ZN3JSC5LexerD1Ev
+__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_EENS8_IS2_EEEEEEvRT0_
+__ZN24OpaqueJSClassContextDataD1Ev
+__ZN24OpaqueJSClassContextDataD2Ev
+__ZN3JSC17CommonIdentifiersD2Ev
+__ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
+__ZN3JSC15IdentifierTableD2Ev
+__ZN3JSC4HeapD1Ev
+__ZN3JSC4HeapD2Ev
+__ZN3JSC14MachineThreadsD1Ev
+__ZN3JSC14MachineThreadsD2Ev
+__ZN3JSC25DefaultGCActivityCallbackD0Ev
+__ZN3JSC9JITThunksD1Ev
+__ZN3JSC12SmallStringsD1Ev
+__ZN13OpaqueJSClass26createNoAutomaticPrototypeEPK17JSClassDefinition
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEEC2ERNS_12JSGlobalDataEP13OpaqueJSClassPNS_9StructureE
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE4initEPNS_9ExecStateE
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN13OpaqueJSClass12staticValuesEPN3JSC9ExecStateE
+__ZN13OpaqueJSClass15staticFunctionsEPN3JSC9ExecStateE
+__ZN3JSC14JSGlobalObject14resetPrototypeERNS_12JSGlobalDataENS_7JSValueE
+_JSReportExtraMemoryCost
+_JSValueIsObject
+_JSValueMakeNull
+_JSObjectSetPrototype
+_JSStringCreateWithCharacters
+_JSValueGetType
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+_JSGarbageCollect
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE13visitChildrenERNS_9MarkStackE
+__ZN3JSC11makeUStringINS_7UStringES1_EES1_T_T0_
+__ZN3WTF13tryMakeStringIN3JSC7UStringES2_EENS_10PassRefPtrINS_10StringImplEEET_T0_
+__ZN3WTF13StringBuilder6appendEc
+_JSEvaluateScript
+__ZNK3JSC14JSGlobalObject17supportsProfilingEv
+__ZNK3JSC14JSGlobalObject22supportsRichSourceInfoEv
+__ZN3JSC8JSParser19parseThrowStatementINS_10ASTBuilderEEENT_9StatementERS3_
+__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC3JIT13emit_op_throwEPNS_11InstructionE
-__ZN3JSC3JIT12emit_op_sretEPNS_11InstructionE
-__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-_cti_op_lesseq
-__ZN3JSCL20stringProtoFuncMatchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC18RegExpMatchesArray17fillArrayInstanceEPNS_9ExecStateE
-__ZN3JSC14jsReplaceRangeEPNS_9ExecStateERKNS_7UStringEiiS4_
-__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
-__ZN3JSCL24stringProtoFuncSubstringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_create_arguments_no_params
-__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_pre_dec
-_cti_op_is_undefined
-__ZN3JSC13DeleteDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14emitDeleteByIdEPNS_10RegisterIDES2_RKNS_10IdentifierE
-__ZN3JSC23FunctionCallBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT17emit_op_del_by_idEPNS_11InstructionE
-_cti_op_del_by_id
-__ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
-__ZN3WTFL37parseDateFromNullTerminatedCharactersEPKcRbRi
-_cti_op_get_by_id_proto_fail
-__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
-__ZN3WTF6VectorItLm64EE15reserveCapacityEm
+_cti_op_throw
+__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
+__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
+_JSValueIsEqual
+__ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
+__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC10throwErrorEPNS_9ExecStateENS_7JSValueE
+__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
+__ZN3JSC10jsToNumberERKNS_7UStringE
+_JSStringGetLength
+_JSStringGetCharactersPtr
+_JSStringGetMaximumUTF8CStringSize
+_JSStringGetUTF8CString
+_JSValueIsStrictEqual
+__ZN3JSC21UStringSourceProviderD0Ev
+_JSCheckScriptSyntax
+__ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
+__ZN3JSC17ProgramExecutable11checkSyntaxEPNS_9ExecStateE
+__ZN3WTF6VectorIN3JSC9LabelInfoELm0EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC9LabelInfoELm0EE15reserveCapacityEm
+__ZN3JSC17createSyntaxErrorEPNS_14JSGlobalObjectERKNS_7UStringE
+__ZN3JSC12addErrorInfoEPNS_12JSGlobalDataEPNS_8JSObjectEiRKNS_10SourceCodeE
+__ZN3JSC8JSObject17putWithAttributesEPNS_12JSGlobalDataERKNS_10IdentifierENS_7JSValueEj
+_JSObjectCallAsConstructor
+__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
+__ZN3JSC11Interpreter16executeConstructEPNS_9ExecStateEPNS_8JSObjectENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
+__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+_JSObjectSetPropertyAtIndex
+_JSObjectMakeFunction
+__ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC8JSParser8popScopeERNS0_15AutoPopScopeRefEb
+__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateE
+__ZNK3JSC21UStringSourceProvider8getRangeEii
+__ZNK3JSC18FunctionExecutable11paramStringEv
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringES2_S4_S2_S4_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_T2_T3_T4_
+_JSObjectMakeFunctionWithCallback
+_JSObjectMakeConstructor
+__ZN3JSC21JSCallbackConstructorC1EPNS_14JSGlobalObjectEPNS_9StructureEP13OpaqueJSClassPFP13OpaqueJSValuePK15OpaqueJSContextS8_mPKPKS7_PSD_E
+_JSPropertyNameArrayGetNameAtIndex
+_JSObjectMakeDate
+__ZN3JSC13constructDateEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListE
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEPNS_9StructureEd
+__ZN3WTF8timeClipEd
+__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateE
+__ZNK3JSC12DateInstance26calculateGregorianDateTimeEPNS_9ExecStateE
+__ZN3JSC21msToGregorianDateTimeEPNS_9ExecStateEdbRNS_17GregorianDateTimeE
+__ZN3JSCL12getDSTOffsetEPNS_9ExecStateEdd
+__ZN3WTF18calculateDSTOffsetEdd
+__ZN3WTF18dateToDaysFrom1970Eiii
+__ZN3JSC10formatDateERKNS_17GregorianDateTimeERA100_c
+__ZN3JSC10formatTimeERKNS_17GregorianDateTimeERA100_c
+__ZN3WTF13tryMakeStringIPcPKcS1_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
+_JSObjectMakeError
+__ZN3JSC13ErrorInstance6createEPNS_9ExecStateEPNS_9StructureENS_7JSValueE
+_JSObjectMakeRegExp
+__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringEPcEENS_10PassRefPtrINS_10StringImplEEET_T0_T1_
+__ZN13OpaqueJSClassD1Ev
+__ZN13OpaqueJSClassD2Ev
 __ZN3JSC20EvalFunctionCallNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator12emitCallEvalEPNS_10RegisterIDES2_S2_PNS_13ArgumentsNodeEjjj
+__ZN3JSC17BytecodeGenerator12emitCallEvalEPNS_10RegisterIDES2_RNS_13CallArgumentsEjjj
+__ZN3JSC3JIT25emit_op_resolve_with_baseEPNS_11InstructionE
 __ZN3JSC3JIT17emit_op_call_evalEPNS_11InstructionE
 __ZN3JSC3JIT21emitSlow_op_call_evalEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_resolve
+_cti_op_resolve_with_base
+__ZN3JSC12JSActivation18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 _cti_op_call_eval
-__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEiiRNS_7JSValueE
-__ZN3JSC13LiteralParser5Lexer3lexERNS1_18LiteralParserTokenE
-__ZN3JSC13LiteralParser5parseENS0_11ParserStateE
-__ZN3JSC14EvalExecutable7compileEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_12JSGlobalDataEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPi
-__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16Fu
-__ZNK3JSC10ScopeChain10localDepthEv
-__ZNK3JSC12JSActivation9classInfoEv
-__ZN3JSC17BytecodeGeneratorC1EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrIN7WebCore10StringImplEE
-__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPKNS_8DebuggerERKNS_10ScopeChainEPN3WTF7HashMapINS9_6RefPtrIN7WebCore10StringImplEE
+__ZN3JSC11Interpreter8callEvalEPNS_9ExecStateEPNS_12RegisterFileEPNS_8RegisterEii
+__ZN3JSC14EvalExecutableC1EPNS_9ExecStateERKNS_10SourceCodeEb
+__ZN3JSC14EvalExecutable15compileInternalEPNS_9ExecStateEPNS_14ScopeChainNodeE
+__ZN3JSC6Parser5parseINS_8EvalNodeEEEN3WTF10PassRefPtrIT_EEPNS_14JSGlobalObjectEPNS_8DebuggerEPNS_9ExecStateERKNS_10SourceCodeEPNS_18FunctionParametersENS_18JSParserStrictnessEPPNS_8JSObjectE
+__ZN3JSCL19isNonASCIIIdentPartEi
+__ZN3JSC8EvalNode6createEPNS_12JSGlobalDataEPNS_14SourceElementsEPN3WTF6VectorISt4pairIPKNS_10IdentifierEjELm0EEEPNS6_IPNS_16FunctionBodyNodeELm0EEERNS5_7HashSetINS5_6RefPtrINS5_10StringImplEEENS_17IdentifierRepHashENS5_10HashTraitsISL_EEEERKNS_10SourceCodeEji
+__ZN3JSC14ScopeChainNode10localDepthEv
+__ZN3JSC17BytecodeGeneratorC1EPNS_8EvalNodeEPNS_14ScopeChainNodeEPN3WTF7HashMapINS5_6RefPtrINS5_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS5_10HashTraitsIS9_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
+__ZN3JSC17BytecodeGeneratorC2EPNS_8EvalNodeEPNS_14ScopeChainNodeEPN3WTF7HashMapINS5_6RefPtrINS5_10StringImplEEENS_16SymbolTableEntryENS_17IdentifierRepHashENS5_10HashTraitsIS9_EENS_26SymbolTableIndexHashTraitsEEEPNS_13EvalCodeBlockE
 __ZN3JSC8EvalNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZThn16_N3JSC8EvalNodeD0Ev
 __ZN3JSC8EvalNodeD0Ev
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEESt4pairIS4_NS1_IN3JSC14EvalExecutableEEEENS_18PairFirstExtractorIS9_EENS2
-__ZN3JSC9ExecState9thisValueEv
-__ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeEPNS_7JSValueE
-__ZN3JSC14EvalExecutable15generateJITCodeEPNS_9ExecStateEPNS_14ScopeChainNodeE
-__ZN3JSC9ThrowNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-_cti_op_throw
-__ZN3JSC9CodeBlock34reparseForExceptionInfoIfNecessaryEPNS_9ExecStateE
-__ZN3JSC18FunctionExecutable20reparseExceptionInfoEPNS_12JSGlobalDataEPNS_14ScopeChainNodeEPNS_9CodeBlockE
-__ZN3JSC11Interpreter14throwExceptionERPNS_9ExecStateERNS_7JSValueEjb
-__ZN3JSC9CodeBlock24handlerForBytecodeOffsetEj
-__ZN3JSC11Interpreter15unwindCallFrameERPNS_9ExecStateENS_7JSValueERjRPNS_9CodeBlockE
-__ZN3JSC9CodeBlock36hasGlobalResolveInfoAtBytecodeOffsetEj
+__ZN3WTF7HashMapINS_6RefPtrINS_10StringImplEEEN3JSC12WriteBarrierINS4_14EvalExecutableEEENS_10StringHashENS_10HashTraitsIS3_EENS9_IS7_EEE3setEPS2_RKS7_
+__ZN3WTF9HashTableINS_6RefPtrINS_10StringImplEEESt4pairIS3_N3JSC12WriteBarrierINS5_14EvalExecutableEEEENS_18PairFirstExtractorIS9_EENS_10StringHashENS_14PairHashTraitsINS_10HashTraitsIS3_EENSE_IS8_EEEESF_E6expandEv
+__ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEiPNS_14ScopeChainNodeE
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE20staticFunctionGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSC17ProgramExecutable13visitChildrenERNS_9MarkStackE
+__ZN3JSC19JSStaticScopeObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC14EvalExecutableD1Ev
+__ZN3JSC13EvalCodeBlockD0Ev
+__ZN3JSC12DateInstanceD1Ev
+__ZN3JSC21JSCallbackConstructorD1Ev
+__ZN3JSC17TypeOfResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT20emit_op_resolve_baseEPNS_11InstructionE
+__ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
+_cti_op_resolve
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEE17staticValueGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+_cti_op_resolve_base
+_cti_op_typeof
+__ZN3JSC20jsTypeStringForValueEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE11getCallDataERNS_8CallDataE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 _cti_op_push_new_scope
-__ZN3WTF7HashMapINS_6RefPtrIN7WebCore10StringImplEEEN3JSC16SymbolTableEntryENS5_17IdentifierRepHashENS_10HashTraitsIS4_EENS5_26
 __ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 _cti_op_pop_scope
-_cti_op_is_number
-__ZN3JSCL20arrayProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_stricteq
-__ZN3JSCL20arrayProtoFuncSpliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
-__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEPNS_9ExecStateEj
-__ZN3JSC8RopeImpl20destructNonRecursiveEv
-__ZN3JSC8RopeImpl23derefFibersNonRecursiveERN3WTF6VectorIPS0_Lm32EEE
-__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7JSArray3popEv
-__ZN7WebCore6String6numberEd
-__ZN3JSC10Identifier5equalEPKN7WebCore10StringImplEPKc
-__ZNK3JSC9Arguments9classInfoEv
-__ZN3JSC9Arguments15copyToRegistersEPNS_9ExecStateEPNS_8RegisterEj
-__ZN3JSC14InstanceOfNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator14emitInstanceOfEPNS_10RegisterIDES2_S2_S2_
-__ZN3JSC3JIT18emit_op_instanceofEPNS_11InstructionE
-__ZN3JSC3JIT22emitSlow_op_instanceofEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC17BytecodeGenerator11emitPostDecEPNS_10RegisterIDES2_
-__ZN3JSC3JIT16emit_op_post_decEPNS_11InstructionE
-__ZN3JSC3JIT20emitSlow_op_post_decEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_less
-__ZN3JSC13PrefixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-_cti_op_call_NotJSFunction
+__ZN3JSCL20isNonASCIIIdentStartEi
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE4callEPNS_9ExecStateE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE16getConstructDataERNS_13ConstructDataE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE9constructEPNS_9ExecStateE
+_cti_op_instanceof
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE11hasInstanceEPNS_9ExecStateENS_7JSValueES5_
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+_JSPropertyNameAccumulatorAddName
+__ZN3JSC17ObjectConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL41objectConstructorGetOwnPropertyDescriptorEPNS_9ExecStateE
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC18PropertyDescriptor15setConfigurableEb
+__ZN3JSC18PropertyDescriptor13setEnumerableEb
+__ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
+__ZNK3JSC18PropertyDescriptor8writableEv
+__ZNK3JSC18PropertyDescriptor10enumerableEv
+__ZNK3JSC18PropertyDescriptor12configurableEv
+__ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC12hasErrorInfoEPNS_9ExecStateEPNS_8JSObjectE
+__ZN3JSC9CodeBlock27lineNumberForBytecodeOffsetEj
+__ZN3JSC12addErrorInfoEPNS_9ExecStateEPNS_8JSObjectEiRKNS_10SourceCodeE
+__ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC15constructNumberEPNS_9ExecStateEPNS_14JSGlobalObjectENS_7JSValueE
+__ZN3JSC3JIT19emit_op_to_jsnumberEPNS_11InstructionE
+__ZN3JSC3JIT23emitSlow_op_to_jsnumberEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_to_jsnumber
+__ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE8toNumberEPNS_9ExecStateE
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
+__ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE9classNameEv
 __ZN3JSC17StringConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callStringConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSString8toNumberEPNS_9ExecStateE
-__ZNK3JSC7UString8toDoubleEv
+__ZN3JSCL21callStringConstructorEPNS_9ExecStateE
+__ZNK3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEE8toStringEPNS_9ExecStateE
+_cti_op_sub
+__ZN3JSC21JSCallbackConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL19constructJSCallbackEPNS_9ExecStateE
+_cti_op_to_primitive
+__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateE
+_cti_op_jmp_scopes
+__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
+__ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC9Structure27despecifyFunctionTransitionERNS_12JSGlobalDataEPS0_RKNS_10IdentifierE
+__ZN3JSC13PropertyTableC2ERNS_12JSGlobalDataEPNS_6JSCellERKS0_
+_cti_op_mul
+__ZNK3JSC8JSObject9classNameEv
+__ZN3JSC12RegisterFile21releaseExcessCapacityEv
+__ZN3JSC16JSCallbackObjectINS_14JSGlobalObjectEED1Ev
+__ZN3JSC19JSStaticScopeObjectD1Ev
+__ZN3JSC12NumberObjectD1Ev
+_JSObjectHasProperty
+_JSObjectGetPrototype
+__ZN3JSC8JSObject15unwrappedObjectEv
+__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
+__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj
+__ZNK3JSC7UString4utf8Eb
+__ZN3JSC12JSGlobalData13startSamplingEv
+__ZN3JSC11Interpreter13startSamplingEv
+__ZN3JSC15DateConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL28constructWithDateConstructorEPNS_9ExecStateE
+__ZN3JSC21gregorianDateTimeToMSEPNS_9ExecStateERKNS_17GregorianDateTimeEdb
+__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateE
+_cti_op_negate
+__ZN3JSC12JSGlobalData12stopSamplingEv
+__ZN3JSC11Interpreter12stopSamplingEv
+__ZN3JSC17BytecodeGenerator11emitPostIncEPNS_10RegisterIDES2_
+__ZN3JSC3JIT16emit_op_post_incEPNS_11InstructionE
+__ZN3JSC3JIT20emitSlow_op_post_incEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC10MathObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC17powThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSC12X86Assembler7cmpl_imEiiNS_12X86Registers10RegisterIDE
+__ZN3JSC23MacroAssemblerX86Common26branchConvertDoubleToInt32ENS_12X86Registers13XMMRegisterIDENS1_10RegisterIDERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListES2_
+__ZN3JSC19SpecializedThunkJIT11returnInt32ENS_12X86Registers10RegisterIDE
+__ZN3JSC19SpecializedThunkJIT12returnDoubleENS_12X86Registers13XMMRegisterIDE
+__ZN3JSC19SpecializedThunkJITD1Ev
+__ZN3WTF9HashTableIjSt4pairIjN3JSC12WriteBarrierINS2_7UnknownEEEENS_18PairFirstExtractorIS6_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEENSC_IS5_EEEESD_E6rehashEi
+__ZN3JSC3JIT11emit_op_neqEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_neqEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
+__ZN3JSC11Interpreter14dumpSampleDataEPNS_9ExecStateE
+__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL20callArrayConstructorEPNS_9ExecStateE
+__ZN3JSC10ASTBuilder11makeModNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT11emit_op_modEPNS_11InstructionE
+__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callNumberConstructorEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncAbsEPNS_9ExecStateE
+__ZN3JSCL28numberConstructorPosInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL18mathProtoFuncFloorEPNS_9ExecStateE
+_cti_op_mod
+_cti_timeout_check
+__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
+__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE14expandCapacityEm
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIPNS0_IN3JSC10RegisterIDELm32EEELm32EE15reserveCapacityEm
+__ZN3JSC3JIT13linkConstructEPNS_10JSFunctionEPNS_9CodeBlockES4_NS_21MacroAssemblerCodePtrEPNS_12CallLinkInfoEiPNS_12JSGlobalDataE
+__ZN3JSC14EvalExecutable13visitChildrenERNS_9MarkStackE
+__ZN3JSC17NumberConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithNumberConstructorEPNS_9ExecStateE
+__ZN3JSC12NumberObjectC1ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC18BooleanConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL31constructWithBooleanConstructorEPNS_9ExecStateE
+__ZN3JSC16constructBooleanEPNS_9ExecStateERKNS_7ArgListE
+__ZN3JSC13BooleanObjectC1ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC13BooleanObjectD1Ev
+__ZN3JSC9ExecState21arrayConstructorTableEPS0_
+__ZN3JSC17FunctionPrototype11getCallDataERNS_8CallDataE
+__ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
+__ZN3JSC8VoidNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSCL25numberConstructorNaNValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL28numberConstructorNegInfinityEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC18BooleanConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL22callBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7JSArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC9ExecState10arrayTableEPS0_
-__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL22callBooleanConstructorEPNS_9ExecStateE
+__ZN3JSC8JSString17substringFromRopeEPNS_9ExecStateEjj
+__ZN3WTF6VectorIN3JSC8JSString12RopeIterator8WorkItemELm16EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIN3JSC8JSString12RopeIterator8WorkItemELm16EE15reserveCapacityEm
+__ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateE
+__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateE
+__ZN3WTF6VectorItLm64EE17tryExpandCapacityEm
+__ZNK3WTF13DecimalNumber19toStringExponentialEPtj
+__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateE
+__ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9CommaNodeD1Ev
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateE
+__ZN3JSC17constructFunctionEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListE
+__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateE
+__ZN3JSC12StringObjectC1EPNS_9ExecStateEPNS_9StructureERKNS_7UStringE
+__ZN3JSC12StringObjectC2EPNS_9ExecStateEPNS_9StructureERKNS_7UStringE
+__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateE
+__ZN3JSC12NumberObject11getJSNumberEv
+__ZN3JSC11makeUStringINS_7UStringEPKcS1_EES1_T_T0_T1_
+__ZN3JSCL23booleanProtoFuncValueOfEPNS_9ExecStateE
+__ZN3JSC21ReadModifyBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC26fromCharCodeThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateE
+__ZN3JSCL18arrayProtoFuncSortEPNS_9ExecStateE
+__ZN3JSC7JSArray4sortEPNS_9ExecStateE
+__ZN3JSC7JSArray17compactForSortingEv
+__ZN3JSC4Heap18pushTempSortVectorEPN3WTF6VectorISt4pairINS_7JSValueENS_7UStringEELm0EEE
+__ZN3WTF6VectorIPNS0_ISt4pairIN3JSC7JSValueENS2_7UStringEELm0EEELm0EE15reserveCapacityEm
+__ZN3JSC4Heap17popTempSortVectorEPN3WTF6VectorISt4pairINS_7JSValueENS_7UStringEELm0EEE
+__ZN3JSCltERKNS_7UStringES2_
+__ZN3JSCL27compareByStringPairForQSortEPKvS1_
+__ZN3WTF16codePointCompareEPKNS_10StringImplES2_
 __ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
-__ZN3WTF6VectorIN3JSC26AVLTreeNodeForArrayCompareELm0EE14expandCapacityEm
-__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeEPNS_
+__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeE
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
-__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureEPNS_7JSValueE
-__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
 __ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE
-__ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL17mathProtoFuncATanEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZL17makeLeftShiftNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
-__ZN3JSC3JIT14emit_op_lshiftEPNS_11InstructionE
-__ZN3JSC3JIT14emit_op_bitandEPNS_11InstructionE
-__ZN3JSC3JIT14emit_op_rshiftEPNS_11InstructionE
-__ZN3JSC3JIT18emitSlow_op_lshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT18emitSlow_op_bitandEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT18emitSlow_op_rshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC32jsSpliceSubstringsWithSeparatorsEPNS_9ExecStateEPNS_8JSStringERKNS_7UStringEPKNS_11StringRangeEiPS5_i
-__ZN3JSCL26stringProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue20toIntegerPreserveNaNEPNS_9ExecStateE
-__ZNK3JSC7UString5rfindERKS0_j
-__ZN3WTF6VectorIiLm0EE15reserveCapacityEm
-__ZN3WTF6VectorINS_6RefPtrIN3JSC5LabelEEELm8EE15reserveCapacityEm
-__ZN3WTF6VectorISt4pairIiiELm8EE14expandCapacityEm
-__ZN3JSC11DoWhileNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC3JIT19emit_op_switch_charEPNS_11InstructionE
-_cti_op_switch_char
-__ZN3JSCL21stringProtoFuncSearchEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF10RefCountedIN3JSC6RegExpEE5derefEv
-__ZN3JSC14JSGlobalObjectD2Ev
-__ZN3JSC12RegisterFile17clearGlobalObjectEPNS_14JSGlobalObjectE
-__ZN3JSC17FunctionPrototypeD1Ev
-__ZN3JSC15ObjectPrototypeD1Ev
-__ZN3JSC14ArrayPrototypeD1Ev
-__ZN3JSC15StringPrototypeD1Ev
-__ZN3JSC16BooleanPrototypeD1Ev
-__ZN3JSC15NumberPrototypeD1Ev
-__ZN3JSC13DatePrototypeD1Ev
-__ZN3JSC15RegExpPrototypeD1Ev
-__ZN3JSC14ErrorPrototypeD1Ev
-__ZN3JSC20NativeErrorPrototypeD1Ev
-__ZN3JSC17ObjectConstructorD1Ev
-__ZN3JSC19FunctionConstructorD1Ev
-__ZN3JSC16ArrayConstructorD1Ev
-__ZN3JSC17StringConstructorD1Ev
-__ZN3JSC18BooleanConstructorD1Ev
-__ZN3JSC17NumberConstructorD1Ev
-__ZN3JSC15DateConstructorD1Ev
-__ZN3JSC17RegExpConstructorD1Ev
-__ZN3JSC16ErrorConstructorD1Ev
-__ZN3JSC22NativeErrorConstructorD1Ev
-__ZN3JSC10MathObjectD1Ev
-__ZN3JSC10JSONObjectD1Ev
-__ZN3JSC18GlobalEvalFunctionD1Ev
-__ZN3JSC19JSStaticScopeObjectD1Ev
-__ZN3JSC19JSStaticScopeObjectD2Ev
-__ZN3WTF6VectorIPvLm0EE14expandCapacityEmPKS1_
-__ZN3WTF6VectorIPvLm0EE15reserveCapacityEm
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEED1Ev
-__ZL25clearReferenceToPrototypeP13OpaqueJSValue
-_JSObjectGetPrivate
-__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE9classInfoEv
-__ZN3JSC28globalFuncEncodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL6encodeEPNS_9ExecStateERKNS_7ArgListEPKc
-__ZN3WTF6VectorItLm64EE9tryAppendItEEbPKT_m
-__ZN3WTF6VectorItLm64EE18tryReserveCapacityEm
-__ZN3JSC28globalFuncDecodeURIComponentEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL6decodeEPNS_9ExecStateERKNS_7ArgListEPKcb
-__ZN3WTF7Unicode18UTF8SequenceLengthEc
-__ZN3WTF7Unicode18decodeUTF8SequenceEPKc
-__ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSCltERKNS_7UStringES2_
-__ZN3WTF6VectorItLm0EE14expandCapacityEmPKt
-__ZN3WTF6VectorItLm0EE15reserveCapacityEm
-__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC18RegExpMatchesArray14deletePropertyEPNS_9ExecStateEj
-__ZN3JSC18RegExpMatchesArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC14EvalExecutableD0Ev
-__ZN3JSC13EvalCodeBlockD0Ev
-__ZN3JSC3JIT30emit_op_resolve_global_dynamicEPNS_11InstructionE
-__ZN3JSC3JIT34emitSlow_op_resolve_global_dynamicEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC19FunctionConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL32constructWithFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC3JIT18emit_op_jmp_scopesEPNS_11InstructionE
+__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureE
+__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
+__ZNK3JSC14ExpressionNode11isCommaNodeEv
+__ZNK3JSC7SubNode10isSubtractEv
+__ZN3JSC17BytecodeGenerator17argumentNumberForERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator27setIsNumericCompareFunctionEb
+__ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
+__ZN3JSCL20dateProtoFuncGetTimeEPNS_9ExecStateE
+__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSC24charCodeAtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZNK3JSC8NullNode6isNullEv
+__ZN3JSC3JIT15emit_op_eq_nullEPNS_11InstructionE
+_cti_op_is_number
+__ZNK3JSC7JSValue16synthesizeObjectEPNS_9ExecStateE
+__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateEPNS_14JSGlobalObjectENS_7JSValueE
+__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
+__ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateE
+__ZNK3JSC12DateInstance29calculateGregorianDateTimeUTCEPNS_9ExecStateE
+__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE13TrustedImmPtrENS_12X86Registers10RegisterIDE
+__ZN3JSCL24dateProtoFuncGetUTCMonthEPNS_9ExecStateE
+__ZN3JSCL23dateProtoFuncGetUTCDateEPNS_9ExecStateE
+__ZN3JSCL22dateProtoFuncGetUTCDayEPNS_9ExecStateE
+__ZN3JSCL24dateProtoFuncGetUTCHoursEPNS_9ExecStateE
+__ZN3JSCL26dateProtoFuncGetUTCMinutesEPNS_9ExecStateE
+__ZN3JSCL26dateProtoFuncGetUTCSecondsEPNS_9ExecStateE
+__ZN3JSCL31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateE
+__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateE
+__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateE
+__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateE
+__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateE
+__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateE
+__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateE
+__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateE
+__ZN3JSCL28dateProtoFuncGetMilliSecondsEPNS_9ExecStateE
+__ZN3JSC9parseDateEPNS_9ExecStateERKNS_7UStringE
+__ZN3WTF40parseES5DateFromNullTerminatedCharactersEPKc
+__ZN3JSC37parseDateFromNullTerminatedCharactersEPNS_9ExecStateEPKc
+__ZN3WTFL37parseDateFromNullTerminatedCharactersEPKcRbRi
+__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateE
+__ZN3JSC20formatDateUTCVariantERKNS_17GregorianDateTimeERA100_c
+__ZN3JSC13formatTimeUTCERKNS_17GregorianDateTimeERA100_c
+__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateE
+__ZN3JSC15DateConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSCL9dateParseEPNS_9ExecStateE
+__ZN3JSCL7dateUTCEPNS_9ExecStateE
+__ZN3JSC15globalFuncIsNaNEPNS_9ExecStateE
+_cti_op_is_object
+__ZN3JSC14jsIsObjectTypeENS_7JSValueE
+_cti_op_less
+__ZN3JSCL19jsStrDecimalLiteralERPKtS1_
+__ZN3WTF6VectorIcLm32EE14expandCapacityEm
+__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateE
+_cti_op_pre_inc
+__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateE
+__ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateE
+__ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateEib
+__ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateE
+__ZN3JSCL23dateProtoFuncSetSecondsEPNS_9ExecStateE
+__ZN3JSCL23dateProtoFuncSetMinutesEPNS_9ExecStateE
+__ZN3JSCL26dateProtoFuncSetUTCMinutesEPNS_9ExecStateE
+__ZN3JSCL21dateProtoFuncSetHoursEPNS_9ExecStateE
+__ZN3JSCL24dateProtoFuncSetUTCHoursEPNS_9ExecStateE
+__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateE
+__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateEib
+__ZN3JSCL23dateProtoFuncSetUTCDateEPNS_9ExecStateE
+__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateE
+__ZN3JSCL24dateProtoFuncSetUTCMonthEPNS_9ExecStateE
+__ZN3JSCL24dateProtoFuncSetFullYearEPNS_9ExecStateE
+__ZN3JSCL27dateProtoFuncSetUTCFullYearEPNS_9ExecStateE
+__ZN3JSC8JSParser18parseWithStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+_cti_op_construct_arityCheck
+__ZN3JSC8JSParser18parseWithStatementINS_10ASTBuilderEEENT_9StatementERS3_
 __ZN3JSC8WithNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitPushScopeEPNS_10RegisterIDE
 __ZN3JSC3JIT18emit_op_push_scopeEPNS_11InstructionE
 _cti_op_push_scope
-_cti_op_jmp_scopes
-__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE14expandCapacityEm
-__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL17mathProtoFuncASinEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_loop_if_lesseq
-__ZN3JSC7JSArray4sortEPNS_9ExecStateE
-__ZN3JSC7JSArray17compactForSortingEv
-__ZL18makeRightShiftNodePN3JSC12JSGlobalDataEPNS_14ExpressionNodeES3_b
+__ZN3JSC17DeleteResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC3JIT17emit_op_jneq_nullEPNS_11InstructionE
+__ZN3JSC3JIT26emit_op_ret_object_or_thisEPNS_11InstructionE
+__ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorIS2_EENS_7PtrHashIS2_EENS_10HashTraitsIS2_EES8_E6expandEv
+__ZN3WTF6VectorIN3JSC10IdentifierELm20EE15reserveCapacityEm
+__ZN3JSC9ExecState17globalObjectTableEPS0_
+__ZNK3JSC8JSObject16isVariableObjectEv
+__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE
+__ZN3JSC19FunctionConstructor11getCallDataERNS_8CallDataE
+__ZN3JSC15DateConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL25numberConstructorMaxValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL25numberConstructorMinValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSC18sqrtThunkGeneratorEPNS_12JSGlobalDataEPNS_14ExecutablePoolE
+__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEjRiS1_S1_
+__ZN3JSC11makeUStringINS_7UStringEPKcS1_S3_EES1_T_T0_T1_T2_
+__ZN3WTF13tryMakeStringIN3JSC7UStringEPKcS2_S4_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_T2_
+__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
+__ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_7JSValueE
+_cti_op_post_inc
+_cti_op_post_dec
+__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC10ASTBuilder18makeBitwiseNotNodeEPNS_14ExpressionNodeE
+__ZN3JSC3JIT14emit_op_bitnotEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitnotEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_jlesseq
+_cti_op_bitnot
+__ZN3JSC12StringObjectC1EPNS_9ExecStateEPNS_9StructureE
+__ZN3WTF6VectorIjLm16EE15reserveCapacityEm
+__ZNK3JSC8JSString8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
+__ZN3JSC10ASTBuilder17makeLeftShiftNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT14emit_op_lshiftEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_lshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_lshift
+__ZN3JSC10ASTBuilder18makeRightShiftNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT14emit_op_rshiftEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_rshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_rshift
+__ZN3JSC10ASTBuilder19makeURightShiftNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT15emit_op_urshiftEPNS_11InstructionE
+__ZN3JSC3JIT19emitSlow_op_urshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3WTF6VectorIPNS_14StringImplBaseELm32EE14expandCapacityEm
+_cti_op_urshift
+__ZN3JSC3JIT16emit_op_neq_nullEPNS_11InstructionE
+__ZN3JSC10ASTBuilder14makeBitAndNodeEPNS_14ExpressionNodeES2_b
+__ZN3JSC3JIT14emit_op_bitandEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_bitandEPNS_11InstructionERPNS_13SlowCaseEntryE
+_cti_op_bitand
+__ZN3JSC10ASTBuilder13makeBitOrNodeEPNS_14ExpressionNodeES2_b
 __ZN3JSC3JIT13emit_op_bitorEPNS_11InstructionE
 __ZN3JSC3JIT17emitSlow_op_bitorEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3WTF6VectorIN3JSC11StringRangeELm16EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEmPKS2_
-__ZN3WTF6VectorIN3JSC7UStringELm16EE15reserveCapacityEm
-__ZNK3JSC8JSString8toObjectEPNS_9ExecStateE
-__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-_cti_op_post_dec
+_cti_op_bitor
+__ZN3JSC10ASTBuilder14makeBitXOrNodeEPNS_14ExpressionNodeES2_b
 __ZN3JSC3JIT14emit_op_bitxorEPNS_11InstructionE
 __ZN3JSC3JIT18emitSlow_op_bitxorEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_bitand
-_cti_op_bitor
-__ZN7WebCore10StringImpl18simplifyWhiteSpaceEv
-_cti_op_is_object
-__ZN3JSC14jsIsObjectTypeENS_7JSValueE
-__ZN3JSC17PrototypeFunction11getCallDataERNS_8CallDataE
-__ZN3JSC14globalFuncEvalEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL19isNonASCIIIdentPartEi
-__ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeEPNS_7JSValueE
-_cti_op_mod
-__ZN7WebCore6String6appendEc
-__ZN7WebCore6String6appendEPKtj
-__ZN3JSC16globalFuncEscapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK7WebCore6String8foldCaseEv
-__ZN7WebCore10StringImpl8foldCaseEv
+_cti_op_bitxor
+_cti_op_div
+__ZN3JSCL23callFunctionConstructorEPNS_9ExecStateE
+__ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSC10JSFunction15argumentsGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZNK3JSC11Interpreter17retrieveArgumentsEPNS_9ExecStateEPNS_10JSFunctionE
-__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
-__ZN3WTF6VectorINS_6RefPtrIN3JSC10RegisterIDEEELm16EE15reserveCapacityEm
-__ZN3WTF6VectorIN7WebCore6StringELm0EE14expandCapacityEm
-__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
-__ZN3JSC18globalFuncUnescapeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorItLm64EE14expandCapacityEm
-__ZN3JSC3JIT16emit_op_jeq_nullEPNS_11InstructionE
-__ZN3WTF7CStringC1EPKc
-__ZN3WTFeqERKNS_7CStringES2_
-__ZN7WebCore17equalIgnoringCaseEPKtPKcj
-__ZNK7WebCore6String6toUIntEPb
-__ZN7WebCore10StringImpl6toUIntEPb
-__ZN7WebCore16charactersToUIntEPKtmPb
-__ZN7WebCore10StringImpl11reverseFindEti
-__ZN3WTF23waitForThreadCompletionEjPPv
-__ZN3WTF14FastMallocZone10statisticsEP14_malloc_zone_tP19malloc_statistics_t
-__ZNK7WebCore6String18simplifyWhiteSpaceEv
-__ZN7WebCore10StringImpl23defaultWritingDirectionEv
-__ZN3JSCL20dateProtoFuncSetTimeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21dateProtoFuncGetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12DateInstance26calculateGregorianDateTimeEPNS_9ExecStateE
-__ZN3JSC21msToGregorianDateTimeEPNS_9ExecStateEdbRNS_17GregorianDateTimeE
-__ZN3WTFL18calculateDSTOffsetEdd
-__ZN3JSCL20dateProtoFuncGetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue8inheritsEPKNS_9ClassInfoE
-__ZN3JSCL20dateProtoFuncGetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21dateProtoFuncGetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23dateProtoFuncGetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC3JIT17emit_op_jneq_nullEPNS_11InstructionE
-__ZN3JSCL20dateProtoFuncSetYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7JSValue7toInt32EPNS_9ExecStateERb
-__ZN3JSC21gregorianDateTimeToMSEPNS_9ExecStateERKNS_17GregorianDateTimeEdb
-__ZN3WTF18dateToDaysFrom1970Eiii
-__ZN3JSCL21dateProtoFuncSetMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23setNewValueFromDateArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
-__ZN3JSCL20dateProtoFuncSetDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24dateProtoFuncToGMTStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12DateInstance29calculateGregorianDateTimeUTCEPNS_9ExecStateE
-__ZN3JSC20formatDateUTCVariantERKNS_17GregorianDateTimeERA100_c
-__ZN3JSC13formatTimeUTCERKNS_17GregorianDateTimeERA100_c
-__ZN3JSC13tryMakeStringIPcPKcS1_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_
-__ZN3JSC9parseDateEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC37parseDateFromNullTerminatedCharactersEPNS_9ExecStateEPKc
-__ZN3JSC16ArrayConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL29constructWithArrayConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSCL27constructArrayWithSizeQuirkEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEEj
-__ZN3JSC17StringConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL30constructWithStringConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC12StringObjectC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringE
-__ZN3JSC12StringObjectC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7UStringE
-_cti_op_pre_inc
-__ZN3JSCL23dateProtoFuncGetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN7WebCore6String6removeEji
-__ZN3JSC23MacroAssemblerX86Common12branchTest32ENS0_9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_5Imm
-__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE7AddressENS4_5Imm32E
-__ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
-__ZNK3JSC7UStringixEj
-__ZN3JSC3JIT19emit_op_to_jsnumberEPNS_11InstructionE
-__ZN3JSC3JIT23emitSlow_op_to_jsnumberEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_to_jsnumber
-__ZN3JSCL30dateProtoFuncGetTimezoneOffsetEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC5Error6createEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS6_
-__ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSC9constructEPNS_9ExecStateENS_7JSValueENS_13ConstructTypeERKNS_13ConstructDataERKNS_7ArgListE
-__ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC22NativeErrorConstructor9constructEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC13ErrorInstanceC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
-__ZNK3JSC8JSObject13exceptionTypeEv
-__ZN3JSCL22errorProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC13tryMakeStringINS_7UStringEPKcS1_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_
-__ZN3JSC13ErrorInstanceD1Ev
-__ZN3JSC4Heap9freeBlockEm
-__ZN3JSC4Heap12freeBlockPtrEPNS_14CollectorBlockE
-__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierEjPNS_9CodeBlockE
-__ZN3JSC9CodeBlock32expressionRangeForBytecodeOffsetEPNS_9ExecStateEjRiS3_S3_
-__ZN3JSC10makeStringIPKcNS_7UStringEEES3_T_T0_
-__ZN3JSC13tryMakeStringIPKcNS_7UStringEEEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_
-__ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataENS_16ReturnAddressPtrERS2_
-_ctiVMThrowTrampoline
-_cti_vm_throw
-__ZNK3JSC8JSObject22isNotAnObjectErrorStubEv
-__ZNK3JSC7UString5asciiEv
-__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
-__ZN3JSCL17createJSLockCountEv
-__ZN3JSC6JSLock12DropAllLocksD1Ev
-__ZNK7WebCore6String5upperEv
-__ZN3JSC4Yarr23RegexPatternConstructor31atomParentheticalAssertionBeginEb
-__ZN3JSC4Yarr14RegexGenerator30generateParentheticalAssertionERNS1_19TermGenerationStateE
-__ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
-__ZN3WTF6VectorIPN3JSC4Yarr18PatternDisjunctionELm4EE14expandCapacityEmPKS4_
-__ZN3JSCL18regExpObjectSourceEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSObject9classNameEv
-__ZN3JSC13tryMakeStringIPKcNS_7UStringES2_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_
-__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE
-__ZN3JSC36constructBooleanFromImmediateBooleanEPNS_9ExecStateENS_7JSValueE
-__ZN3JSC13BooleanObjectC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC17ObjectConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL30constructWithObjectConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZNK3JSC9ArrayNode13isSimpleArrayEv
-__ZN3JSC7JSArray14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSCL27compareByStringPairForQSortEPKvS1_
-__ZN3JSC7compareERKNS_7UStringES2_
-__ZN3JSCL24dateProtoFuncToUTCStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC17NumberConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL30constructWithNumberConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC12NumberObjectC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSCL20isNonASCIIIdentStartEi
-__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC14MacroAssembler4peekENS_12X86Registers10RegisterIDEi
-__ZN3JSC4Yarr14RegexGenerator12atEndOfInputEv
-__ZN3JSC14MacroAssembler8branch32ENS_23MacroAssemblerX86Common9ConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemb
-__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList6linkToENS2_5LabelEPS2_
-__ZN3JSC14MacroAssembler4pokeENS_12X86Registers10RegisterIDEi
-__ZN3JSCL28substituteBackreferencesSlowERKNS_7UStringES2_PKiPNS_6RegExpEj
-__ZN3WTF6VectorItLm0EE6appendItEEvPKT_m
-_cti_op_to_primitive
-__ZN3JSC15constructNumberEPNS_9ExecStateENS_7JSValueE
-__ZNK3JSC12NumberObject9classInfoEv
-__Z12jsRegExpFreeP8JSRegExp
-__ZN3JSC13BooleanObjectD1Ev
-__ZN3JSCL18stringFromCharCodeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10makeStringIPKcNS_7UStringES2_EES3_T_T0_T1_
-__ZN3JSCL19dateProtoFuncGetDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC14EvalExecutable20reparseExceptionInfoEPNS_12JSGlobalDataEPNS_14ScopeChainNodeEPNS_9CodeBlockE
-__ZN3JSCL22objectProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN3JSCL24dateProtoFuncGetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
-__Z15jsc_pcre_xclassiPKh
-__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZNK3JSC17RegExpConstructor14getLeftContextEPNS_9ExecStateE
+__ZN3JSCL21callFunctionPrototypeEPNS_9ExecStateE
+__ZNK3JSC14ExpressionNode10isLocationEv
+__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_7JSValueE
+__ZN3JSC10JSFunction19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZNK3JSC9CommaNode11isCommaNodeEv
+__ZN3JSC20globalFuncParseFloatEPNS_9ExecStateE
+__ZN3WTF6VectorIN3JSC15SimpleJumpTableELm0EE14expandCapacityEm
+__ZNK3JSC5Label4bindEii
+__ZN3WTF6VectorIiLm0EEC2ERKS1_
+__ZN3JSC3JIT18emit_op_switch_immEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC17CodeLocationLabelELm0EE14expandCapacityEm
+_cti_op_switch_imm
+__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateE
+__ZN3JSC28createUndefinedVariableErrorEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC11makeUStringIPKcNS_7UStringEEES3_T_T0_
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringEEENS_10PassRefPtrINS_10StringImplEEET_T0_
+__ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator23emitThrowReferenceErrorERKNS_7UStringE
+__ZN3JSC3JIT29emit_op_throw_reference_errorEPNS_11InstructionE
+_cti_op_throw_reference_error
+__ZN3JSC16parseIntOverflowEPKcii
+__ZN3JSC9ExecState9mathTableEPS0_
+__ZN3JSCL17mathProtoFuncACosEPNS_9ExecStateE
+__ZN3JSCL17mathProtoFuncASinEPNS_9ExecStateE
+__ZN3JSCL17mathProtoFuncATanEPNS_9ExecStateE
+__ZN3JSCL18mathProtoFuncATan2EPNS_9ExecStateE
+__ZN3JSCL17mathProtoFuncCeilEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncCosEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncExpEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncLogEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncMinEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncPowEPNS_9ExecStateE
+__ZN3JSCL19mathProtoFuncRandomEPNS_9ExecStateE
+__ZN3JSCL18mathProtoFuncRoundEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncSinEPNS_9ExecStateE
+__ZN3JSCL17mathProtoFuncSqrtEPNS_9ExecStateE
+__ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateE
+__ZN3JSC9ExecState22numberConstructorTableEPS0_
+__ZN3JSC6JSCell11getJSNumberEv
+__ZN3JSCL21callObjectConstructorEPNS_9ExecStateE
+__ZN3JSC9ExecState22objectConstructorTableEPS0_
 _cti_to_object
-__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
-_cti_op_sub
-__ZN3JSC17NumberConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callNumberConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-_cti_op_bitxor
-_cti_op_is_function
-__ZN3JSC16jsIsFunctionTypeENS_7JSValueE
-__ZN3JSC12NumberObjectD1Ev
-__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEm
-__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
-__ZN7WebCore6String26fromUTF8WithLatin1FallbackEPKcm
-__ZN7WebCore6String8fromUTF8EPKcm
-__ZN3WTF10fastStrDupEPKc
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE
-__ZN3WTF6VectorIN3JSC15StringJumpTableELm0EE14expandCapacityEm
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEESt4pairIS4_N3JSC14OffsetLocationEENS_18PairFirstExtractorIS8_EENS2_10Stri
-__ZN3JSC3JIT21emit_op_switch_stringEPNS_11InstructionE
-__ZN3JSC13LiteralParser5Lexer9lexNumberERNS1_18LiteralParserTokenE
-__ZN3WTF6VectorIPNS_14StringImplBaseELm32EE14expandCapacityEm
-__ZN3JSC4Yarr17nonwordcharCreateEv
-__ZN3JSC3JIT15emit_op_eq_nullEPNS_11InstructionE
-_cti_op_switch_string
-__ZN3JSC12X86Assembler23X86InstructionFormatter15emitRexIfNeededEiii
-__ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_12X86Registers10RegisterIDES3_ii
-__ZN3JSC4Yarr6ParserINS0_23RegexPatternConstructorEE28CharacterClassParserDelegate25atomBuiltInCharacterClassENS0_23BuiltInChar
+__ZN3JSC9ExecState20numberPrototypeTableEPS0_
+__ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN3WTF10StringImplE
+__ZNK3JSC14ExpressionNode17isDotAccessorNodeEv
+__ZN3JSC9ExecState22stringConstructorTableEPS0_
+__ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateE
+__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateE
+__ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE
+__ZN3JSCL26stringProtoFuncToLowerCaseEPNS_9ExecStateE
+__ZN3JSCL26stringProtoFuncToUpperCaseEPNS_9ExecStateE
+__ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
+__ZN3JSC9ExecState11stringTableEPS0_
+__ZN3JSC12StringObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator18pushFinallyContextEPNS_5LabelEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator17popFinallyContextEv
+__ZN3JSC17BytecodeGenerator19highestUsedRegisterEv
+__ZN3JSC17BytecodeGenerator18emitJumpSubroutineEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator20emitSubroutineReturnEPNS_10RegisterIDE
+__ZN3JSC3JIT11emit_op_jsrEPNS_11InstructionE
+__ZN3WTF6VectorIN3JSC3JIT7JSRInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT12emit_op_sretEPNS_11InstructionE
+_cti_op_check_has_instance
+__ZN3JSC23createInvalidParamErrorEPNS_9ExecStateEPKcNS_7JSValueE
+__ZN3JSC11makeUStringIPKcNS_7UStringES2_S2_S2_EES3_T_T0_T1_T2_T3_
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringES2_S2_S2_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_T2_T3_
+_cti_op_is_string
+__ZN3JSC17RegExpConstructor18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC12RegExpObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL21regExpObjectLastIndexEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSC4Yarr12digitsCreateEv
+__ZN3WTF6VectorIN3JSC4Yarr12ByteCompiler21ParenthesesStackEntryELm0EE14expandCapacityEm
+__ZN3JSC4Yarr12ByteCompiler16closeAlternativeEi
+__ZN3WTF6VectorIN3JSC4Yarr8ByteTermELm0EE14expandCapacityEmPKS3_
+__ZN3WTF6VectorIPN3JSC4Yarr15ByteDisjunctionELm0EE14expandCapacityEm
+__ZN3JSC3JIT16emit_op_jeq_nullEPNS_11InstructionE
+__ZN3JSC18RegExpMatchesArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC4Yarr11Interpreter20backtrackParenthesesERNS0_8ByteTermEPNS1_18DisjunctionContextE
+__ZN3JSC4Yarr11YarrPattern21newlineCharacterClassEv
+__ZN3JSC4Yarr6ParserINS0_22YarrPatternConstructorEE28CharacterClassParserDelegate25atomBuiltInCharacterClassENS0_23BuiltInCharacterClassIDEb
+__ZN3WTF6VectorIPN3JSC4Yarr14CharacterClassELm0EE14expandCapacityEmPKS4_
+__ZN3JSC4Yarr25CharacterClassConstructor6appendEPKNS0_14CharacterClassE
 __ZN3JSC4Yarr15nonspacesCreateEv
-__ZN3JSCL25functionProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC21UStringSourceProvider8getRangeEii
-__ZNK3JSC7UString6substrEjj
-__ZN3JSC10makeStringINS_7UStringEPKcS1_EES1_T_T0_T1_
-__ZNK3JSC18FunctionExecutable11paramStringEv
-__ZN3WTF6VectorItLm64EE6appendItEEvPKT_m
-__ZN3JSC13tryMakeStringIPKcNS_7UStringES2_S3_S2_S3_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_T2_T3_T4_
-__ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10JSFunction14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSCL22arrayProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEmPKS5_
+__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EE14expandCapacityEm
+__ZN3JSC4Yarr15nondigitsCreateEv
+__ZN3JSC4Yarr13YarrGenerator29generateAssertionWordBoundaryEm
+__ZN3JSCL24setRegExpObjectLastIndexEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSC9ExecState11regExpTableEPS0_
+__ZN3JSC9ExecState20regExpPrototypeTableEPS0_
+__ZN3JSC8JSParser21parseDoWhileStatementINS_13SyntaxCheckerEEENT_9StatementERS3_
+__ZN3JSC9LabelNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC14PostfixDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF6VectorIiLm0EE15reserveCapacityEm
+__ZN3JSC3JIT19emit_op_switch_charEPNS_11InstructionE
+_cti_op_switch_char
+__ZN3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpList6appendERS3_
+__ZNK3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_22IdentityHashTranslatorIS3_S3_S7_EEEENS_22HashTableConstIteratorIS3_S3_S5_S7_S9_S9_EERKT_
+__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateE
+_cti_op_get_by_id_proto_fail
+__ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateE
+__ZN3JSCL17arrayProtoFuncPopEPNS_9ExecStateE
+__ZN3JSC7JSArray3popEv
 __ZN3JSC16ErrorConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC14constructErrorEPNS_9ExecStateERKNS_7ArgListE
-_cti_op_instanceof
-__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringE
-__ZN3WTF9HashTableIPN7WebCore10StringImplES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findIS3_NS_
-_cti_op_get_by_id_string_fail
-__ZN3JSCL20stringProtoFuncSliceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC14MacroAssembler4jumpENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelE
-__ZN3JSCL23regExpProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL18regExpObjectGlobalEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL22regExpObjectIgnoreCaseEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL21regExpObjectMultilineEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC13tryMakeStringIPKcNS_7UStringEPcEEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_
-__ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3WTFL10timerFiredEP16__CFRunLoopTimerPv
-__ZN7WebCore22charactersToUIntStrictEPKtmPbi
-__ZN3WTF9HashTableIjSt4pairIjN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEE
-__ZN3JSCL23dateProtoFuncSetMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23setNewValueFromTimeArgsEPNS_9ExecStateENS_7JSValueERKNS_7ArgListEib
-__ZN3JSCL23dateProtoFuncSetSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL28dateProtoFuncSetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL9dateParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21dateProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10formatDateERKNS_17GregorianDateTimeERA100_c
-__ZN3JSC10formatTimeERKNS_17GregorianDateTimeERA100_c
-__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC13UnaryPlusNode14stripUnaryPlusEv
-__ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL27objectProtoFuncLookupGetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZNK3JSC6JSCell14isGetterSetterEv
-__ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
-__ZN3JSCL27objectProtoFuncDefineGetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
-__ZNK3JSC12GetterSetter14isGetterSetterEv
-__ZN3JSC8JSObject15unwrappedObjectEv
-__ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
-__ZN3JSC16toUInt32SlowCaseEdRb
-__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE
-__ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
-_cti_op_get_by_id_getter_stub
-__ZN3JSC12GetterSetter12markChildrenERNS_9MarkStackE
-__ZN3JSCL17mathProtoFuncACosEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF13tryFastCallocEmm
-__ZN3JSC3JIT20emit_op_resolve_skipEPNS_11InstructionE
-_cti_op_resolve_skip
-__ZN3JSC3JIT15emit_op_urshiftEPNS_11InstructionE
-__ZN3JSC3JIT19emitSlow_op_urshiftEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSCL25stringProtoFuncCharCodeAtEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorIcLm0EE14expandCapacityEm
-__ZN3JSC15AssignErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC23ThrowableExpressionData14emitThrowErrorERNS_17BytecodeGeneratorENS_9ErrorTypeEPKc
-__ZN3JSC17BytecodeGenerator12emitNewErrorEPNS_10RegisterIDENS_9ErrorTypeENS_7JSValueE
-__ZN3JSC3JIT17emit_op_new_errorEPNS_11InstructionE
-__ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC26createNotAnObjectErrorStubEPNS_9ExecStateEb
-__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZNK3JSC22JSNotAnObjectErrorStub22isNotAnObjectErrorStubEv
-__ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateEPNS_22JSNotAnObjectErrorStubEjPNS_9CodeBlockE
-__ZN3JSC9CodeBlock37getByIdExceptionInfoForBytecodeOffsetEPNS_9ExecStateEjRNS_8OpcodeIDE
-__ZN3JSCL18createErrorMessageEPNS_9ExecStateEPNS_9CodeBlockEiiiNS_7JSValueENS_7UStringE
-__ZN3JSC10makeStringIPKcNS_7UStringES2_S3_S2_S3_S2_EES3_T_T0_T1_T2_T3_T4_T5_
-__ZN3JSC13tryMakeStringIPKcNS_7UStringES2_S3_S2_S3_S2_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_T2_T3_T4_T5_
-__ZN3JSC22JSNotAnObjectErrorStubD1Ev
-__ZN3JSC13JSNotAnObjectD1Ev
-__ZN3JSC12GetterSetterD1Ev
-__ZN3JSC20FixedVMPoolAllocator17coalesceFreeSpaceEv
-__ZN3WTF6VectorIPN3JSC13FreeListEntryELm0EE15reserveCapacityEm
-__ZN3JSCL35reverseSortFreeListEntriesByPointerEPKvS1_
-__ZN3JSCL33reverseSortCommonSizedAllocationsEPKvS1_
-__ZN7WebCore20equalIgnoringNullityEPNS_10StringImplES1_
-__ZN3JSC19globalFuncDecodeURIEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL29constructWithErrorConstructorEPNS_9ExecStateE
+__ZN3JSCL22compareNumbersForQSortEPKvS1_
+__ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateE
+__ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateE
+_cti_op_get_by_val_string
+__ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateE
+__ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatE
+__ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateE
 __ZN3JSC16ErrorConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL20callErrorConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL22functionProtoFuncApplyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC9Arguments11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
-__ZN3JSCL21functionProtoFuncCallEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10JSONObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-_cti_op_lshift
+__ZN3JSCL20callErrorConstructorEPNS_9ExecStateE
+__ZN3JSC17RegExpConstructor11getCallDataERNS_8CallDataE
+__ZN3JSCL21callRegExpConstructorEPNS_9ExecStateE
+__ZNK3JSC8JSObject15isErrorInstanceEv
+__ZN3JSC3JIT26emit_op_tear_off_argumentsEPNS_11InstructionE
+__ZN3JSC8jsStringEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC12JSActivation14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC17BytecodeGenerator14emitPutByIndexEPNS_10RegisterIDEjS2_
+__ZN3JSC3JIT20emit_op_put_by_indexEPNS_11InstructionE
+_cti_op_put_by_index
+__ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSC17DeleteBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator15emitDeleteByValEPNS_10RegisterIDES2_S2_
+_cti_op_del_by_val
+__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj
+__ZN3JSC14LogicalNotNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b
+_cti_op_tear_off_arguments
+__ZN3JSC9Arguments3putEPNS_9ExecStateEjNS_7JSValueE
+__ZN3JSCL29objectProtoFuncHasOwnPropertyEPNS_9ExecStateE
+__ZNK3JSC8JSObject14hasOwnPropertyEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateE
+__ZN3WTF11dtoaRoundDPEPcdiRbRiRj
+__ZN3WTF4dtoaILb0ELb0ELb1ELb0EEEvPcdiRbRiRj
+__ZN3JSCL28numberProtoFuncToExponentialEPNS_9ExecStateE
+__ZN3WTF11dtoaRoundSFEPcdiRbRiRj
+__ZN3WTF4dtoaILb0ELb1ELb0ELb0EEEvPcdiRbRiRj
+__ZN3JSCL26numberProtoFuncToPrecisionEPNS_9ExecStateE
+__ZN3JSC22NativeErrorConstructor16getConstructDataERNS_13ConstructDataE
+__ZN3JSCL35constructWithNativeErrorConstructorEPNS_9ExecStateE
+__ZN3JSC23MacroAssemblerX86Common8branch16ENS0_19RelationalConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE9BaseIndexENS4_12TrustedImm32E
+__ZN3JSC4Yarr17nonwordcharCreateEv
+__ZN3JSC12X86Assembler23X86InstructionFormatter15emitRexIfNeededEiii
+__ZN3JSC8JSString18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
+__ZN3JSCL28substituteBackreferencesSlowERKNS_7UStringES2_PKiPNS_6RegExpEm
+__ZN3WTF6VectorItLm0EE6appendItEEvPKT_m
+__ZN3JSC17createSyntaxErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSCL26regExpConstructorLastMatchEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZNK3JSC17RegExpConstructor10getBackrefEPNS_9ExecStateEj
+__ZN3JSCL28regExpConstructorLeftContextEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZNK3JSC17RegExpConstructor14getLeftContextEPNS_9ExecStateE
 __ZN3JSCL29regExpConstructorRightContextEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZNK3JSC17RegExpConstructor15getRightContextEPNS_9ExecStateE
-__ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
-__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6expan
-__ZN3WTF6VectorIN3JSC8RegisterELm8EE15reserveCapacityEm
-__ZN3WTF9HashTableIPN3JSC20MarkedArgumentBufferES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E4findI
-__ZN3JSCL26stringFromCharCodeSlowCaseEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC4Yarr12RegexPattern21newlineCharacterClassEv
-__ZN3JSC10JSFunction12lengthGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC18globalFuncIsFiniteEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC16ArrayConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL20callArrayConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL19stringProtoFuncTrimEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC15isStrWhiteSpaceEt
-__ZN3JSC6JSCell9getObjectEv
-_ctiOpThrowNotCaught
-__ZN3JSCL22numberProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12NumberObject11getJSNumberEv
-__ZN7WebCore10StringImpl6secureEt
-__ZN3JSC23createNotAFunctionErrorEPNS_9ExecStateENS_7JSValueEjPNS_9CodeBlockE
-_cti_op_rshift
-__ZN3JSC13JSNotAnObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3WTF6VectorIN3JSC22AbstractMacroAssemblerINS1_12X86AssemblerEE4JumpELm16EEC2ERKS6_
-__ZN3JSCL21arrayProtoFuncReverseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF21CrossThreadRefCountedINS_16OwnFastMallocPtrIKtEEE5derefEv
-_cti_op_post_inc
-__ZN3JSCL21regExpObjectLastIndexEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC3JIT14emit_op_bitnotEPNS_11InstructionE
-__ZN3JSC3JIT18emitSlow_op_bitnotEPNS_11InstructionERPNS_13SlowCaseEntryE
-_cti_op_bitnot
-__ZNK3JSC10JSONObject9classInfoEv
-_JSGlobalContextCreate
-_JSGlobalContextCreateInGroup
-__ZN3JSC12JSGlobalData18createContextGroupENS_15ThreadStackTypeE
-__ZN3JSC21createIdentifierTableEv
-__ZN3JSC4Heap29makeUsableFromMultipleThreadsEv
-__ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
-_JSValueMakeFromJSONString
-_JSValueIsNull
-_JSValueIsUndefined
-_JSValueIsBoolean
-_JSValueIsNumber
-_JSValueIsString
-__ZN3JSC14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-_JSValueIsInstanceOfConstructor
-__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
-_JSValueToNumber
-_JSObjectGetPropertyAtIndex
-_JSValueToStringCopy
-__ZN14OpaqueJSString6createERKN3JSC7UStringE
-_JSStringCopyCFString
-__ZN3JSC4Heap7destroyEv
-__ZN3JSC4Heap10freeBlocksEv
-__ZN3JSC14JSGlobalObjectD1Ev
-__ZN3JSC14JSGlobalObject25destroyJSGlobalObjectDataEPv
-__ZN3JSC12JSGlobalDataD1Ev
-__ZN3JSC12JSGlobalDataD2Ev
-__ZN3JSC12RegisterFileD1Ev
-__ZNK3JSC9HashTable11deleteTableEv
-__ZN3JSC5LexerD1Ev
-__ZN3WTF20deleteAllPairSecondsIP24OpaqueJSClassContextDataKNS_7HashMapIP13OpaqueJSClassS2_NS_7PtrHashIS5_EENS_10HashTraitsIS5_E
-__ZN3JSC17CommonIdentifiersD2Ev
-__ZN3JSC21deleteIdentifierTableEPNS_15IdentifierTableE
-__ZN3JSC15IdentifierTableD2Ev
-__ZN3JSC4HeapD1Ev
-__ZN3JSC9JITThunksD1Ev
-__ZN3JSC16NativeExecutableD0Ev
-__ZN3JSC12SmallStringsD1Ev
-__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC17ObjectConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL21callObjectConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateEj
-__ZN3JSCL18JSONProtoFuncParseEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7JSArray11fillArgListEPNS_9ExecStateERNS_20MarkedArgumentBufferE
-__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12StringObjectC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC23MacroAssemblerX86Common9urshift32ENS_12X86Registers10RegisterIDES2_
-_cti_op_urshift
-__ZN3JSC15ObjectPrototype3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3WTF6VectorIiLm32EE15reserveCapacityEm
+__ZN3WTF6VectorIN3JSC11StringRangeELm16EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC11StringRangeELm16EE15reserveCapacityEm
+__ZN3WTF6VectorIN3JSC7UStringELm16EE14expandCapacityEmPKS2_
+__ZN3WTF6VectorIN3JSC7UStringELm16EE15reserveCapacityEm
+__ZN3JSCL24regExpConstructorDollar1EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL24regExpConstructorDollar2EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3WTF6VectorIPNS0_IN3JSC5LabelELm32EEELm32EE14expandCapacityEmPKS4_
+__ZN3WTF6VectorIPNS0_IN3JSC5LabelELm32EEELm32EE15reserveCapacityEm
+__ZN3JSC8JSString16replaceCharacterEPNS_9ExecStateEtRKNS_7UStringE
+__ZN3JSCL19arrayProtoFuncShiftEPNS_9ExecStateE
+__ZN3JSC7JSArray10shiftCountEPNS_9ExecStateEi
+__ZN3JSCL21arrayProtoFuncUnShiftEPNS_9ExecStateE
+__ZN3JSC7JSArray12unshiftCountEPNS_9ExecStateEi
+__ZN3JSC7JSArray26increaseVectorPrefixLengthEj
+__ZN3WTF6VectorIPN3JSC14ExpressionNodeELm16EE14expandCapacityEm
+__ZN3JSCL21stringProtoFuncConcatEPNS_9ExecStateE
 __ZN3JSCL24regExpConstructorDollar3EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
 __ZN3JSCL24regExpConstructorDollar4EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC20MarkedArgumentBuffer9markListsERNS_9MarkStackERN3WTF7HashSetIPS0_NS3_7PtrHashIS5_EENS3_10HashTraitsIS5_EEEE
-__ZN3JSCL22numberProtoFuncToFixedEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16integerPartNoExpEd
-__ZN3JSC10makeStringINS_7UStringES1_PKcS1_EES1_T_T0_T1_T2_
-__ZN3JSC13tryMakeStringINS_7UStringES1_PKcS1_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_T2_
-__ZN3JSCL26numberProtoFuncToPrecisionEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL12charSequenceEci
-__ZN3JSC13tryMakeStringINS_7UStringEPKcS1_S1_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_T2_
-__ZN3JSCL24booleanProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC12JSActivation12toThisObjectEPNS_9ExecStateE
-_cti_op_div
-__ZN3JSC17BytecodeGenerator21emitComplexJumpScopesEPNS_5LabelEPNS_18ControlFlowContextES4_
-__ZN7WebCore10StringImpl7replaceEjjPS0_
-__ZN3JSC12RegExpObject11getCallDataERNS_8CallDataE
-__ZN3JSC12StringObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC9ExecState11stringTableEPS0_
-__ZNK3JSC7JSValue16synthesizeObjectEPNS_9ExecStateE
-__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSCL24regExpConstructorDollar5EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL24regExpConstructorDollar6EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL24regExpConstructorDollar9EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSC17RegExpConstructor3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL25setRegExpConstructorInputEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSCL22regExpConstructorInputEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL26regExpConstructorLastParenEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZNK3JSC17RegExpConstructor12getLastParenEPNS_9ExecStateE
+__ZN3JSCL26regExpConstructorMultilineEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
+__ZN3JSCL29setRegExpConstructorMultilineEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
+__ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateE
+__ZN3JSC14globalFuncEvalEPNS_9ExecStateE
+__ZN3JSC11Interpreter7executeEPNS_14EvalExecutableEPNS_9ExecStateEPNS_8JSObjectEPNS_14ScopeChainNodeE
+__ZNK3JSC19JSStaticScopeObject14isDynamicScopeERb
+__ZN3JSC9Arguments3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSC17ConservativeRoots4growEv
+__ZN3JSCL27objectProtoFuncDefineSetterEPNS_9ExecStateE
+__ZN3JSC15ObjectPrototype3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
+__ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateE
+__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL27objectProtoFuncLookupGetterEPNS_9ExecStateE
+__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
+__ZN3JSCL21stringProtoFuncAnchorEPNS_9ExecStateE
+__ZN3WTF13tryMakeStringIPKcN3JSC7UStringES2_S4_S2_EENS_10PassRefPtrINS_10StringImplEEET_T0_T1_T2_T3_
+__ZN3JSCL18stringProtoFuncBigEPNS_9ExecStateE
+__ZN3JSCL20stringProtoFuncBlinkEPNS_9ExecStateE
+__ZN3JSC22jsMakeNontrivialStringIPKcNS_7UStringES2_EENS_7JSValueEPNS_9ExecStateET_T0_T1_
+__ZN3JSCL19stringProtoFuncBoldEPNS_9ExecStateE
+__ZN3JSCL22stringProtoFuncItalicsEPNS_9ExecStateE
+__ZN3JSCL20stringProtoFuncFixedEPNS_9ExecStateE
+__ZN3JSCL24stringProtoFuncFontcolorEPNS_9ExecStateE
+__ZN3JSCL23stringProtoFuncFontsizeEPNS_9ExecStateE
+__ZN3JSCL19stringProtoFuncLinkEPNS_9ExecStateE
+__ZN3JSCL20stringProtoFuncSmallEPNS_9ExecStateE
+__ZN3JSCL21stringProtoFuncStrikeEPNS_9ExecStateE
+__ZN3JSCL18stringProtoFuncSubEPNS_9ExecStateE
+__ZN3JSCL18stringProtoFuncSupEPNS_9ExecStateE
+__ZN3JSC18PostfixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC19globalFuncEncodeURIEPNS_9ExecStateE
+__ZN3JSCL6encodeEPNS_9ExecStateEPKc
+__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateE
 __ZNK3JSC8JSObject20propertyIsEnumerableEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC7JSArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC14JSGlobalObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
-__ZNK3JSC18PropertyDescriptor10enumerableEv
-__ZN3JSCL22JSONProtoFuncStringifyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC11StringifierC2EPNS_9ExecStateENS_7JSValueES3_
-__ZN3JSC11Stringifier9stringifyENS_7JSValueE
-__ZN3JSC11Stringifier22appendStringifiedValueERNS_13StringBuilderENS_7JSValueEPNS_8JSObjectERKNS_27PropertyNameForFunctionCallE
-__ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
-__ZN3JSC11Stringifier6Holder18appendNextPropertyERS0_RNS_13StringBuilderE
-__ZN3JSC11Stringifier18appendQuotedStringERNS_13StringBuilderERKNS_7UStringE
-__ZN3JSC11StringifierD2Ev
-__ZN3JSC5Lexer19copyCodeWithoutBOMsEv
-__ZN3JSCL21dateProtoFuncSetHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC17FunctionPrototype11getCallDataERNS_8CallDataE
-__ZN3JSCL28dateProtoFuncGetMilliSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10makeStringINS_7UStringES1_EES1_T_T0_
-__ZN3JSC13tryMakeStringINS_7UStringES1_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_
-__ZN3JSC23MacroAssemblerX86Common8branch16ENS0_9ConditionENS_22AbstractMacroAssemblerINS_12X86AssemblerEE9BaseIndexENS4_5Imm32E
-__Z22jsc_pcre_ucp_othercasej
-__ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSCL24dateProtoFuncSetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL26dateProtoFuncSetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL26dateProtoFuncSetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23dateProtoFuncGetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23dateProtoFuncSetUTCDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24dateProtoFuncGetUTCHoursEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL26dateProtoFuncGetUTCMinutesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL26dateProtoFuncGetUTCSecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24dateProtoFuncSetFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorIiLm32EE15reserveCapacityEm
-__ZN3JSCL22regExpProtoFuncCompileEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC27PropertyNameForFunctionCall5valueEPNS_9ExecStateE
-_cti_op_new_error
-__ZN7WebCore6String6numberEj
-__ZN3JSCL27dateProtoFuncGetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24dateProtoFuncGetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL31dateProtoFuncToLocaleDateStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16formatLocaleDateEPNS_9ExecStateEPNS_12DateInstanceEdNS_20LocaleDateTimeFormatERKNS_7ArgListE
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc
-__ZN3JSCL23throwStackOverflowErrorEPNS_9ExecStateEPNS_12JSGlobalDataENS_16ReturnAddressPtrERS4_
-__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
-__ZN3JSC12RegisterFile21releaseExcessCapacityEv
+__ZN3JSC19globalFuncDecodeURIEPNS_9ExecStateE
+__ZN3JSC14createURIErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3WTF6VectorISt4pairIPN3JSC14ExpressionNodeENS2_10ASTBuilder12BinaryOpInfoEELm10EE14expandCapacityEmPKS7_
+__ZN3WTF6VectorISt4pairIPN3JSC14ExpressionNodeENS2_10ASTBuilder12BinaryOpInfoEELm10EE15reserveCapacityEm
+__ZN3WTF6VectorISt4pairIiiELm10EE14expandCapacityEm
+__ZN3JSC29callHostFunctionAsConstructorEPNS_9ExecStateE
+__ZN3JSC3JIT30emit_op_resolve_global_dynamicEPNS_11InstructionE
+__ZN3JSC3JIT34emitSlow_op_resolve_global_dynamicEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZNK3JSC9ArrayNode13isSimpleArrayEv
+__ZN3JSCL17arrayProtoFuncMapEPNS_9ExecStateE
+__ZN3JSCL21arrayProtoFuncForEachEPNS_9ExecStateE
+__ZN3JSCL20arrayProtoFuncFilterEPNS_9ExecStateE
+__ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateE
+__ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateE
+__ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateE
 __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-__ZN3JSC19FunctionConstructor11getCallDataERNS_8CallDataE
-__ZN7WebCore6String8fromUTF8EPKc
-__ZN3JSCL27dateProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC18BooleanConstructor16getConstructDataERNS_13ConstructDataE
-__ZN3JSCL31constructWithBooleanConstructorEPNS_9ExecStateEPNS_8JSObjectERKNS_7ArgListE
-__ZN3JSC16constructBooleanEPNS_9ExecStateERKNS_7ArgListE
-__ZN3JSC7JSArray11sortNumericEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
-__ZN3JSCL22compareNumbersForQSortEPKvS1_
-__ZN3WTF6VectorIjLm16EE15reserveCapacityEm
-__ZN3JSC8JSString16getIndexSlowCaseEPNS_9ExecStateEj
-__ZN3JSCL25numberConstructorNaNValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC6JSCell3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSC4Yarr15nondigitsCreateEv
-__ZN3JSCL7dateUTCEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC7ArgList2atEm
-__ZN3JSCL16mathProtoFuncTanEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC8JSObject16isVariableObjectEv
-__ZN7WebCore6String6insertERKS0_j
-__ZN7WebCore6String6insertEPKtjj
-__ZN7WebCore10StringImpl37createStrippingNullCharactersSlowCaseEPKtj
-__ZN3JSCL31dateProtoFuncToLocaleTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF7CString11mutableDataEv
-__ZN3WTF7CString18copyBufferIfNeededEv
-__ZN3JSCL18arrayProtoFuncSomeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC21DebuggerStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSCL31dateProtoFuncGetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF15ThreadConditionD1Ev
-__ZN3JSC18RegExpMatchesArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3WTF6VectorIPNS0_IN3JSC10IdentifierELm64EEELm32EE14expandCapacityEm
-__ZN3JSC15DateConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL8callDateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL22dateProtoFuncGetUTCDayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL19arrayProtoFuncEveryEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL23callFunctionConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL19stringProtoFuncLinkEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL25dateProtoFuncToDateStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC10throwErrorEPNS_9ExecStateEPNS_8JSObjectE
-__ZN3JSCL27dateProtoFuncSetUTCFullYearEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24dateProtoFuncSetUTCMonthEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL31dateProtoFuncSetUTCMillisecondsEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN7WebCore6String6numberEx
-__ZNK3JSC17NumberConstructor9classInfoEv
-__ZNK3JSC17RegExpConstructor9classInfoEv
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEESt4pairIS4_P19StaticFunctionEntryENS_18PairFirstExtractorIS8_EENS2_10Stri
-__ZN3WTF9HashTableINS_6RefPtrIN7WebCore10StringImplEEESt4pairIS4_P16StaticValueEntryENS_18PairFirstExtractorIS8_EENS2_10StringH
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE20staticFunctionGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC18JSCallbackFunctionC1EPNS_9ExecStateEPFPK13OpaqueJSValuePK15OpaqueJSContextPS3_S9_mPKS5_PS5_ERKNS_10IdentifierE
-__ZN3JSC18JSCallbackFunction11getCallDataERNS_8CallDataE
-__ZN3JSC18JSCallbackFunction4callEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
-_JSValueMakeUndefined
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE17staticValueGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-_JSValueMakeString
-__ZN3JSC18JSCallbackFunctionD1Ev
-_JSValueMakeBoolean
-_JSStringCreateWithCharacters
-_JSValueMakeNumber
-__ZN3JSC4Heap6isBusyEv
-__ZN7WebCore10StringImpl7replaceEtPS0_
-__ZNK3JSC8JSObject14isGlobalObjectEv
-__ZNK7WebCore6String5splitEtbRN3WTF6VectorIS0_Lm0EEE
-__ZN7WebCore6String6appendEt
-__ZNK3JSC7UString8toUInt32EPb
-__ZN3WTF9ByteArray6createEm
-__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
-__ZN3JSC11JSByteArrayC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE
+__ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
+__ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateE
+__ZNK3WTF6String7toFloatEPbS1_
+__ZN3WTF10StringImpl7toFloatEPbS1_
+__ZN3WTF17charactersToFloatEPKtmPbS2_
+__ZNK3JSC7UString5asciiEv
+__ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
+__ZN3WTF10StringImpl8toDoubleEPbS1_
+__ZN3JSCL21stringProtoFuncSubstrEPNS_9ExecStateE
+__ZN3WTF10StringImpl4findEPKcj
+__ZN3WTF6String26fromUTF8WithLatin1FallbackEPKcm
+__ZN3WTF10fastStrDupEPKc
+__ZN3WTF17equalIgnoringCaseEPKtPKcj
+__ZN3JSC10Identifier5equalEPKN3WTF10StringImplEPKc
+__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataENS_7JSValueEPKNS_9ClassInfoE
+__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
+__ZN3JSC11JSByteArrayC2EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE
+__ZN3JSC11JSByteArrayD1Ev
+_cti_op_get_by_val_byte_array
 __ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC11JSByteArray3putEPNS_9ExecStateEjNS_7JSValueE
+_cti_op_put_by_val_byte_array
+__ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
+__ZN3WTF10StringImpl16findIgnoringCaseEPS0_j
+__ZNK3WTF6String6toUIntEPb
+__ZN3WTF10StringImpl6toUIntEPb
+__ZN3WTF16charactersToUIntEPKtmPb
+__ZN3WTFeqERKNS_12AtomicStringERKNS_6VectorItLm0EEE
+__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
+__ZN3WTF7Unicode36calculateStringHashAndLengthFromUTF8EPKcS2_RjS3_
+__ZNK3WTF6String5splitERKS0_RNS_6VectorIS0_Lm0EEE
+__ZN3WTF10StringImpl7replaceEtPS0_
+__ZN3WTFeqERKNS_7CStringES2_
+__ZN3WTF10StringImpl6secureEtNS0_21LastCharacterBehaviorE
+__ZNK3WTF6String5upperEv
+__ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
+__ZNK3WTF6String6latin1Ev
+__ZN3WTF6VectorIN3JSC14ExecutablePool10AllocationELm2EE15reserveCapacityEm
+__ZN3WTF6String6numberEj
+__ZNK3JSC8JSObject14isGlobalObjectEv
+__ZN3WTF10StringImpl19characterStartingAtEj
+__ZN3WTF6String6appendEt
+__ZNK3WTF6String19characterStartingAtEj
 __ZN3JSC11JSByteArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 __ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
-_cti_op_get_by_val_byte_array
-_cti_op_put_by_val_byte_array
-_JSStringGetUTF8CString
-__ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZNK3JSC22NativeErrorConstructor9classInfoEv
-__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE9classNameEv
-__ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE
-__ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_7JSValueEjPNS_9CodeBlockE
-__ZNK3JSC4Heap11objectCountEv
-__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
-__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
-__ZN3JSC9Structure22getterSetterTransitionEPS0_
-__ZN3JSCL28objectProtoFuncIsPrototypeOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE11getCallDataERNS_8CallDataE
-__ZN3JSCL23arrayConstructorIsArrayEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21objectConstructorKeysEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd
-__ZN3JSC12DateInstanceC2EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd
-__ZN3JSCL24dateProtoFuncToISOStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC15createTypeErrorEPNS_9ExecStateEPKc
-__ZNK3JSC11JSByteArray9classInfoEv
-__ZN3JSC11JSByteArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC22NativeErrorConstructor11getCallDataERNS_8CallDataE
-__ZN3JSCL36objectConstructorGetOwnPropertyNamesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL41objectConstructorGetOwnPropertyDescriptorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
-__ZNK3JSC18PropertyDescriptor8writableEv
-__ZNK3JSC18PropertyDescriptor12configurableEv
-__ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
+__ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_
+_cti_op_get_by_id_array_fail
+__ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3WTF21CrossThreadRefCountedINS_16OwnFastMallocPtrIKtEEE5derefEv
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
+__ZN3JSC8DebuggerD2Ev
 __ZN3WTF14ThreadSpecificINS_13WTFThreadDataEE7destroyEPv
 __ZN3WTF13WTFThreadDataD1Ev
-__ZN7WebCore17AtomicStringTable7destroyEPS0_
+__ZN3WTF17AtomicStringTable7destroyEPS0_
 __ZN3JSC15IdentifierTableD1Ev
-__ZN3WTF9dayInYearEdi
-__ZN3WTF18monthFromDayInYearEib
-__ZN3WTF23dayInMonthFromDayInYearEib
-__ZN3JSC6Walker4walkENS_7JSValueE
-__ZN3WTF9HashTableIPN7WebCore10StringImplES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_EC2ERKSA_
-__ZN3WTF6VectorIPN3JSC7JSArrayELm16EE14expandCapacityEm
-__ZN3WTF6VectorIjLm16EE14expandCapacityEm
-__ZN3WTF6VectorIN3JSC11WalkerStateELm16EE14expandCapacityEm
-__ZL30makeGetterOrSetterPropertyNodePN3JSC12JSGlobalDataERKNS_10IdentifierES4_PNS_13ParameterNodeEPNS_16FunctionBodyNodeERKNS_1
-__ZN3JSC17BytecodeGenerator13emitPutGetterEPNS_10RegisterIDERKNS_10IdentifierES2_
-__ZN3JSC3JIT18emit_op_put_getterEPNS_11InstructionE
-_cti_op_put_getter
-__ZN3JSCL23booleanProtoFuncValueOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL19dateProtoFuncToJSONEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC9ExecState9dateTableEPS0_
-__ZN3JSC10Identifier4fromEPNS_9ExecStateEd
-__ZN3JSC13StringBuilder6appendEt
-__ZN3JSC17BytecodeGenerator13emitPutSetterEPNS_10RegisterIDERKNS_10IdentifierES2_
-__ZN3JSC3JIT18emit_op_put_setterEPNS_11InstructionE
-_cti_op_put_setter
-__ZN3JSCL23objectConstructorCreateEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL16definePropertiesEPNS_9ExecStateEPNS_8JSObjectES3_
-__ZN3JSCL20toPropertyDescriptorEPNS_9ExecStateENS_7JSValueERNS_18PropertyDescriptorE
-__ZN3JSC18PropertyDescriptor13setEnumerableEb
-__ZN3WTF6VectorIN3JSC18PropertyDescriptorELm0EE14expandCapacityEm
-__ZNK3JSC18PropertyDescriptor16isDataDescriptorEv
-__ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
-__ZN3JSCL13putDescriptorEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERNS_18PropertyDescriptorEjNS_7JSValueE
-__ZNK3JSC18PropertyDescriptor19isGenericDescriptorEv
-__ZN3JSCL31objectConstructorGetPrototypeOfEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
-__ZNK3JSC18PropertyDescriptor6getterEv
-__ZNK3JSC18PropertyDescriptor6setterEv
-__ZN3JSC18PropertyDescriptor15setConfigurableEb
-__ZN3JSC18PropertyDescriptor11setWritableEb
-__ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
-__ZN3JSCL33objectConstructorDefinePropertiesEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZNK3JSC18PropertyDescriptor7equalToEPNS_9ExecStateERKS0_
-__ZNK3JSC18PropertyDescriptor15attributesEqualERKS0_
-__ZNK3JSC18PropertyDescriptor22attributesWithOverrideERKS0_
-__ZN3JSCL31objectConstructorDefinePropertyEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC9ExecState11regExpTableEPS0_
-__ZN3JSC9Arguments19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC9ExecState11numberTableEPS0_
-__ZN3JSC9ExecState22regExpConstructorTableEPS0_
-__ZNK3JSC15RegExpPrototype9classInfoEv
-__ZNK3JSC10MathObject9classInfoEv
-__ZN3JSC9ExecState9mathTableEPS0_
-__ZN3JSC9ExecState9jsonTableEPS0_
-__ZN3JSCL20arrayProtoFuncReduceEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL25arrayProtoFuncReduceRightEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL28arrayProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC19JSStaticScopeObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN3JSCL25dateProtoFuncToTimeStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC7JSValueC1EPNS_9ExecStateEd
-__ZN3JSC15DeleteValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC16PostfixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC23ThrowableExpressionData14emitThrowErrorERNS_17BytecodeGeneratorENS_9ErrorTypeEPKcRKNS_7UStringE
-__ZN3JSC10makeStringINS_7UStringES1_S1_EES1_T_T0_T1_
-__ZN3JSC13tryMakeStringINS_7UStringES1_S1_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_
-__ZN3JSC15PrefixErrorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC23createInvalidParamErrorEPNS_9ExecStateEPKcNS_7JSValueEjPNS_9CodeBlockE
-__ZN3JSC10makeStringIPKcS2_S2_EENS_7UStringET_T0_T1_
-__ZN3JSC13tryMakeStringIPKcS2_S2_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_T1_
-__ZNK3JSC15DotAccessorNode17isDotAccessorNodeEv
-__ZNK3JSC14ExpressionNode17isDotAccessorNodeEv
-__ZN3JSC13JSNotAnObject3putEPNS_9ExecStateEjNS_7JSValueE
-__ZN3JSC14ArrayPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC13DatePrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC15StringPrototype24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC8JSString27getStringPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC17NumberConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC17RegExpConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSCL22regExpConstructorInputEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSC12RegExpObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC10MathObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC18RegExpMatchesArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC10JSFunction24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZN3JSC11JSByteArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
-__ZNK3JSC16JSCallbackObjectINS_8JSObjectEE8toStringEPNS_9ExecStateE
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringEilS5_
-__ZN3JSC17BytecodeGenerator35emitThrowExpressionTooDeepExceptionEv
-__ZN3JSCL25numberConstructorMinValueEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL18mathProtoFuncATan2EPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL28numberProtoFuncToExponentialEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC16parseIntOverflowEPKcii
-__ZN3JSCL29objectProtoFuncToLocaleStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24regExpConstructorDollar5EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL24regExpConstructorDollar6EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL24regExpConstructorDollar9EPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL25setRegExpConstructorInputEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
-__ZN3JSCL26regExpConstructorLastMatchEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL26regExpConstructorLastParenEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZNK3JSC17RegExpConstructor12getLastParenEPNS_9ExecStateE
-__ZN3JSCL26regExpConstructorMultilineEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL29setRegExpConstructorMultilineEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueE
-__ZNK3JSC17RegExpConstructor5inputEv
-__ZN3JSC10makeStringIPKcS2_EENS_7UStringET_T0_
-__ZN3JSC13tryMakeStringIPKcS2_EEN3WTF10PassRefPtrIN7WebCore10StringImplEEET_T0_
-__ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE
-__ZNK3JSC19JSStaticScopeObject12toThisObjectEPNS_9ExecStateE
-__ZN3JSCL23stringProtoFuncTrimLeftEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL24stringProtoFuncTrimRightEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC12JSActivation18getArgumentsGetterEv
-__ZN3JSC12JSActivation15argumentsGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-__ZN3JSCL28stringProtoFuncLocaleCompareEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF8Collator11userDefaultEv
-__ZNK3WTF8Collator7collateEPKtmS2_m
-__ZNK3WTF8Collator14createCollatorEv
-__ZN3WTF8CollatorD1Ev
-__ZN3WTF8Collator15releaseCollatorEv
-__ZN3JSC9Arguments14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSCL26callNativeErrorConstructorEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSCL21callFunctionPrototypeEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3JSC6JSCell11getJSNumberEv
-__ZN3JSCL16callRegExpObjectEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
-__ZN3WTF6VectorIN3JSC20FunctionRegisterInfoELm0EE14expandCapacityEm
-__ZN3JSC3JIT25emit_op_profile_will_callEPNS_11InstructionE
-__ZN3JSC3JIT24emit_op_profile_did_callEPNS_11InstructionE
-__ZN3JSC8Profiler8profilerEv
-__ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC16ProfileGenerator6createERKNS_7UStringEPNS_9ExecStateEj
-__ZN3JSC16ProfileGeneratorC2ERKNS_7UStringEPNS_9ExecStateEj
-__ZN3JSC7Profile6createERKNS_7UStringEj
-__ZN3JSC7ProfileC2ERKNS_7UStringEj
-__ZN3JSC11ProfileNodeC1ERKNS_14CallIdentifierEPS0_S4_
-__ZN3JSC16ProfileGenerator24addParentForConsoleStartEPNS_9ExecStateE
-__ZN3JSC8Profiler20createCallIdentifierEPNS_9ExecStateENS_7JSValueERKNS_7UStringEi
-__ZN3JSC16InternalFunction21calculatedDisplayNameEPNS_9ExecStateE
-__ZN3JSC16InternalFunction11displayNameEPNS_9ExecStateE
-__ZN3JSC11ProfileNode10insertNodeEN3WTF10PassRefPtrIS0_EE
-__ZN3WTF6VectorINS_6RefPtrIN3JSC11ProfileNodeEEELm0EE14expandCapacityEm
-__ZN3WTF6VectorINS_6RefPtrIN3JSC16ProfileGeneratorEEELm0EE15reserveCapacityEm
-_cti_op_profile_did_call
-__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateENS_7JSValueE
-__ZN3JSC16ProfileGenerator10didExecuteERKNS_14CallIdentifierE
-__ZN3JSC11ProfileNode10didExecuteEv
-_cti_op_profile_will_call
-__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateENS_7JSValueE
-__ZN3JSC16ProfileGenerator11willExecuteERKNS_14CallIdentifierE
-__ZN3JSC11ProfileNode11willExecuteERKNS_14CallIdentifierE
-__ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
-__ZN3JSC16ProfileGenerator13stopProfilingEv
-__ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
-__ZNK3JSC11ProfileNode25traverseNextNodePostOrderEv
-__ZN3JSC11ProfileNode13stopProfilingEv
-__ZN3JSC11ProfileNode11removeChildEPS0_
-__ZN3JSC11ProfileNode8addChildEN3WTF10PassRefPtrIS0_EE
-__ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
-__ZN3JSC4Heap16primaryHeapBeginEv
-__ZN3JSC4Heap14primaryHeapEndEv
-__ZNK3JSC18JSCallbackFunction9classInfoEv
-__ZN3WTF7HashSetIPN3JSC18FunctionExecutableENS_7PtrHashIS3_EENS_10HashTraitsIS3_EEE3addERKS3_
-__ZN3WTF9HashTableIPN3JSC18FunctionExecutableES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6expandE
-__ZN3JSC18FunctionExecutable9recompileEPNS_9ExecStateE
-__ZN3JSC8Profiler11willExecuteEPNS_9ExecStateERKNS_7UStringEi
-__ZN3JSC8Profiler10didExecuteEPNS_9ExecStateERKNS_7UStringEi
-__ZNK3JSC16ProfileGenerator5titleEv
-__ZN3JSC9CodeBlock33functionRegisterForBytecodeOffsetEjRi
-__ZN3JSC7ProfileD0Ev
-__ZN3WTF10RefCountedIN3JSC11ProfileNodeEE5derefEv
-__ZN3JSC34createTerminatedExecutionExceptionEPNS_12JSGlobalDataE
-__ZNK3JSC24TerminatedExecutionError13exceptionTypeEv
-__ZN3JSC24TerminatedExecutionErrorD1Ev
-__ZN3WTF8CollatorC1EPKc
-__ZN3WTF8Collator18setOrderLowerFirstEb
-_JSValueIsEqual
-__ZN3JSC7JSValue13equalSlowCaseEPNS_9ExecStateES0_S0_
-__ZNK3JSC14JSGlobalObject17supportsProfilingEv
-__ZNK7WebCore6String12toUIntStrictEPbi
-__ZN7WebCore10StringImpl12toUIntStrictEPbi
-__ZN3WTF12randomNumberEv
-__ZNK7WebCore6String8toUInt64EPb
-__ZN7WebCore10StringImpl8toUInt64EPb
-__ZN7WebCore18charactersToUInt64EPKtmPb
-_JSStringGetMaximumUTF8CStringSize
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
-__ZN7WebCore6String6numberEm
-__ZN3JSC4Heap17globalObjectCountEv
-__ZN3JSC4Heap20protectedObjectCountEv
-__ZN3JSC4Heap25protectedObjectTypeCountsEv
-__ZN3WTF9HashTableIPKcSt4pairIS2_jENS_18PairFirstExtractorIS4_EENS_7PtrHashIS2_EENS_14PairHashTraitsINS_10HashTraitsIS2_EENSA_I
-__ZNK3JSC6JSCell17isAPIValueWrapperEv
-__ZNK3JSC6JSCell22isPropertyNameIteratorEv
-__ZN3JSC4Heap16objectTypeCountsEv
-__ZNK3JSC22JSPropertyNameIterator22isPropertyNameIteratorEv
-__ZN3WTF20fastMallocStatisticsEv
-__ZNK3JSC4Heap10statisticsEv
-__ZN3WTF27releaseFastMallocFreeMemoryEv
-_JSStringIsEqualToUTF8CString
-__ZN3JSC16JSCallbackObjectINS_8JSObjectEE14callbackGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE
-_JSObjectSetPrivate
-__ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
-__ZN3WTF9HashTableIPN3JSC14JSGlobalObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZN3WTF9HashTableIPN3JSC14SourceProviderESt4pairIS3_PNS1_9ExecStateEENS_18PairFirstExtractorIS7_EENS_7PtrHashIS3_EENS_14PairHa
-__ZN3JSC7UString4fromEl
-__ZN3JSC3JIT13emit_op_debugEPNS_11InstructionE
-_cti_op_debug
-__ZN3JSC11Interpreter5debugEPNS_9ExecStateENS_11DebugHookIDEii
-__ZNK3JSC17DebuggerCallFrame4typeEv
-__ZNK3JSC17DebuggerCallFrame22calculatedFunctionNameEv
-__ZNK3JSC12JSActivation18isActivationObjectEv
-__ZNK3JSC17DebuggerCallFrame10thisObjectEv
-__ZN3WTF28setMainThreadCallbacksPausedEb
-__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
-__ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
-_JSValueIsObjectOfClass
index de5505f021af7a7220f0665345c52a897bd7ca3f..ed4cf2e2730a10fda48e3a1a58dcfe5d92f681b9 100644 (file)
@@ -1,86 +1,84 @@
 # JavaScriptCore - Qt4 build info
+
+include(../common.pri)
+
 VPATH += $$PWD
-CONFIG(debug, debug|release) {
-    # Output in JavaScriptCore/<config>
-    JAVASCRIPTCORE_DESTDIR = debug
-    # Use a config-specific target to prevent parallel builds file clashes on Mac
-    JAVASCRIPTCORE_TARGET = jscored
-} else {
-    JAVASCRIPTCORE_DESTDIR = release
-    JAVASCRIPTCORE_TARGET = jscore
-}
+
+# Use a config-specific target to prevent parallel builds file clashes on Mac
+mac: CONFIG(debug, debug|release): JAVASCRIPTCORE_TARGET = jscored
+else: JAVASCRIPTCORE_TARGET = jscore
+
+# Output in JavaScriptCore/<config>
+CONFIG(debug, debug|release) : JAVASCRIPTCORE_DESTDIR = debug
+else: JAVASCRIPTCORE_DESTDIR = release
+
 CONFIG(standalone_package) {
     isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated
 } else {
-    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = generated
-}
-
-CONFIG(standalone_package): DEFINES *= NDEBUG
-
-symbian: {
-    # Need to guarantee this comes before system includes of /epoc32/include
-    MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler"
-    LIBS += -lhal
-    # For hal.h
-    INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE
+    isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$OUTPUT_DIR/JavaScriptCore/generated
 }
 
-INCLUDEPATH = \
+JAVASCRIPTCORE_INCLUDEPATH = \
     $$PWD \
     $$PWD/.. \
+    $$PWD/../ThirdParty \
     $$PWD/assembler \
     $$PWD/bytecode \
     $$PWD/bytecompiler \
+    $$PWD/heap \
+    $$PWD/dfg \
     $$PWD/debugger \
     $$PWD/interpreter \
     $$PWD/jit \
     $$PWD/parser \
-    $$PWD/pcre \
     $$PWD/profiler \
     $$PWD/runtime \
     $$PWD/wtf \
+    $$PWD/wtf/gobject \
     $$PWD/wtf/symbian \
     $$PWD/wtf/unicode \
     $$PWD/yarr \
     $$PWD/API \
     $$PWD/ForwardingHeaders \
-    $$JSC_GENERATED_SOURCES_DIR \
-    $$INCLUDEPATH
+    $$JSC_GENERATED_SOURCES_DIR
+
+symbian {
+    PREPEND_INCLUDEPATH = $$JAVASCRIPTCORE_INCLUDEPATH $$PREPEND_INCLUDEPATH
+} else {
+    INCLUDEPATH = $$JAVASCRIPTCORE_INCLUDEPATH $$INCLUDEPATH
+}
+
+symbian {
+    LIBS += -lhal
+    INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE
+}
 
 win32-*: DEFINES += _HAS_TR1=0
 
-DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF
+DEFINES += BUILDING_JavaScriptCore BUILDING_WTF
 
-contains(JAVASCRIPTCORE_JIT,yes) {
-    DEFINES+=ENABLE_JIT=1
-    DEFINES+=ENABLE_YARR_JIT=1
-    DEFINES+=ENABLE_YARR=1
-}
-contains(JAVASCRIPTCORE_JIT,no) {
-    DEFINES+=ENABLE_JIT=0
-    DEFINES+=ENABLE_YARR_JIT=0
-    DEFINES+=ENABLE_YARR=0
+# CONFIG += text_breaking_with_icu
+
+contains (CONFIG, text_breaking_with_icu) {
+    DEFINES += WTF_USE_QT_ICU_TEXT_BREAKING=1
 }
 
 wince* {
     INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat
-    DEFINES += WINCEBASIC
-
-    INCLUDEPATH += $$PWD/../JavaScriptCore/os-wince
     INCLUDEPATH += $$PWD/../JavaScriptCore/os-win32
 }
 
 
-defineTest(addJavaScriptCoreLib) {
+defineTest(prependJavaScriptCoreLib) {
     # Argument is the relative path to JavaScriptCore.pro's qmake output
     pathToJavaScriptCoreOutput = $$ARGS/$$JAVASCRIPTCORE_DESTDIR
 
     win32-msvc*|wince* {
-        LIBS += -L$$pathToJavaScriptCoreOutput
-        LIBS += -l$$JAVASCRIPTCORE_TARGET
+        LIBS = -l$$JAVASCRIPTCORE_TARGET $$LIBS
+        LIBS = -L$$pathToJavaScriptCoreOutput $$LIBS
         POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib
     } else:symbian {
-        LIBS += -l$${JAVASCRIPTCORE_TARGET}.lib
+        LIBS = -l$${JAVASCRIPTCORE_TARGET}.lib $$LIBS
         # The default symbian build system does not use library paths at all. However when building with
         # qmake's symbian makespec that uses Makefiles
         QMAKE_LIBDIR += $$pathToJavaScriptCoreOutput
@@ -89,7 +87,7 @@ defineTest(addJavaScriptCoreLib) {
         # Make sure jscore will be early in the list of libraries to workaround a bug in MinGW
         # that can't resolve symbols from QtCore if libjscore comes after.
         QMAKE_LIBDIR = $$pathToJavaScriptCoreOutput $$QMAKE_LIBDIR
-        LIBS += -l$$JAVASCRIPTCORE_TARGET
+        LIBS = -l$$JAVASCRIPTCORE_TARGET $$LIBS
         POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}lib$${JAVASCRIPTCORE_TARGET}.a
     }
 
@@ -109,3 +107,4 @@ defineTest(addJavaScriptCoreLib) {
 
     return(true)
 }
+
index 8b0a0efa1123c092c9e2da9db70d518f4347e21c..3e0caf8df920b5de0aa9b7a3b187ae2dcaba22ff 100644 (file)
@@ -16,20 +16,6 @@ CONFIG += depend_includepath
 
 contains(QT_CONFIG, embedded):CONFIG += embedded
 
-CONFIG(QTDIR_build) {
-    # Make sure we compile both debug and release on mac when inside Qt.
-    # This line was extracted from qbase.pri instead of including the whole file
-    win32|mac:!macx-xcode:CONFIG += debug_and_release
-} else {
-    CONFIG(debug, debug|release) {
-        OBJECTS_DIR = obj/debug
-    } else { # Release
-        OBJECTS_DIR = obj/release
-    }
-    # Make sure that build_all follows the build_all config in WebCore
-    mac:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework):!build_pass:CONFIG += build_all
-}
-
 # WebCore adds these config only when in a standalone build.
 # qbase.pri takes care of that when in a QTDIR_build
 # Here we add the config for both cases since we don't include qbase.pri
@@ -42,14 +28,6 @@ CONFIG(QTDIR_build) {
     CONFIG += no_debug_info
 }
 
-# Pick up 3rdparty libraries from INCLUDE/LIB just like with MSVC
-win32-g++ {
-    TMPPATH            = $$quote($$(INCLUDE))
-    QMAKE_INCDIR_POST += $$split(TMPPATH,";")
-    TMPPATH            = $$quote($$(LIB))
-    QMAKE_LIBDIR_POST += $$split(TMPPATH,";")
-}
-
 *-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2
 *-g++*:QMAKE_CXXFLAGS_RELEASE += -O3
 
@@ -65,7 +43,10 @@ wince* {
     SOURCES += $$QT_SOURCE_TREE/src/3rdparty/ce-compat/ce_time.c
 }
 
-include(pcre/pcre.pri)
+include(yarr/yarr.pri)
+include(wtf/wtf.pri)
+
+INSTALLDEPS += all
 
 SOURCES += \
     API/JSBase.cpp \
@@ -79,7 +60,11 @@ SOURCES += \
     API/JSValueRef.cpp \
     API/OpaqueJSString.cpp \
     assembler/ARMAssembler.cpp \
+    assembler/ARMv7Assembler.cpp \
     assembler/MacroAssemblerARM.cpp \
+    assembler/MacroAssemblerSH4.h \
+    assembler/MacroAssemblerSH4.cpp \
+    assembler/SH4Assembler.h \
     bytecode/CodeBlock.cpp \
     bytecode/JumpTable.cpp \
     bytecode/Opcode.cpp \
@@ -87,20 +72,36 @@ SOURCES += \
     bytecode/StructureStubInfo.cpp \
     bytecompiler/BytecodeGenerator.cpp \
     bytecompiler/NodesCodegen.cpp \
+    heap/ConservativeRoots.cpp \
+    heap/HandleHeap.cpp \
+    heap/HandleStack.cpp \
+    heap/Heap.cpp \
+    heap/MachineStackMarker.cpp \
+    heap/MarkStack.cpp \
+    heap/MarkStackPosix.cpp \
+    heap/MarkStackSymbian.cpp \
+    heap/MarkStackWin.cpp \
+    heap/MarkedBlock.cpp \
+    heap/MarkedSpace.cpp \
     debugger/DebuggerActivation.cpp \
     debugger/DebuggerCallFrame.cpp \
     debugger/Debugger.cpp \
+    dfg/DFGByteCodeParser.cpp \
+    dfg/DFGGraph.cpp \
+    dfg/DFGJITCodeGenerator.cpp \
+    dfg/DFGJITCompiler.cpp \
+    dfg/DFGNonSpeculativeJIT.cpp \
+    dfg/DFGOperations.cpp \
+    dfg/DFGSpeculativeJIT.cpp \
     interpreter/CallFrame.cpp \
     interpreter/Interpreter.cpp \
     interpreter/RegisterFile.cpp \
     jit/ExecutableAllocatorFixedVMPool.cpp \
-    jit/ExecutableAllocatorPosix.cpp \
-    jit/ExecutableAllocatorSymbian.cpp \
-    jit/ExecutableAllocatorWin.cpp \
     jit/ExecutableAllocator.cpp \
     jit/JITArithmetic.cpp \
     jit/JITArithmetic32_64.cpp \
     jit/JITCall.cpp \
+    jit/JITCall32_64.cpp \
     jit/JIT.cpp \
     jit/JITOpcodes.cpp \
     jit/JITOpcodes32_64.cpp \
@@ -108,10 +109,12 @@ SOURCES += \
     jit/JITPropertyAccess32_64.cpp \
     jit/JITStubs.cpp \
     jit/ThunkGenerators.cpp \
+    parser/JSParser.cpp \
     parser/Lexer.cpp \
     parser/Nodes.cpp \
     parser/ParserArena.cpp \
     parser/Parser.cpp \
+    parser/SourceProviderCache.cpp \
     profiler/Profile.cpp \
     profiler/ProfileGenerator.cpp \
     profiler/ProfileNode.cpp \
@@ -124,7 +127,6 @@ SOURCES += \
     runtime/BooleanObject.cpp \
     runtime/BooleanPrototype.cpp \
     runtime/CallData.cpp \
-    runtime/Collector.cpp \
     runtime/CommonIdentifiers.cpp \
     runtime/Completion.cpp \
     runtime/ConstructData.cpp \
@@ -140,8 +142,8 @@ SOURCES += \
     runtime/Executable.cpp \
     runtime/FunctionConstructor.cpp \
     runtime/FunctionPrototype.cpp \
+    runtime/GCActivityCallback.cpp \
     runtime/GetterSetter.cpp \
-    runtime/GlobalEvalFunction.cpp \
     runtime/Identifier.cpp \
     runtime/InitializeThreading.cpp \
     runtime/InternalFunction.cpp \
@@ -154,11 +156,10 @@ SOURCES += \
     runtime/JSGlobalData.cpp \
     runtime/JSGlobalObject.cpp \
     runtime/JSGlobalObjectFunctions.cpp \
-    runtime/JSImmediate.cpp \
     runtime/JSLock.cpp \
     runtime/JSNotAnObject.cpp \
-    runtime/JSNumberCell.cpp \
     runtime/JSObject.cpp \
+    runtime/JSObjectWithGlobalObject.cpp \
     runtime/JSONObject.cpp \
     runtime/JSPropertyNameIterator.cpp \
     runtime/JSStaticScopeObject.cpp \
@@ -168,10 +169,6 @@ SOURCES += \
     runtime/JSWrapperObject.cpp \
     runtime/LiteralParser.cpp \
     runtime/Lookup.cpp \
-    runtime/MarkStackPosix.cpp \
-    runtime/MarkStackSymbian.cpp \
-    runtime/MarkStackWin.cpp \
-    runtime/MarkStack.cpp \
     runtime/MathObject.cpp \
     runtime/NativeErrorConstructor.cpp \
     runtime/NativeErrorPrototype.cpp \
@@ -184,7 +181,6 @@ SOURCES += \
     runtime/PropertyDescriptor.cpp \
     runtime/PropertyNameArray.cpp \
     runtime/PropertySlot.cpp \
-    runtime/PrototypeFunction.cpp \
     runtime/RegExpConstructor.cpp \
     runtime/RegExp.cpp \
     runtime/RegExpObject.cpp \
@@ -193,51 +189,36 @@ SOURCES += \
     runtime/RopeImpl.cpp \
     runtime/ScopeChain.cpp \
     runtime/SmallStrings.cpp \
+    runtime/StrictEvalActivation.cpp \
     runtime/StringConstructor.cpp \
     runtime/StringObject.cpp \
     runtime/StringPrototype.cpp \
+    runtime/StringRecursionChecker.cpp \
     runtime/StructureChain.cpp \
     runtime/Structure.cpp \
     runtime/TimeoutChecker.cpp \
     runtime/UString.cpp \
-    wtf/Assertions.cpp \
-    wtf/ByteArray.cpp \
-    wtf/CurrentTime.cpp \
-    wtf/DateMath.cpp \
-    wtf/dtoa.cpp \
-    wtf/FastMalloc.cpp \
-    wtf/HashTable.cpp \
-    wtf/MD5.cpp \
-    wtf/MainThread.cpp \
-    wtf/qt/MainThreadQt.cpp \
-    wtf/qt/StringQt.cpp \
-    wtf/qt/ThreadingQt.cpp \
-    wtf/RandomNumber.cpp \
-    wtf/RefCountedLeakCounter.cpp \
-    wtf/symbian/BlockAllocatorSymbian.cpp \
-    wtf/ThreadingNone.cpp \
-    wtf/Threading.cpp \
-    wtf/TypeTraits.cpp \
-    wtf/WTFThreadData.cpp \
-    wtf/text/AtomicString.cpp \
-    wtf/text/CString.cpp \
-    wtf/text/StringImpl.cpp \
-    wtf/text/StringStatics.cpp \
-    wtf/text/WTFString.cpp \
-    wtf/unicode/CollatorDefault.cpp \
-    wtf/unicode/icu/CollatorICU.cpp \
-    wtf/unicode/UTF8.cpp \
-    yarr/RegexCompiler.cpp \
-    yarr/RegexInterpreter.cpp \
-    yarr/RegexJIT.cpp
+    yarr/YarrJIT.cpp \
+
+*sh4* {
+    QMAKE_CXXFLAGS += -mieee -w
+    QMAKE_CFLAGS   += -mieee -w
+}
 
 # Generated files, simply list them for JavaScriptCore
-SOURCES += \
-    $${JSC_GENERATED_SOURCES_DIR}/Grammar.cpp
 
-!contains(DEFINES, USE_SYSTEM_MALLOC) {
-    SOURCES += wtf/TCSystemAlloc.cpp
+symbian: {
+    symbian-abld|symbian-sbsv2 {
+        MMP_RULES += ALWAYS_BUILD_AS_ARM
+    }  else {
+        QMAKE_CFLAGS -= --thumb
+        QMAKE_CXXFLAGS -= --thumb
+    }
+    QMAKE_CXXFLAGS.ARMCC += -OTime -O3
+}
+
+lessThan(QT_GCC_MAJOR_VERSION, 5):lessThan(QT_GCC_MINOR_VERSION, 6) {
+    # Disable C++0x mode in JSC for those who enabled it in their Qt's mkspec.
+    *-g++*:QMAKE_CXXFLAGS -= -std=c++0x -std=gnu++0x
 }
 
-# Disable C++0x mode in JSC for those who enabled it in their Qt's mkspec
-*-g++*:QMAKE_CXXFLAGS -= -std=c++0x -std=gnu++0x
index 13b21bbbe61a53d93561979e4df818013e57c329..21d620415f234dc18be077a3285932f4e132d650 100644 (file)
@@ -33,3 +33,4 @@
 /* Work around bug with C++ library that screws up Objective-C++ when exception support is disabled. */
 #undef try
 #undef catch
+
diff --git a/JavaScriptCoreSources.bkl b/JavaScriptCoreSources.bkl
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/KeywordLookupGenerator.py b/KeywordLookupGenerator.py
new file mode 100644 (file)
index 0000000..6ba7e34
--- /dev/null
@@ -0,0 +1,230 @@
+# Copyright (C) 2010 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.
+
+import sys
+import string
+import operator
+
+keywordsText = open(sys.argv[1]).read()
+
+# Observed weights of the most common keywords, rounded to 2.s.d
+keyWordWeights = {
+    "catch": 0.01,
+    "try": 0.01,
+    "while": 0.01,
+    "case": 0.01,
+    "break": 0.01,
+    "new": 0.01,
+    "in": 0.01,
+    "typeof": 0.02,
+    "true": 0.02,
+    "false": 0.02,
+    "for": 0.03,
+    "null": 0.03,
+    "else": 0.03,
+    "return": 0.13,
+    "var": 0.13,
+    "if": 0.16,
+    "function": 0.18,
+    "this": 0.18,
+}
+
+
+def allWhitespace(str):
+    for c in str:
+        if not(c in string.whitespace):
+            return False
+    return True
+
+
+def parseKeywords(keywordsText):
+    lines = keywordsText.split("\n")
+    lines = [line.split("#")[0] for line in lines]
+    lines = [line for line in lines if (not allWhitespace(line))]
+    name = lines[0].split()
+    terminator = lines[-1]
+    if not name[0] == "@begin":
+        raise Exception("expected description beginning with @begin")
+    if not terminator == "@end":
+        raise Exception("expected description ending with @end")
+
+    lines = lines[1:-1]  # trim off the old heading
+    return [line.split() for line in lines]
+
+
+def makePadding(size):
+    str = ""
+    for i in range(size):
+        str = str + " "
+    return str
+
+
+class Trie:
+    def __init__(self, prefix):
+        self.prefix = prefix
+        self.keys = {}
+        self.value = None
+
+    def insert(self, key, value):
+        if len(key) == 0:
+            self.value = value
+            return
+        if not (key[0] in self.keys):
+            self.keys[key[0]] = Trie(key[0])
+        self.keys[key[0]].insert(key[1:], value)
+
+    def coalesce(self):
+        keys = {}
+        for k, v in self.keys.items():
+            t = v.coalesce()
+            keys[t.prefix] = t
+        self.keys = keys
+        if self.value != None:
+            return self
+        if len(self.keys) != 1:
+            return self
+        (prefix, suffix) = self.keys.items()[0]
+        res = Trie(self.prefix + prefix)
+        res.value = suffix.value
+        res.keys = suffix.keys
+        return res
+
+    def fillOut(self, prefix=""):
+        self.fullPrefix = prefix + self.prefix
+        weight = 0
+        if self.fullPrefix in keyWordWeights:
+            weight = weight + keyWordWeights[self.fullPrefix]
+        self.selfWeight = weight
+        for trie in self.keys.values():
+            trie.fillOut(self.fullPrefix)
+            weight = weight + trie.weight
+        self.keys = [(trie.prefix, trie) for trie in sorted(self.keys.values(), key=operator.attrgetter('weight'), reverse=True)]
+        self.weight = weight
+
+    def printSubTreeAsC(self, indent):
+        str = makePadding(indent)
+
+        if self.value != None:
+            print(str + "if (!isIdentPart(code[%d])) {" % (len(self.fullPrefix)))
+            print(str + "    internalShift<%d, DoNotBoundsCheck>();" % len(self.fullPrefix))
+            print(str + "    if (shouldCreateIdentifier)")
+            print(str + ("        data->ident = &m_globalData->propertyNames->%sKeyword;" % self.fullPrefix))
+            print(str + "    return " + self.value + ";")
+            print(str + "}")
+        rootIndex = len(self.fullPrefix)
+        itemCount = 0
+        for k, trie in self.keys:
+            baseIndex = rootIndex
+            if (baseIndex > 0) and (len(k) == 3):
+                baseIndex = baseIndex - 1
+                k = trie.fullPrefix[baseIndex] + k
+            test = [("'%s'" % c) for c in k]
+            if len(test) == 1:
+                comparison = "code[%d] == %s" % (baseIndex, test[0])
+            else:
+                base = "code"
+                if baseIndex > 0:
+                    base = "code + %d" % baseIndex
+                comparison = ("COMPARE_CHARACTERS%d(%s, " % (len(test), base)) + ", ".join(test) + ")"
+            if itemCount == 0:
+                print(str + "if (" + comparison + ") {")
+            else:
+                print(str + "else if (" + comparison + ") {")
+
+            trie.printSubTreeAsC(indent + 4)
+            itemCount = itemCount + 1
+            print(str + "}")
+
+    def maxLength(self):
+        max = len(self.fullPrefix)
+        for (_, trie) in self.keys:
+            l = trie.maxLength()
+            if l > max:
+                max = l
+        return max
+
+    def printAsC(self):
+        print("namespace JSC {")
+        print("static ALWAYS_INLINE bool isIdentPart(int c);")
+        # max length + 1 so we don't need to do any bounds checking at all
+        print("static const int maxTokenLength = %d;" % (self.maxLength() + 1))
+        print("template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseKeyword(JSTokenData* data) {")
+        print("    ASSERT(m_codeEnd - m_code >= maxTokenLength);")
+        print("    const UChar* code = m_code;")
+        self.printSubTreeAsC(4)
+        print("    return IDENT;")
+        print("}")
+        print("}")
+
+keywords = parseKeywords(keywordsText)
+trie = Trie("")
+for k, v in keywords:
+    trie.insert(k, v)
+trie.coalesce()
+trie.fillOut()
+print("// This file was generated by KeywordLookupGenerator.py.  Do not edit.")
+print("""
+
+#if CPU(NEEDS_ALIGNED_ACCESS)
+
+#define COMPARE_CHARACTERS2(address, char1, char2) \
+    (((address)[0] == char1) && ((address)[1] == char2))
+#define COMPARE_CHARACTERS4(address, char1, char2, char3, char4) \
+    (COMPARE_CHARACTERS2(address, char1, char2) && COMPARE_CHARACTERS2((address) + 2, char3, char4))
+
+#else
+
+#if CPU(BIG_ENDIAN)
+#define CHARPAIR_TOUINT32(a, b) ((((uint32_t)(a)) << 16) + (uint32_t)(b))
+#define CHARQUAD_TOUINT64(a, b, c, d) ((((uint64_t)(CHARPAIR_TOUINT32(a, b))) << 32) + CHARPAIR_TOUINT32(c, d))
+#else
+#define CHARPAIR_TOUINT32(a, b) ((((uint32_t)(b)) << 16) + (uint32_t)(a))
+#define CHARQUAD_TOUINT64(a, b, c, d) ((((uint64_t)(CHARPAIR_TOUINT32(c, d))) << 32) + CHARPAIR_TOUINT32(a, b))
+#endif
+
+#define COMPARE_CHARACTERS2(address, char1, char2) \
+    (((uint32_t*)(address))[0] == CHARPAIR_TOUINT32(char1, char2))
+#if CPU(X86_64)
+
+#define COMPARE_CHARACTERS4(address, char1, char2, char3, char4) \
+    (((uint64_t*)(address))[0] == CHARQUAD_TOUINT64(char1, char2, char3, char4))
+#else
+#define COMPARE_CHARACTERS4(address, char1, char2, char3, char4) \
+    (COMPARE_CHARACTERS2(address, char1, char2) && COMPARE_CHARACTERS2((address) + 2, char3, char4))
+#endif
+
+#endif
+
+#define COMPARE_CHARACTERS3(address, char1, char2, char3) \
+    (COMPARE_CHARACTERS2(address, char1, char2) && ((address)[2] == (char3)))
+#define COMPARE_CHARACTERS5(address, char1, char2, char3, char4, char5) \
+    (COMPARE_CHARACTERS4(address, char1, char2, char3, char4) && ((address)[4] == (char5)))
+#define COMPARE_CHARACTERS6(address, char1, char2, char3, char4, char5, char6) \
+    (COMPARE_CHARACTERS4(address, char1, char2, char3, char4) && COMPARE_CHARACTERS2(address + 4, char5, char6))
+#define COMPARE_CHARACTERS7(address, char1, char2, char3, char4, char5, char6, char7) \
+    (COMPARE_CHARACTERS4(address, char1, char2, char3, char4) && COMPARE_CHARACTERS4(address + 3, char4, char5, char6, char7))
+#define COMPARE_CHARACTERS8(address, char1, char2, char3, char4, char5, char6, char7, char8) \
+    (COMPARE_CHARACTERS4(address, char1, char2, char3, char4) && COMPARE_CHARACTERS4(address + 4, char5, char6, char7, char8))
+""")
+
+trie.printAsC()
index b9e2a72f287ed7f7e61d2cb155709141dc096b46..cb4c11a57c6739a1426a5bb9d812b73001e69d91 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1 @@
-OTHER_OPTIONS = -target All
 include ../Makefile.shared
index a181b7e982f4a4eaa7c68e78a0b94197a7b06f3c..f86444d08b62d819a7de767d1d2479642aaef9bb 100644 (file)
@@ -272,8 +272,8 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas
             add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
             dtr_u(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag);
         } else {
-            ARMWord reg = getImm(offset, ARMRegisters::S0);
-            dtr_ur(isLoad, srcDst, base, reg | transferFlag);
+            moveImm(offset, ARMRegisters::S0);
+            dtr_ur(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
         }
     } else {
         offset = -offset;
@@ -283,8 +283,8 @@ void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID bas
             sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
             dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag);
         } else {
-            ARMWord reg = getImm(offset, ARMRegisters::S0);
-            dtr_dr(isLoad, srcDst, base, reg | transferFlag);
+            moveImm(offset, ARMRegisters::S0);
+            dtr_dr(isLoad, srcDst, base, ARMRegisters::S0 | transferFlag);
         }
     }
 }
@@ -343,23 +343,23 @@ void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID b
     fdtr_u(isLoad, srcDst, ARMRegisters::S0, 0);
 }
 
-void* ARMAssembler::executableCopy(ExecutablePool* allocator)
+void* ARMAssembler::executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
 {
     // 64-bit alignment is required for next constant pool and JIT code as well
     m_buffer.flushWithoutBarrier(true);
-    if (m_buffer.uncheckedSize() & 0x7)
+    if (!m_buffer.isAligned(8))
         bkpt(0);
 
-    char* data = reinterpret_cast<char*>(m_buffer.executableCopy(allocator));
+    char* data = reinterpret_cast<char*>(m_buffer.executableCopy(globalData, allocator));
 
     for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
         // The last bit is set if the constant must be placed on constant pool.
-        int pos = (*iter) & (~0x1);
-        ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
+        int pos = (iter->m_offset) & (~0x1);
+        ARMWord* ldrAddr = reinterpret_cast_ptr<ARMWord*>(data + pos);
         ARMWord* addr = getLdrImmAddress(ldrAddr);
         if (*addr != InvalidBranchTarget) {
-            if (!(*iter & 1)) {
-                int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching);
+            if (!(iter->m_offset & 1)) {
+                int diff = reinterpret_cast_ptr<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching);
 
                 if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) {
                     *ldrAddr = B | getConditionalField(*ldrAddr) | (diff & BRANCH_MASK);
index 2ca0949803079ba7bb4864bab1d29c6aa4722ad5..1a216fecefc3b5b339de97c98668358c61617632 100644 (file)
@@ -40,32 +40,54 @@ namespace JSC {
             r0 = 0,
             r1,
             r2,
-            r3,
-            S0 = r3,
+            r3, S0 = r3,
             r4,
             r5,
             r6,
             r7,
-            r8,
-            S1 = r8,
+            r8, S1 = r8,
             r9,
             r10,
             r11,
             r12,
-            r13,
-            sp = r13,
-            r14,
-            lr = r14,
-            r15,
-            pc = r15
+            r13, sp = r13,
+            r14, lr = r14,
+            r15, pc = r15
         } RegisterID;
 
         typedef enum {
             d0,
             d1,
             d2,
-            d3,
-            SD0 = d3
+            d3, SD0 = d3,
+            d4,
+            d5,
+            d6,
+            d7,
+            d8,
+            d9,
+            d10,
+            d11,
+            d12,
+            d13,
+            d14,
+            d15,
+            d16,
+            d17,
+            d18,
+            d19,
+            d20,
+            d21,
+            d22,
+            d23,
+            d24,
+            d25,
+            d26,
+            d27,
+            d28,
+            d29,
+            d30,
+            d31
         } FPRegisterID;
 
     } // namespace ARMRegisters
@@ -75,7 +97,7 @@ namespace JSC {
         typedef ARMRegisters::RegisterID RegisterID;
         typedef ARMRegisters::FPRegisterID FPRegisterID;
         typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
-        typedef SegmentedVector<int, 64> Jumps;
+        typedef SegmentedVector<AssemblerLabel, 64> Jumps;
 
         ARMAssembler() { }
 
@@ -118,12 +140,12 @@ namespace JSC {
             MVN = (0xf << 21),
             MUL = 0x00000090,
             MULL = 0x00c00090,
-            FADDD = 0x0e300b00,
-            FDIVD = 0x0e800b00,
-            FSUBD = 0x0e300b40,
-            FMULD = 0x0e200b00,
-            FCMPD = 0x0eb40b40,
-            FSQRTD = 0x0eb10bc0,
+            VADD_F64 = 0x0e300b00,
+            VDIV_F64 = 0x0e800b00,
+            VSUB_F64 = 0x0e300b40,
+            VMUL_F64 = 0x0e200b00,
+            VCMP_F64 = 0x0eb40b40,
+            VSQRT_F64 = 0x0eb10bc0,
             DTR = 0x05000000,
             LDRH = 0x00100090,
             STRH = 0x00000090,
@@ -135,15 +157,17 @@ namespace JSC {
 #if WTF_ARM_ARCH_AT_LEAST(5) || defined(__ARM_ARCH_4T__)
             BX = 0x012fff10,
 #endif
-            FMSR = 0x0e000a10,
-            FMRS = 0x0e100a10,
-            FSITOD = 0x0eb80bc0,
-            FTOSID = 0x0ebd0b40,
-            FMSTAT = 0x0ef1fa10,
+            VMOV_VFP = 0x0e000a10,
+            VMOV_ARM = 0x0e100a10,
+            VCVT_F64_S32 = 0x0eb80bc0,
+            VCVT_S32_F64 = 0x0ebd0b40,
+            VCVTR_S32_F64 = 0x0ebd0bc0,
+            VMRS_APSR = 0x0ef1fa10,
 #if WTF_ARM_ARCH_AT_LEAST(5)
             CLZ = 0x016f0f10,
-            BKPT = 0xe120070,
+            BKPT = 0xe1200070,
             BLX = 0x012fff30,
+            NOP_T2 = 0xf3af8000,
 #endif
 #if WTF_ARM_ARCH_AT_LEAST(7)
             MOVW = 0x03000000,
@@ -183,61 +207,37 @@ namespace JSC {
         enum {
             padForAlign8  = 0x00,
             padForAlign16 = 0x0000,
-            padForAlign32 = 0xee120070,
+            padForAlign32 = 0xe12fff7f // 'bkpt 0xffff' instruction.
         };
 
         static const ARMWord INVALID_IMM = 0xf0000000;
         static const ARMWord InvalidBranchTarget = 0xffffffff;
         static const int DefaultPrefetching = 2;
 
-        class JmpSrc {
-            friend class ARMAssembler;
-        public:
-            JmpSrc()
-                : m_offset(-1)
-            {
-            }
-
-        private:
-            JmpSrc(int offset)
-                : m_offset(offset)
-            {
-            }
-
-            int m_offset;
-        };
-
-        class JmpDst {
-            friend class ARMAssembler;
-        public:
-            JmpDst()
-                : m_offset(-1)
-                , m_used(false)
-            {
-            }
-
-            bool isUsed() const { return m_used; }
-            void used() { m_used = true; }
-        private:
-            JmpDst(int offset)
-                : m_offset(offset)
-                , m_used(false)
-            {
-                ASSERT(m_offset == offset);
-            }
-
-            int m_offset : 31;
-            int m_used : 1;
-        };
-
         // Instruction formating
 
         void emitInst(ARMWord op, int rd, int rn, ARMWord op2)
         {
-            ASSERT ( ((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)) );
+            ASSERT(((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)));
             m_buffer.putInt(op | RN(rn) | RD(rd) | op2);
         }
 
+        void emitDoublePrecisionInst(ARMWord op, int dd, int dn, int dm)
+        {
+            ASSERT((dd >= 0 && dd <= 31) && (dn >= 0 && dn <= 31) && (dm >= 0 && dm <= 31));
+            m_buffer.putInt(op | ((dd & 0xf) << 12) | ((dd & 0x10) << (22 - 4))
+                               | ((dn & 0xf) << 16) | ((dn & 0x10) << (7 - 4))
+                               | (dm & 0xf) | ((dm & 0x10) << (5 - 4)));
+        }
+
+        void emitSinglePrecisionInst(ARMWord op, int sd, int sn, int sm)
+        {
+            ASSERT((sd >= 0 && sd <= 31) && (sn >= 0 && sn <= 31) && (sm >= 0 && sm <= 31));
+            m_buffer.putInt(op | ((sd >> 1) << 12) | ((sd & 0x1) << 22)
+                               | ((sn >> 1) << 16) | ((sn & 0x1) << 7)
+                               | (sm >> 1) | ((sm & 0x1) << 5));
+        }
+
         void and_r(int rd, int rn, ARMWord op2, Condition cc = AL)
         {
             emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2);
@@ -333,6 +333,11 @@ namespace JSC {
             emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
         }
 
+        void cmn_r(int rn, ARMWord op2, Condition cc = AL)
+        {
+            emitInst(static_cast<ARMWord>(cc) | CMN | SET_CC, 0, rn, op2);
+        }
+
         void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
         {
             emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
@@ -402,34 +407,34 @@ namespace JSC {
             m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm));
         }
 
-        void faddd_r(int dd, int dn, int dm, Condition cc = AL)
+        void vadd_f64_r(int dd, int dn, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm);
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VADD_F64, dd, dn, dm);
         }
 
-        void fdivd_r(int dd, int dn, int dm, Condition cc = AL)
+        void vdiv_f64_r(int dd, int dn, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FDIVD, dd, dn, dm);
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VDIV_F64, dd, dn, dm);
         }
 
-        void fsubd_r(int dd, int dn, int dm, Condition cc = AL)
+        void vsub_f64_r(int dd, int dn, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm);
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSUB_F64, dd, dn, dm);
         }
 
-        void fmuld_r(int dd, int dn, int dm, Condition cc = AL)
+        void vmul_f64_r(int dd, int dn, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm);
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VMUL_F64, dd, dn, dm);
         }
 
-        void fcmpd_r(int dd, int dm, Condition cc = AL)
+        void vcmp_f64_r(int dd, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm);
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCMP_F64, dd, 0, dm);
         }
 
-        void fsqrtd_r(int dd, int dm, Condition cc = AL)
+        void vsqrt_f64_r(int dd, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FSQRTD, dd, 0, dm);
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VSQRT_F64, dd, 0, dm);
         }
 
         void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
@@ -516,29 +521,39 @@ namespace JSC {
             dtr_u(true, reg, ARMRegisters::sp, 0, cc);
         }
 
-        void fmsr_r(int dd, int rn, Condition cc = AL)
+        void vmov_vfp_r(int sn, int rt, Condition cc = AL)
+        {
+            ASSERT(rt <= 15);
+            emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_VFP, rt << 1, sn, 0);
+        }
+
+        void vmov_arm_r(int rt, int sn, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0);
+            ASSERT(rt <= 15);
+            emitSinglePrecisionInst(static_cast<ARMWord>(cc) | VMOV_ARM, rt << 1, sn, 0);
         }
 
-        void fmrs_r(int rd, int dn, Condition cc = AL)
+        void vcvt_f64_s32_r(int dd, int sm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FMRS, rd, dn, 0);
+            ASSERT(!(sm & 0x1)); // sm must be divisible by 2
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_F64_S32, dd, 0, (sm >> 1));
         }
 
-        void fsitod_r(int dd, int dm, Condition cc = AL)
+        void vcvt_s32_f64_r(int sd, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm);
+            ASSERT(!(sd & 0x1)); // sd must be divisible by 2
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVT_S32_F64, (sd >> 1), 0, dm);
         }
 
-        void ftosid_r(int fd, int dm, Condition cc = AL)
+        void vcvtr_s32_f64_r(int sd, int dm, Condition cc = AL)
         {
-            emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm);
+            ASSERT(!(sd & 0x1)); // sd must be divisible by 2
+            emitDoublePrecisionInst(static_cast<ARMWord>(cc) | VCVTR_S32_F64, (sd >> 1), 0, dm);
         }
 
-        void fmstat(Condition cc = AL)
+        void vmrs_apsr(Condition cc = AL)
         {
-            m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
+            m_buffer.putInt(static_cast<ARMWord>(cc) | VMRS_APSR);
         }
 
 #if WTF_ARM_ARCH_AT_LEAST(5)
@@ -557,6 +572,11 @@ namespace JSC {
             dtr_dr(true, ARMRegisters::S0, ARMRegisters::S0, ARMRegisters::S0);
 #endif
         }
+        
+        void nop()
+        {
+            m_buffer.putInt(OP_NOP_T2);
+        }
 
         void bx(int rm, Condition cc = AL)
         {
@@ -567,19 +587,17 @@ namespace JSC {
 #endif
         }
 
-        JmpSrc blx(int rm, Condition cc = AL)
+        AssemblerLabel blx(int rm, Condition cc = AL)
         {
 #if WTF_ARM_ARCH_AT_LEAST(5)
-            int s = m_buffer.uncheckedSize();
             emitInst(static_cast<ARMWord>(cc) | BLX, 0, 0, RM(rm));
 #else
             ASSERT(rm != 14);
             ensureSpace(2 * sizeof(ARMWord), 0);
             mov_r(ARMRegisters::lr, ARMRegisters::pc, cc);
-            int s = m_buffer.uncheckedSize();
             bx(rm, cc);
 #endif
-            return JmpSrc(s);
+            return m_buffer.label();
         }
 
         static ARMWord lsl(int reg, ARMWord value)
@@ -626,9 +644,9 @@ namespace JSC {
 
         // General helpers
 
-        int size()
+        size_t codeSize() const
         {
-            return m_buffer.size();
+            return m_buffer.codeSize();
         }
 
         void ensureSpace(int insnSpace, int constSpace)
@@ -641,12 +659,13 @@ namespace JSC {
             return m_buffer.sizeOfConstantPool();
         }
 
-        JmpDst label()
+        AssemblerLabel label()
         {
-            return JmpDst(m_buffer.size());
+            m_buffer.ensureSpaceForAnyOneInstruction();
+            return m_buffer.label();
         }
 
-        JmpDst align(int alignment)
+        AssemblerLabel align(int alignment)
         {
             while (!m_buffer.isAligned(alignment))
                 mov_r(ARMRegisters::r0, ARMRegisters::r0);
@@ -654,21 +673,24 @@ namespace JSC {
             return label();
         }
 
-        JmpSrc loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0)
+        AssemblerLabel loadBranchTarget(int rd, Condition cc = AL, int useConstantPool = 0)
         {
             ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
-            int s = m_buffer.uncheckedSize();
+            m_jumps.append(m_buffer.codeSize() | (useConstantPool & 0x1));
             ldr_un_imm(rd, InvalidBranchTarget, cc);
-            m_jumps.append(s | (useConstantPool & 0x1));
-            return JmpSrc(s);
+            return m_buffer.label();
         }
 
-        JmpSrc jmp(Condition cc = AL, int useConstantPool = 0)
+        AssemblerLabel jmp(Condition cc = AL, int useConstantPool = 0)
         {
             return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool);
         }
 
-        void* executableCopy(ExecutablePool* allocator);
+        void* executableCopy(JSGlobalData&, ExecutablePool* allocator);
+
+#ifndef NDEBUG
+        unsigned debugOffset() { return m_buffer.debugOffset(); }
+#endif
 
         // Patching helpers
 
@@ -717,9 +739,17 @@ namespace JSC {
 
         static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
 
+        // Read pointers
+        static void* readPointer(void* from)
+        {
+            ARMWord* insn = reinterpret_cast<ARMWord*>(from);
+            void* addr = reinterpret_cast<void*>(getLdrImmAddress(insn));
+            return *addr;
+        }
+        
         // Patch pointers
 
-        static void linkPointer(void* code, JmpDst from, void* to)
+        static void linkPointer(void* code, AssemblerLabel from, void* to)
         {
             patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
         }
@@ -728,79 +758,67 @@ namespace JSC {
         {
             patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to));
         }
+        
+        static void repatchCompact(void* where, int32_t value)
+        {
+            repatchInt32(where, value);
+        }
 
         static void repatchPointer(void* from, void* to)
         {
             patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
         }
 
-        static void repatchLoadPtrToLEA(void* from)
+        // Linkers
+        static intptr_t getAbsoluteJumpAddress(void* base, int offset = 0)
         {
-            // On arm, this is a patch from LDR to ADD. It is restricted conversion,
-            // from special case to special case, altough enough for its purpose
-            ARMWord* insn = reinterpret_cast<ARMWord*>(from);
-            ASSERT((*insn & 0x0ff00f00) == 0x05900000);
-
-            *insn = (*insn & 0xf00ff0ff) | 0x02800000;
-            ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord));
+            return reinterpret_cast<intptr_t>(base) + offset - sizeof(ARMWord);
         }
 
-        // Linkers
-
-        void linkJump(JmpSrc from, JmpDst to)
+        void linkJump(AssemblerLabel from, AssemblerLabel to)
         {
-            ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
+            ARMWord* insn = reinterpret_cast<ARMWord*>(getAbsoluteJumpAddress(m_buffer.data(), from.m_offset));
             ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress());
             *addr = static_cast<ARMWord>(to.m_offset);
         }
 
-        static void linkJump(void* code, JmpSrc from, void* to)
+        static void linkJump(void* code, AssemblerLabel from, void* to)
         {
-            patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
+            patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to);
         }
 
         static void relinkJump(void* from, void* to)
         {
-            patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
+            patchPointerInternal(getAbsoluteJumpAddress(from), to);
         }
 
-        static void linkCall(void* code, JmpSrc from, void* to)
+        static void linkCall(void* code, AssemblerLabel from, void* to)
         {
-            patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
+            patchPointerInternal(getAbsoluteJumpAddress(code, from.m_offset), to);
         }
 
         static void relinkCall(void* from, void* to)
         {
-            patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
+            patchPointerInternal(getAbsoluteJumpAddress(from), to);
         }
 
         // Address operations
 
-        static void* getRelocatedAddress(void* code, JmpSrc jump)
-        {
-            return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord) + 1);
-        }
-
-        static void* getRelocatedAddress(void* code, JmpDst label)
+        static void* getRelocatedAddress(void* code, AssemblerLabel label)
         {
-            return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + label.m_offset / sizeof(ARMWord));
+            return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
         }
 
         // Address differences
 
-        static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
+        static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
         {
-            return (to.m_offset + sizeof(ARMWord)) - from.m_offset;
+            return b.m_offset - a.m_offset;
         }
 
-        static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
+        static unsigned getCallReturnOffset(AssemblerLabel call)
         {
-            return to.m_offset - from.m_offset;
-        }
-
-        static unsigned getCallReturnOffset(JmpSrc call)
-        {
-            return call.m_offset + sizeof(ARMWord);
+            return call.m_offset;
         }
 
         // Handle immediates
@@ -825,6 +843,15 @@ namespace JSC {
         void moveImm(ARMWord imm, int dest);
         ARMWord encodeComplexImm(ARMWord imm, int dest);
 
+        ARMWord getOffsetForHalfwordDataTransfer(ARMWord imm, int tmpReg)
+        {
+            // Encode immediate data in the instruction if it is possible
+            if (imm <= 0xff)
+                return getOp2Byte(imm);
+            // Otherwise, store the data in a temporary register
+            return encodeComplexImm(imm, tmpReg);
+        }
+
         // Memory load/store helpers
 
         void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false);
index 7aa1f103fce3dd1d63ad4ebb41f638245227d16d..faca66421bc6bffc576e955597223943ada6bff5 100644 (file)
 
 namespace JSC {
 
-const int ARMv7Assembler::JumpSizes[] = { 0xffffffff, sizeof(uint16_t), sizeof(uint16_t),
-    2 * sizeof(uint16_t), 2 * sizeof(uint16_t), 3 * sizeof(uint16_t), 5 * sizeof(uint16_t), 6 * sizeof(uint16_t) };
-const int ARMv7Assembler::JumpPaddingSizes[] = { 0, 5 * sizeof(uint16_t), 6 * sizeof(uint16_t),
-    5 * sizeof(uint16_t), 6 * sizeof(uint16_t) };
-
 }
 
 #endif
index 13ad3e0d3259d83e4147a139082734bc62b376f4..f5101c76b7e44c2f6f894a4958824a76a0e0fb3c 100644 (file)
@@ -340,6 +340,8 @@ public:
         return m_type != TypeInvalid;
     }
 
+    uint16_t asUInt16() const { return m_value.asInt; }
+
     // These methods rely on the format of encoded byte values.
     bool isUInt3() { return !(m_value.asInt & 0xfff8); }
     bool isUInt4() { return !(m_value.asInt & 0xfff0); }
@@ -357,8 +359,8 @@ public:
     uint8_t getUInt6() { ASSERT(isUInt6()); return m_value.asInt; }
     uint8_t getUInt7() { ASSERT(isUInt7()); return m_value.asInt; }
     uint8_t getUInt8() { ASSERT(isUInt8()); return m_value.asInt; }
-    uint8_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
-    uint8_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
+    uint16_t getUInt9() { ASSERT(isUInt9()); return m_value.asInt; }
+    uint16_t getUInt10() { ASSERT(isUInt10()); return m_value.asInt; }
     uint16_t getUInt12() { ASSERT(isUInt12()); return m_value.asInt; }
     uint16_t getUInt16() { ASSERT(isUInt16()); return m_value.asInt; }
 
@@ -369,40 +371,6 @@ private:
     ThumbImmediateValue m_value;
 };
 
-class VFPImmediate {
-public:
-    VFPImmediate(double d)
-        : m_value(-1)
-    {
-        union {
-            uint64_t i;
-            double d;
-        } u;
-
-        u.d = d;
-
-        int sign = static_cast<int>(u.i >> 63);
-        int exponent = static_cast<int>(u.i >> 52) & 0x7ff;
-        uint64_t mantissa = u.i & 0x000fffffffffffffull;
-
-        if ((exponent >= 0x3fc) && (exponent <= 0x403) && !(mantissa & 0x0000ffffffffffffull))
-            m_value = (sign << 7) | ((exponent & 7) << 4) | (int)(mantissa >> 48);
-    }
-
-    bool isValid()
-    {
-        return m_value != -1;
-    }
-    
-    uint8_t value()
-    {
-        return (uint8_t)m_value;
-    }
-
-private:
-    int m_value;
-};
-
 typedef enum {
     SRType_LSL,
     SRType_LSR,
@@ -412,7 +380,6 @@ typedef enum {
     SRType_RRX = SRType_ROR
 } ARMShiftType;
 
-class ARMv7Assembler;
 class ShiftTypeAndAmount {
     friend class ARMv7Assembler;
 
@@ -462,8 +429,8 @@ public:
     typedef enum {
         ConditionEQ,
         ConditionNE,
-        ConditionHS,
-        ConditionLO,
+        ConditionHS, ConditionCS = ConditionHS,
+        ConditionLO, ConditionCC = ConditionLO,
         ConditionMI,
         ConditionPL,
         ConditionVS,
@@ -475,16 +442,28 @@ public:
         ConditionGT,
         ConditionLE,
         ConditionAL,
-        
-        ConditionCS = ConditionHS,
-        ConditionCC = ConditionLO,
+        ConditionInvalid
     } Condition;
 
-    enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount };
-    enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3,
-        LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount };
-    static const int JumpSizes[JumpLinkTypeCount];
-    static const int JumpPaddingSizes[JumpTypeCount];
+#define JUMP_ENUM_WITH_SIZE(index, value) (((value) << 3) | (index))
+#define JUMP_ENUM_SIZE(jump) ((jump) >> 3) 
+    enum JumpType { JumpFixed = JUMP_ENUM_WITH_SIZE(0, 0), 
+                    JumpNoCondition = JUMP_ENUM_WITH_SIZE(1, 5 * sizeof(uint16_t)),
+                    JumpCondition = JUMP_ENUM_WITH_SIZE(2, 6 * sizeof(uint16_t)),
+                    JumpNoConditionFixedSize = JUMP_ENUM_WITH_SIZE(3, 5 * sizeof(uint16_t)),
+                    JumpConditionFixedSize = JUMP_ENUM_WITH_SIZE(4, 6 * sizeof(uint16_t))
+    };
+    enum JumpLinkType { 
+        LinkInvalid = JUMP_ENUM_WITH_SIZE(0, 0),
+        LinkJumpT1 = JUMP_ENUM_WITH_SIZE(1, sizeof(uint16_t)),
+        LinkJumpT2 = JUMP_ENUM_WITH_SIZE(2, sizeof(uint16_t)),
+        LinkJumpT3 = JUMP_ENUM_WITH_SIZE(3, 2 * sizeof(uint16_t)),
+        LinkJumpT4 = JUMP_ENUM_WITH_SIZE(4, 2 * sizeof(uint16_t)),
+        LinkConditionalJumpT4 = JUMP_ENUM_WITH_SIZE(5, 3 * sizeof(uint16_t)),
+        LinkBX = JUMP_ENUM_WITH_SIZE(6, 5 * sizeof(uint16_t)),
+        LinkConditionalBX = JUMP_ENUM_WITH_SIZE(7, 6 * sizeof(uint16_t))
+    };
+
     class LinkRecord {
     public:
         LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
@@ -505,67 +484,9 @@ public:
     private:
         intptr_t m_from : 31;
         intptr_t m_to : 31;
-        JumpType m_type : 3;
-        JumpLinkType m_linkType : 4;
-        Condition m_condition : 16;
-    };
-    
-    class JmpSrc {
-        friend class ARMv7Assembler;
-        friend class ARMInstructionFormatter;
-        friend class LinkBuffer;
-    public:
-        JmpSrc()
-            : m_offset(-1)
-        {
-        }
-
-    private:
-        JmpSrc(int offset, JumpType type)
-            : m_offset(offset)
-            , m_condition(0xffff)
-            , m_type(type)
-        {
-            ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize);
-        }
-
-        JmpSrc(int offset, JumpType type, Condition condition)
-            : m_offset(offset)
-            , m_condition(condition)
-            , m_type(type)
-        {
-            ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize);
-        }
-
-        int m_offset;
+        JumpType m_type : 8;
+        JumpLinkType m_linkType : 8;
         Condition m_condition : 16;
-        JumpType m_type : 16;
-        
-    };
-    
-    class JmpDst {
-        friend class ARMv7Assembler;
-        friend class ARMInstructionFormatter;
-        friend class LinkBuffer;
-    public:
-        JmpDst()
-            : m_offset(-1)
-            , m_used(false)
-        {
-        }
-
-        bool isUsed() const { return m_used; }
-        void used() { m_used = true; }
-    private:
-        JmpDst(int offset)
-            : m_offset(offset)
-            , m_used(false)
-        {
-            ASSERT(m_offset == offset);
-        }
-
-        int m_offset : 31;
-        int m_used : 1;
     };
 
 private:
@@ -696,6 +617,7 @@ private:
         OP_LSR_reg_T2   = 0xFA20,
         OP_ASR_reg_T2   = 0xFA40,
         OP_ROR_reg_T2   = 0xFA60,
+        OP_CLZ          = 0xFAB0,
         OP_SMULL_T1     = 0xFB80,
     } OpcodeID1;
 
@@ -787,10 +709,10 @@ public:
 
         if (rn == ARMRegisters::sp) {
             if (!(rd & 8) && imm.isUInt10()) {
-                m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, imm.getUInt10() >> 2);
+                m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2));
                 return;
             } else if ((rd == ARMRegisters::sp) && imm.isUInt9()) {
-                m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, imm.getUInt9() >> 2);
+                m_formatter.oneWordOp9Imm7(OP_ADD_SP_imm_T2, static_cast<uint8_t>(imm.getUInt9() >> 2));
                 return;
             }
         } else if (!((rd | rn) & 8)) {
@@ -811,7 +733,7 @@ public:
         }
     }
 
-    void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
         ASSERT(rd != ARMRegisters::pc);
@@ -821,7 +743,7 @@ public:
     }
 
     // NOTE: In an IT block, add doesn't modify the flags register.
-    void add(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void add(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         if (rd == rn)
             m_formatter.oneWordOp8RegReg143(OP_ADD_reg_T2, rm, rd);
@@ -834,7 +756,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block.
-    void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
@@ -856,7 +778,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block?
-    void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
         ASSERT(rd != ARMRegisters::pc);
@@ -866,7 +788,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block.
-    void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void add_S(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         if (!((rd | rn | rm) & 8))
             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_ADD_reg_T1, rm, rn, rd);
@@ -874,7 +796,7 @@ public:
             add_S(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -882,7 +804,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
     }
 
-    void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -890,7 +812,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_AND_reg_T2, rn, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
 
-    void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void ARM_and(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         if ((rd == rn) && !((rd | rm) & 8))
             m_formatter.oneWordOp10Reg3Reg3(OP_AND_reg_T1, rm, rd);
@@ -900,7 +822,7 @@ public:
             ARM_and(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+    ALWAYS_INLINE void asr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rm));
@@ -908,7 +830,7 @@ public:
         m_formatter.twoWordOp16FourFours(OP_ASR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
 
-    void asr(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void asr(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -917,39 +839,40 @@ public:
     }
     
     // Only allowed in IT (if then) block if last instruction.
-    JmpSrc b(JumpType type)
+    ALWAYS_INLINE AssemblerLabel b()
     {
         m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
-        return JmpSrc(m_formatter.size(), type);
+        return m_formatter.label();
     }
     
     // Only allowed in IT (if then) block if last instruction.
-    JmpSrc blx(RegisterID rm, JumpType type)
+    ALWAYS_INLINE AssemblerLabel blx(RegisterID rm)
     {
         ASSERT(rm != ARMRegisters::pc);
         m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
-        return JmpSrc(m_formatter.size(), type);
+        return m_formatter.label();
     }
 
     // Only allowed in IT (if then) block if last instruction.
-    JmpSrc bx(RegisterID rm, JumpType type, Condition condition)
+    ALWAYS_INLINE AssemblerLabel bx(RegisterID rm)
     {
         m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
-        return JmpSrc(m_formatter.size(), type, condition);
+        return m_formatter.label();
     }
 
-    JmpSrc bx(RegisterID rm, JumpType type)
+    void bkpt(uint8_t imm=0)
     {
-        m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
-        return JmpSrc(m_formatter.size(), type);
+        m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
     }
 
-    void bkpt(uint8_t imm=0)
+    ALWAYS_INLINE void clz(RegisterID rd, RegisterID rm)
     {
-        m_formatter.oneWordOp8Imm8(OP_BKPT, imm);
+        ASSERT(!BadReg(rd));
+        ASSERT(!BadReg(rm));
+        m_formatter.twoWordOp12Reg4FourFours(OP_CLZ, rm, FourFours(0xf, rd, 8, rm));
     }
 
-    void cmn(RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void cmn(RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
@@ -957,7 +880,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
     }
 
-    void cmp(RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void cmp(RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
@@ -968,14 +891,14 @@ public:
             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
     }
 
-    void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_CMP_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
     }
 
-    void cmp(RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void cmp(RegisterID rn, RegisterID rm)
     {
         if ((rn | rm) & 8)
             cmp(rn, rm, ShiftTypeAndAmount());
@@ -984,7 +907,7 @@ public:
     }
 
     // xor is not spelled with an 'e'. :-(
-    void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -993,7 +916,7 @@ public:
     }
 
     // xor is not spelled with an 'e'. :-(
-    void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void eor(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1012,28 +935,28 @@ public:
             eor(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void it(Condition cond)
+    ALWAYS_INLINE void it(Condition cond)
     {
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond));
     }
 
-    void it(Condition cond, bool inst2if)
+    ALWAYS_INLINE void it(Condition cond, bool inst2if)
     {
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if));
     }
 
-    void it(Condition cond, bool inst2if, bool inst3if)
+    ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if)
     {
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if));
     }
 
-    void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
+    ALWAYS_INLINE void it(Condition cond, bool inst2if, bool inst3if, bool inst4if)
     {
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(cond, inst2if, inst3if, inst4if));
     }
 
     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
-    void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(imm.isUInt12());
@@ -1041,11 +964,19 @@ public:
         if (!((rt | rn) & 8) && imm.isUInt7())
             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
-            m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, imm.getUInt10() >> 2);
+            m_formatter.oneWordOp5Reg3Imm8(OP_LDR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
         else
             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDR_imm_T3, rn, rt, imm.getUInt12());
     }
 
+    ALWAYS_INLINE void ldrCompact(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+    {
+        ASSERT(rn != ARMRegisters::pc); // LDR (literal)
+        ASSERT(imm.isUInt7());
+        ASSERT(!((rt | rn) & 8));
+        m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDR_imm_T1, imm.getUInt7() >> 2, rn, rt);
+    }
+
     // If index is set, this is a regular offset or a pre-indexed load;
     // if index is not set then is is a post-index load.
     //
@@ -1057,7 +988,7 @@ public:
     // _tmp = _reg + offset
     // MEM[index ? _tmp : _reg] = REG[rt]
     // if (wback) REG[rn] = _tmp
-    void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+    ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
         ASSERT(rt != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1080,7 +1011,7 @@ public:
     }
 
     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
-    void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
+    ALWAYS_INLINE void ldr(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
     {
         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(!BadReg(rm));
@@ -1093,7 +1024,7 @@ public:
     }
 
     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
-    void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(imm.isUInt12());
@@ -1115,7 +1046,7 @@ public:
     // _tmp = _reg + offset
     // MEM[index ? _tmp : _reg] = REG[rt]
     // if (wback) REG[rn] = _tmp
-    void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+    ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
         ASSERT(rt != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1137,7 +1068,7 @@ public:
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
     }
 
-    void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
+    ALWAYS_INLINE void ldrh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
     {
         ASSERT(!BadReg(rt));   // Memory hint
         ASSERT(rn != ARMRegisters::pc); // LDRH (literal)
@@ -1184,7 +1115,7 @@ public:
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset);
     }
 
-    void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
+    ALWAYS_INLINE void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
     {
         ASSERT(rn != ARMRegisters::pc); // LDR (literal)
         ASSERT(!BadReg(rm));
@@ -1204,7 +1135,7 @@ public:
         m_formatter.twoWordOp16FourFours(OP_LSL_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
 
-    void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void lsl(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1212,7 +1143,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
     }
 
-    void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+    ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rm, int32_t shiftAmount)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rm));
@@ -1220,7 +1151,7 @@ public:
         m_formatter.twoWordOp16FourFours(OP_LSR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
 
-    void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void lsr(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1228,7 +1159,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
     }
 
-    void movT3(RegisterID rd, ARMThumbImmediate imm)
+    ALWAYS_INLINE void movT3(RegisterID rd, ARMThumbImmediate imm)
     {
         ASSERT(imm.isValid());
         ASSERT(!imm.isEncodedImm());
@@ -1237,7 +1168,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
     }
 
-     void mov(RegisterID rd, ARMThumbImmediate imm)
+    ALWAYS_INLINE void mov(RegisterID rd, ARMThumbImmediate imm)
     {
         ASSERT(imm.isValid());
         ASSERT(!BadReg(rd));
@@ -1250,19 +1181,19 @@ public:
             movT3(rd, imm);
     }
 
-   void mov(RegisterID rd, RegisterID rm)
+    ALWAYS_INLINE void mov(RegisterID rd, RegisterID rm)
     {
         m_formatter.oneWordOp8RegReg143(OP_MOV_reg_T1, rm, rd);
     }
 
-    void movt(RegisterID rd, ARMThumbImmediate imm)
+    ALWAYS_INLINE void movt(RegisterID rd, ARMThumbImmediate imm)
     {
         ASSERT(imm.isUInt16());
         ASSERT(!BadReg(rd));
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOVT, imm.m_value.imm4, rd, imm);
     }
 
-    void mvn(RegisterID rd, ARMThumbImmediate imm)
+    ALWAYS_INLINE void mvn(RegisterID rd, ARMThumbImmediate imm)
     {
         ASSERT(imm.isEncodedImm());
         ASSERT(!BadReg(rd));
@@ -1270,14 +1201,14 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
     }
 
-    void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp16FourFours(OP_MVN_reg_T2, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
 
-    void mvn(RegisterID rd, RegisterID rm)
+    ALWAYS_INLINE void mvn(RegisterID rd, RegisterID rm)
     {
         if (!((rd | rm) & 8))
             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
@@ -1285,13 +1216,13 @@ public:
             mvn(rd, rm, ShiftTypeAndAmount());
     }
 
-    void neg(RegisterID rd, RegisterID rm)
+    ALWAYS_INLINE void neg(RegisterID rd, RegisterID rm)
     {
         ARMThumbImmediate zero = ARMThumbImmediate::makeUInt12(0);
         sub(rd, zero, rm);
     }
 
-    void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1299,7 +1230,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
     }
 
-    void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void orr(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1317,7 +1248,7 @@ public:
             orr(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void orr_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1335,7 +1266,7 @@ public:
             orr_S(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
+    ALWAYS_INLINE void ror(RegisterID rd, RegisterID rm, int32_t shiftAmount)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rm));
@@ -1343,7 +1274,7 @@ public:
         m_formatter.twoWordOp16FourFours(OP_ROR_imm_T1, FourFours(shift.hi4(), rd, shift.lo4(), rm));
     }
 
-    void ror(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void ror(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1351,7 +1282,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
     }
 
-    void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm)
     {
         ASSERT(!BadReg(rdLo));
         ASSERT(!BadReg(rdHi));
@@ -1362,7 +1293,7 @@ public:
     }
 
     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
-    void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(rt != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1371,7 +1302,7 @@ public:
         if (!((rt | rn) & 8) && imm.isUInt7())
             m_formatter.oneWordOp5Imm5Reg3Reg3(OP_STR_imm_T1, imm.getUInt7() >> 2, rn, rt);
         else if ((rn == ARMRegisters::sp) && !(rt & 8) && imm.isUInt10())
-            m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, imm.getUInt10() >> 2);
+            m_formatter.oneWordOp5Reg3Imm8(OP_STR_imm_T2, rt, static_cast<uint8_t>(imm.getUInt10() >> 2));
         else
             m_formatter.twoWordOp12Reg4Reg4Imm12(OP_STR_imm_T3, rn, rt, imm.getUInt12());
     }
@@ -1387,7 +1318,7 @@ public:
     // _tmp = _reg + offset
     // MEM[index ? _tmp : _reg] = REG[rt]
     // if (wback) REG[rn] = _tmp
-    void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
+    ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, int offset, bool index, bool wback)
     {
         ASSERT(rt != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1410,7 +1341,7 @@ public:
     }
 
     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
-    void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift=0)
+    ALWAYS_INLINE void str(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0)
     {
         ASSERT(rn != ARMRegisters::pc);
         ASSERT(!BadReg(rm));
@@ -1422,7 +1353,7 @@ public:
             m_formatter.twoWordOp12Reg4FourFours(OP_STR_reg_T2, rn, FourFours(rt, 0, shift, rm));
     }
 
-    void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
     {
         // Rd can only be SP if Rn is also SP.
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
@@ -1431,7 +1362,7 @@ public:
         ASSERT(imm.isValid());
 
         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
-            m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
+            m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
             return;
         } else if (!((rd | rn) & 8)) {
             if (imm.isUInt3()) {
@@ -1451,7 +1382,7 @@ public:
         }
     }
 
-    void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
+    ALWAYS_INLINE void sub(RegisterID rd, ARMThumbImmediate imm, RegisterID rn)
     {
         ASSERT(rd != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1464,7 +1395,7 @@ public:
             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
     }
 
-    void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
         ASSERT(rd != ARMRegisters::pc);
@@ -1474,7 +1405,7 @@ public:
     }
 
     // NOTE: In an IT block, add doesn't modify the flags register.
-    void sub(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void sub(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         if (!((rd | rn | rm) & 8))
             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
@@ -1492,7 +1423,7 @@ public:
         ASSERT(imm.isValid());
 
         if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) {
-            m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, imm.getUInt9() >> 2);
+            m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2));
             return;
         } else if (!((rd | rn) & 8)) {
             if (imm.isUInt3()) {
@@ -1508,7 +1439,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block?
-    void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
         ASSERT(rd != ARMRegisters::pc);
@@ -1518,7 +1449,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block.
-    void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void sub_S(RegisterID rd, RegisterID rn, RegisterID rm)
     {
         if (!((rd | rn | rm) & 8))
             m_formatter.oneWordOp7Reg3Reg3Reg3(OP_SUB_reg_T1, rm, rn, rd);
@@ -1526,7 +1457,7 @@ public:
             sub_S(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void tst(RegisterID rn, ARMThumbImmediate imm)
+    ALWAYS_INLINE void tst(RegisterID rn, ARMThumbImmediate imm)
     {
         ASSERT(!BadReg(rn));
         ASSERT(imm.isEncodedImm());
@@ -1534,14 +1465,14 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
     }
 
-    void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
+    ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm, ShiftTypeAndAmount shift)
     {
         ASSERT(!BadReg(rn));
         ASSERT(!BadReg(rm));
         m_formatter.twoWordOp12Reg4FourFours(OP_TST_reg_T2, rn, FourFours(shift.hi4(), 0xf, shift.lo4(), rm));
     }
 
-    void tst(RegisterID rn, RegisterID rm)
+    ALWAYS_INLINE void tst(RegisterID rn, RegisterID rm)
     {
         if ((rn | rm) & 8)
             tst(rn, rm, ShiftTypeAndAmount());
@@ -1619,46 +1550,33 @@ public:
         m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm);
     }
 
-    JmpDst label()
+    void nop()
     {
-        return JmpDst(m_formatter.size());
+        m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0);
     }
-    
-    JmpDst align(int alignment)
-    {
-        while (!m_formatter.isAligned(alignment))
-            bkpt();
 
-        return label();
-    }
-    
-    static void* getRelocatedAddress(void* code, JmpSrc jump)
+    AssemblerLabel label()
     {
-        ASSERT(jump.m_offset != -1);
-
-        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
+        return m_formatter.label();
     }
     
-    static void* getRelocatedAddress(void* code, JmpDst destination)
+    AssemblerLabel align(int alignment)
     {
-        ASSERT(destination.m_offset != -1);
+        while (!m_formatter.isAligned(alignment))
+            bkpt();
 
-        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
-    }
-    
-    static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
-    {
-        return dst.m_offset - src.m_offset;
+        return label();
     }
     
-    static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
+    static void* getRelocatedAddress(void* code, AssemblerLabel label)
     {
-        return dst.m_offset - src.m_offset;
+        ASSERT(label.isSet());
+        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.m_offset);
     }
     
-    static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
+    static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
     {
-        return dst.m_offset - src.m_offset;
+        return b.m_offset - a.m_offset;
     }
 
     int executableOffsetFor(int location)
@@ -1668,16 +1586,11 @@ public:
         return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
     }
     
-    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; }
+    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
     
     // Assembler admin methods:
 
-    size_t size() const
-    {
-        return m_formatter.size();
-    }
-
-    static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
+    static ALWAYS_INLINE bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
     {
         return a.from() < b.from();
     }
@@ -1702,34 +1615,34 @@ public:
         if (jumpType == JumpConditionFixedSize)
             return LinkConditionalBX;
         
-        const int paddingSize = JumpPaddingSizes[jumpType];
+        const int paddingSize = JUMP_ENUM_SIZE(jumpType);
         bool mayTriggerErrata = false;
         
         if (jumpType == JumpCondition) {
             // 2-byte conditional T1
-            const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1]));
+            const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1)));
             if (canBeJumpT1(jumpT1Location, to))
                 return LinkJumpT1;
             // 4-byte conditional T3
-            const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3]));
+            const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3)));
             if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) {
                 if (!mayTriggerErrata)
                     return LinkJumpT3;
             }
             // 4-byte conditional T4 with IT
             const uint16_t* conditionalJumpT4Location = 
-            reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4]));
+            reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4)));
             if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) {
                 if (!mayTriggerErrata)
                     return LinkConditionalJumpT4;
             }
         } else {
             // 2-byte unconditional T2
-            const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2]));
+            const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2)));
             if (canBeJumpT2(jumpT2Location, to))
                 return LinkJumpT2;
             // 4-byte unconditional T4
-            const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4]));
+            const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4)));
             if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
                 if (!mayTriggerErrata)
                     return LinkJumpT4;
@@ -1764,7 +1677,7 @@ public:
         return m_jumpsToLink;
     }
 
-    void link(LinkRecord& record, uint8_t* from, uint8_t* to)
+    void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
     {
         switch (record.linkType()) {
         case LinkJumpT1:
@@ -1795,10 +1708,11 @@ public:
     }
 
     void* unlinkedCode() { return m_formatter.data(); }
-    
-    static unsigned getCallReturnOffset(JmpSrc call)
+    size_t codeSize() const { return m_formatter.codeSize(); }
+
+    static unsigned getCallReturnOffset(AssemblerLabel call)
     {
-        ASSERT(call.m_offset >= 0);
+        ASSERT(call.isSet());
         return call.m_offset;
     }
 
@@ -1810,33 +1724,31 @@ public:
     // writable region of memory; to modify the code in an execute-only execuable
     // pool the 'repatch' and 'relink' methods should be used.
 
-    void linkJump(JmpSrc from, JmpDst to)
+    void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type, Condition condition)
     {
-        ASSERT(to.m_offset != -1);
-        ASSERT(from.m_offset != -1);
-        m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition));
+        ASSERT(to.isSet());
+        ASSERT(from.isSet());
+        m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, type, condition));
     }
 
-    static void linkJump(void* code, JmpSrc from, void* to)
+    static void linkJump(void* code, AssemblerLabel from, void* to)
     {
-        ASSERT(from.m_offset != -1);
+        ASSERT(from.isSet());
         
         uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
         linkJumpAbsolute(location, to);
     }
 
-    // bah, this mathod should really be static, since it is used by the LinkBuffer.
-    // return a bool saying whether the link was successful?
-    static void linkCall(void* code, JmpSrc from, void* to)
+    static void linkCall(void* code, AssemblerLabel from, void* to)
     {
         ASSERT(!(reinterpret_cast<intptr_t>(code) & 1));
-        ASSERT(from.m_offset != -1);
+        ASSERT(from.isSet());
         ASSERT(reinterpret_cast<intptr_t>(to) & 1);
 
         setPointer(reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset) - 1, to);
     }
 
-    static void linkPointer(void* code, JmpDst where, void* value)
+    static void linkPointer(void* code, AssemblerLabel where, void* value)
     {
         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
     }
@@ -1865,6 +1777,13 @@ public:
         
         setInt32(where, value);
     }
+    
+    static void repatchCompact(void* where, int32_t value)
+    {
+        ASSERT(value >= 0);
+        ASSERT(ARMThumbImmediate::makeUInt12(value).isUInt7());
+        setUInt7ForLoad(where, ARMThumbImmediate::makeUInt12(value));
+    }
 
     static void repatchPointer(void* where, void* value)
     {
@@ -1873,20 +1792,9 @@ public:
         setPointer(where, value);
     }
 
-    static void repatchLoadPtrToLEA(void* where)
+    static void* readPointer(void* where)
     {
-        ASSERT(!(reinterpret_cast<intptr_t>(where) & 1));
-        uint16_t* loadOp = reinterpret_cast<uint16_t*>(where) + 4;
-
-        ASSERT((loadOp[0] & 0xfff0) == OP_LDR_reg_T2);
-        ASSERT((loadOp[1] & 0x0ff0) == 0);
-        int rn = loadOp[0] & 0xf;
-        int rt = loadOp[1] >> 12;
-        int rm = loadOp[1] & 0xf;
-
-        loadOp[0] = OP_ADD_reg_T3 | rn;
-        loadOp[1] = rt << 8 | rm;
-        ExecutableAllocator::cacheFlush(loadOp, sizeof(uint32_t));
+        return reinterpret_cast<void*>(readInt32(where));
     }
 
 private:
@@ -1969,6 +1877,33 @@ private:
 
         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
     }
+    
+    static int32_t readInt32(void* code)
+    {
+        uint16_t* location = reinterpret_cast<uint16_t*>(code);
+        ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2));
+        
+        ARMThumbImmediate lo16;
+        ARMThumbImmediate hi16;
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(lo16, location[-4]);
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(lo16, location[-3]);
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(hi16, location[-2]);
+        decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(hi16, location[-1]);
+        uint32_t result = hi16.asUInt16();
+        result <<= 16;
+        result |= lo16.asUInt16();
+        return static_cast<int32_t>(result);
+    }
+
+    static void setUInt7ForLoad(void* code, ARMThumbImmediate imm)
+    {
+        // Requires us to have planted a LDR_imm_T1
+        ASSERT(imm.isValid());
+        ASSERT(imm.isUInt7());
+        uint16_t* location = reinterpret_cast<uint16_t*>(code);
+        location[0] |= (imm.getUInt7() >> 2) << 6;
+        ExecutableAllocator::cacheFlush(location, sizeof(uint16_t));
+    }
 
     static void setPointer(void* code, void* value)
     {
@@ -2225,66 +2160,79 @@ private:
         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
     }
 
+    static void decodeTwoWordOp5i6Imm4Reg4EncodedImmFirst(ARMThumbImmediate& result, uint16_t value)
+    {
+        result.m_value.i = (value >> 10) & 1;
+        result.m_value.imm4 = value & 15;
+    }
+
     static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
     {
         return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8;
     }
 
+    static void decodeTwoWordOp5i6Imm4Reg4EncodedImmSecond(ARMThumbImmediate& result, uint16_t value)
+    {
+        result.m_value.imm3 = (value >> 12) & 7;
+        result.m_value.imm8 = value & 255;
+    }
+
     class ARMInstructionFormatter {
     public:
-        void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
+        ALWAYS_INLINE void oneWordOp5Reg3Imm8(OpcodeID op, RegisterID rd, uint8_t imm)
         {
             m_buffer.putShort(op | (rd << 8) | imm);
         }
         
-        void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
+        ALWAYS_INLINE void oneWordOp5Imm5Reg3Reg3(OpcodeID op, uint8_t imm, RegisterID reg1, RegisterID reg2)
         {
             m_buffer.putShort(op | (imm << 6) | (reg1 << 3) | reg2);
         }
 
-        void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
+        ALWAYS_INLINE void oneWordOp7Reg3Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2, RegisterID reg3)
         {
             m_buffer.putShort(op | (reg1 << 6) | (reg2 << 3) | reg3);
         }
 
-        void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
+        ALWAYS_INLINE void oneWordOp8Imm8(OpcodeID op, uint8_t imm)
         {
             m_buffer.putShort(op | imm);
         }
 
-        void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
+        ALWAYS_INLINE void oneWordOp8RegReg143(OpcodeID op, RegisterID reg1, RegisterID reg2)
         {
             m_buffer.putShort(op | ((reg2 & 8) << 4) | (reg1 << 3) | (reg2 & 7));
         }
-        void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
+
+        ALWAYS_INLINE void oneWordOp9Imm7(OpcodeID op, uint8_t imm)
         {
             m_buffer.putShort(op | imm);
         }
 
-        void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
+        ALWAYS_INLINE void oneWordOp10Reg3Reg3(OpcodeID op, RegisterID reg1, RegisterID reg2)
         {
             m_buffer.putShort(op | (reg1 << 3) | reg2);
         }
 
-        void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
+        ALWAYS_INLINE void twoWordOp12Reg4FourFours(OpcodeID1 op, RegisterID reg, FourFours ff)
         {
             m_buffer.putShort(op | reg);
             m_buffer.putShort(ff.m_u.value);
         }
         
-        void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
+        ALWAYS_INLINE void twoWordOp16FourFours(OpcodeID1 op, FourFours ff)
         {
             m_buffer.putShort(op);
             m_buffer.putShort(ff.m_u.value);
         }
         
-        void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
+        ALWAYS_INLINE void twoWordOp16Op16(OpcodeID1 op1, OpcodeID2 op2)
         {
             m_buffer.putShort(op1);
             m_buffer.putShort(op2);
         }
 
-        void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
+        ALWAYS_INLINE void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm)
         {
             ARMThumbImmediate newImm = imm;
             newImm.m_value.imm4 = imm4;
@@ -2293,7 +2241,7 @@ private:
             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
         }
 
-        void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
+        ALWAYS_INLINE void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm)
         {
             m_buffer.putShort(op | reg1);
             m_buffer.putShort((reg2 << 12) | imm);
@@ -2303,7 +2251,7 @@ private:
         //    111111111B11aaaa:bbbb222SA2C2cccc
         // Where 1s in the pattern come from op1, 2s in the pattern come from op2, S is the provided size bit.
         // Operands provide 5 bit values of the form Aaaaa, Bbbbb, Ccccc.
-        void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
+        ALWAYS_INLINE void vfpOp(OpcodeID1 op1, OpcodeID2 op2, bool size, VFPOperand a, VFPOperand b, VFPOperand c)
         {
             ASSERT(!(op1 & 0x004f));
             ASSERT(!(op2 & 0xf1af));
@@ -2313,7 +2261,7 @@ private:
 
         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
         // (i.e. +/-(0..255) 32-bit words)
-        void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
+        ALWAYS_INLINE void vfpMemOp(OpcodeID1 op1, OpcodeID2 op2, bool size, RegisterID rn, VFPOperand rd, int32_t imm)
         {
             bool up = true;
             if (imm < 0) {
@@ -2331,10 +2279,14 @@ private:
 
         // Administrative methods:
 
-        size_t size() const { return m_buffer.size(); }
+        size_t codeSize() const { return m_buffer.codeSize(); }
+        AssemblerLabel label() const { return m_buffer.label(); }
         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
         void* data() const { return m_buffer.data(); }
-        void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
+
+#ifndef NDEBUG
+        unsigned debugOffset() { return m_buffer.debugOffset(); }
+#endif
 
     private:
         AssemblerBuffer m_buffer;
index 5db2cb9fcd8bd9acced94328766cdb2c71841dbf..7d9d0925c5ee42931c3f7568eec49d7dda05049f 100644 (file)
@@ -26,8 +26,8 @@
 #ifndef AbstractMacroAssembler_h
 #define AbstractMacroAssembler_h
 
-#include <MacroAssemblerCodeRef.h>
-#include <CodeLocation.h>
+#include "CodeLocation.h"
+#include "MacroAssemblerCodeRef.h"
 #include <wtf/Noncopyable.h>
 #include <wtf/UnusedParam.h>
 
@@ -41,6 +41,7 @@ class RepatchBuffer;
 template <class AssemblerType>
 class AbstractMacroAssembler {
 public:
+    friend class JITWriteBarrierBase;
     typedef AssemblerType AssemblerType_T;
 
     typedef MacroAssemblerCodePtr CodePtr;
@@ -49,9 +50,6 @@ public:
     class Jump;
 
     typedef typename AssemblerType::RegisterID RegisterID;
-    typedef typename AssemblerType::JmpSrc JmpSrc;
-    typedef typename AssemblerType::JmpDst JmpDst;
-
 
     // Section 1: MacroAssembler operand types
     //
@@ -145,21 +143,21 @@ public:
     // Describes an memory operand given by a pointer.  For regular load & store
     // operations an unwrapped void* will be used, rather than using this.
     struct AbsoluteAddress {
-        explicit AbsoluteAddress(void* ptr)
+        explicit AbsoluteAddress(const void* ptr)
             : m_ptr(ptr)
         {
         }
 
-        void* m_ptr;
+        const void* m_ptr;
     };
 
-    // ImmPtr:
+    // TrustedImmPtr:
     //
     // A pointer sized immediate operand to an instruction - this is wrapped
     // in a class requiring explicit construction in order to differentiate
     // from pointers used as absolute addresses to memory operations
-    struct ImmPtr {
-        explicit ImmPtr(const void* value)
+    struct TrustedImmPtr {
+        explicit TrustedImmPtr(const void* value)
             : m_value(value)
         {
         }
@@ -172,14 +170,21 @@ public:
         const void* m_value;
     };
 
-    // Imm32:
+    struct ImmPtr : public TrustedImmPtr {
+        explicit ImmPtr(const void* value)
+            : TrustedImmPtr(value)
+        {
+        }
+    };
+
+    // TrustedImm32:
     //
     // A 32bit immediate operand to an instruction - this is wrapped in a
     // class requiring explicit construction in order to prevent RegisterIDs
     // (which are implemented as an enum) from accidentally being passed as
     // immediate values.
-    struct Imm32 {
-        explicit Imm32(int32_t value)
+    struct TrustedImm32 {
+        explicit TrustedImm32(int32_t value)
             : m_value(value)
 #if CPU(ARM) || CPU(MIPS)
             , m_isPointer(false)
@@ -188,7 +193,7 @@ public:
         }
 
 #if !CPU(X86_64)
-        explicit Imm32(ImmPtr ptr)
+        explicit TrustedImm32(TrustedImmPtr ptr)
             : m_value(ptr.asIntptr())
 #if CPU(ARM) || CPU(MIPS)
             , m_isPointer(true)
@@ -211,6 +216,19 @@ public:
     };
 
 
+    struct Imm32 : public TrustedImm32 {
+        explicit Imm32(int32_t value)
+            : TrustedImm32(value)
+        {
+        }
+#if !CPU(X86_64)
+        explicit Imm32(TrustedImmPtr ptr)
+            : TrustedImm32(ptr)
+        {
+        }
+#endif
+    };
+    
     // Section 2: MacroAssembler code buffer handles
     //
     // The following types are used to reference items in the code buffer
@@ -240,10 +258,9 @@ public:
         {
         }
         
-        bool isUsed() const { return m_label.isUsed(); }
-        void used() { m_label.used(); }
+        bool isSet() const { return m_label.isSet(); }
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // DataLabelPtr:
@@ -264,8 +281,10 @@ public:
         {
         }
         
+        bool isSet() const { return m_label.isSet(); }
+        
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // DataLabel32:
@@ -286,8 +305,37 @@ public:
         {
         }
 
+        AssemblerLabel label() const { return m_label; }
+
+    private:
+        AssemblerLabel m_label;
+    };
+
+    // DataLabelCompact:
+    //
+    // A DataLabelCompact is used to refer to a location in the code containing a
+    // compact immediate to be patched after the code has been generated.
+    class DataLabelCompact {
+        template<class TemplateAssemblerType>
+        friend class AbstractMacroAssembler;
+        friend class LinkBuffer;
+    public:
+        DataLabelCompact()
+        {
+        }
+        
+        DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm)
+            : m_label(masm->m_assembler.label())
+        {
+        }
+    
+        DataLabelCompact(AssemblerLabel label)
+            : m_label(label)
+        {
+        }
+
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // Call:
@@ -313,7 +361,7 @@ public:
         {
         }
         
-        Call(JmpSrc jmp, Flags flags)
+        Call(AssemblerLabel jmp, Flags flags)
             : m_jmp(jmp)
             , m_flags(flags)
         {
@@ -329,7 +377,7 @@ public:
             return Call(jump.m_jmp, Linkable);
         }
 
-        JmpSrc m_jmp;
+        AssemblerLabel m_jmp;
     private:
         Flags m_flags;
     };
@@ -350,23 +398,47 @@ public:
         {
         }
         
-        Jump(JmpSrc jmp)    
+#if CPU(ARM_THUMB2)
+        // Fixme: this information should be stored in the instruction stream, not in the Jump object.
+        Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
             : m_jmp(jmp)
+            , m_type(type)
+            , m_condition(condition)
         {
         }
-        
-        void link(AbstractMacroAssembler<AssemblerType>* masm)
+#else
+        Jump(AssemblerLabel jmp)    
+            : m_jmp(jmp)
+        {
+        }
+#endif
+
+        void link(AbstractMacroAssembler<AssemblerType>* masm) const
         {
+#if CPU(ARM_THUMB2)
+            masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label(), m_type, m_condition);
+#else
             masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
+#endif
         }
         
-        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
+        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
         {
+#if CPU(ARM_THUMB2)
+            masm->m_assembler.linkJump(m_jmp, label.m_label, m_type, m_condition);
+#else
             masm->m_assembler.linkJump(m_jmp, label.m_label);
+#endif
         }
 
+        bool isSet() const { return m_jmp.isSet(); }
+
     private:
-        JmpSrc m_jmp;
+        AssemblerLabel m_jmp;
+#if CPU(ARM_THUMB2)
+        ARMv7Assembler::JumpType m_type;
+        ARMv7Assembler::Condition m_condition;
+#endif
     };
 
     // JumpList:
@@ -410,6 +482,11 @@ public:
             return !m_jumps.size();
         }
         
+        void clear()
+        {
+            m_jumps.clear();
+        }
+        
         const JumpVector& jumps() { return m_jumps; }
 
     private:
@@ -418,11 +495,6 @@ public:
 
 
     // Section 3: Misc admin methods
-    size_t size()
-    {
-        return m_assembler.size();
-    }
-
     Label label()
     {
         return Label(this);
@@ -458,6 +530,11 @@ public:
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
+    
+    ptrdiff_t differenceBetween(Label from, DataLabelCompact to)
+    {
+        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+    }
 
     ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
     {
@@ -473,10 +550,19 @@ public:
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
     }
-    
+
+    // Temporary interface; likely to be removed, since may be hard to port to all architectures.
+#if CPU(X86) || CPU(X86_64)
+    void rewindToLabel(Label rewindTo) { m_assembler.rewindToLabel(rewindTo.m_label); }
+#endif
+
     void beginUninterruptedSequence() { }
     void endUninterruptedSequence() { }
 
+#ifndef NDEBUG
+    unsigned debugOffset() { return m_assembler.debugOffset(); }
+#endif
+
 protected:
     AssemblerType m_assembler;
 
@@ -488,17 +574,12 @@ protected:
         AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
     }
 
-    static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value)
+    static void linkPointer(void* code, AssemblerLabel label, void* value)
     {
         AssemblerType::linkPointer(code, label, value);
     }
 
-    static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label)
-    {
-        return AssemblerType::getRelocatedAddress(code, label);
-    }
-
-    static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label)
+    static void* getLinkerAddress(void* code, AssemblerLabel label)
     {
         return AssemblerType::getRelocatedAddress(code, label);
     }
@@ -518,6 +599,11 @@ protected:
         AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
     }
 
+    static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
+    {
+        AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
+    }
+    
     static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
     {
         AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
@@ -527,10 +613,10 @@ protected:
     {
         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
     }
-
-    static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
+    
+    static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
     {
-        AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
+        return AssemblerType::readPointer(dataLabelPtr.dataLocation());
     }
 };
 
index e2fb8a1cc68d019c0ed4305e9e5c0b3611bafd69..b98503d0876e96bec8181eb9c261eedb07e059c5 100644 (file)
 #include <jit/ExecutableAllocator.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
-    class AssemblerBuffer {
-        static const int inlineCapacity = 256;
-    public:
-        AssemblerBuffer()
-            : m_buffer(m_inlineBuffer)
-            , m_capacity(inlineCapacity)
-            , m_size(0)
+    struct AssemblerLabel {
+        AssemblerLabel()
+            : m_offset(std::numeric_limits<uint32_t>::max())
         {
         }
 
-        ~AssemblerBuffer()
+        explicit AssemblerLabel(uint32_t offset)
+            : m_offset(offset)
         {
-            if (m_buffer != m_inlineBuffer)
-                fastFree(m_buffer);
         }
 
-        void ensureSpace(int space)
-        {
-            if (m_size > m_capacity - space)
-                grow();
-        }
+        bool isSet() const { return (m_offset != std::numeric_limits<uint32_t>::max()); }
 
-        bool isAligned(int alignment) const
+        AssemblerLabel labelAtOffset(int offset) const
         {
-            return !(m_size & (alignment - 1));
+            return AssemblerLabel(m_offset + offset);
         }
 
-        void putByteUnchecked(int value)
+        uint32_t m_offset;
+    };
+
+    class AssemblerBuffer {
+        static const int inlineCapacity = 128;
+    public:
+        AssemblerBuffer()
+            : m_storage(inlineCapacity)
+            , m_buffer(m_storage.begin())
+            , m_capacity(inlineCapacity)
+            , m_index(0)
         {
-            ASSERT(!(m_size > m_capacity - 4));
-            m_buffer[m_size] = value;
-            m_size++;
         }
 
-        void putByte(int value)
+        ~AssemblerBuffer()
         {
-            if (m_size > m_capacity - 4)
-                grow();
-            putByteUnchecked(value);
         }
 
-        void putShortUnchecked(int value)
+        bool isAvailable(int space)
         {
-            ASSERT(!(m_size > m_capacity - 4));
-            *reinterpret_cast<short*>(&m_buffer[m_size]) = value;
-            m_size += 2;
+            return m_index + space <= m_capacity;
         }
 
-        void putShort(int value)
+        void ensureSpace(int space)
         {
-            if (m_size > m_capacity - 4)
+            if (!isAvailable(space))
                 grow();
-            putShortUnchecked(value);
         }
 
-        void putIntUnchecked(int value)
+        bool isAligned(int alignment) const
         {
-            ASSERT(!(m_size > m_capacity - 4));
-            *reinterpret_cast<int*>(&m_buffer[m_size]) = value;
-            m_size += 4;
+            return !(m_index & (alignment - 1));
         }
 
-        void putInt64Unchecked(int64_t value)
+        template<typename IntegralType>
+        void putIntegral(IntegralType value)
         {
-            ASSERT(!(m_size > m_capacity - 8));
-            *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
-            m_size += 8;
+            ensureSpace(sizeof(IntegralType));
+            putIntegralUnchecked(value);
         }
 
-        void putInt(int value)
+        template<typename IntegralType>
+        void putIntegralUnchecked(IntegralType value)
         {
-            if (m_size > m_capacity - 4)
-                grow();
-            putIntUnchecked(value);
+            ASSERT(isAvailable(sizeof(IntegralType)));
+            *reinterpret_cast_ptr<IntegralType*>(m_buffer + m_index) = value;
+            m_index += sizeof(IntegralType);
         }
 
+        void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); }
+        void putByte(int8_t value) { putIntegral(value); }
+        void putShortUnchecked(int16_t value) { putIntegralUnchecked(value); }
+        void putShort(int16_t value) { putIntegral(value); }
+        void putIntUnchecked(int32_t value) { putIntegralUnchecked(value); }
+        void putInt(int32_t value) { putIntegral(value); }
+        void putInt64Unchecked(int64_t value) { putIntegralUnchecked(value); }
+        void putInt64(int64_t value) { putIntegral(value); }
+
         void* data() const
         {
             return m_buffer;
         }
 
-        int size() const
+        size_t codeSize() const
         {
-            return m_size;
+            return m_index;
         }
 
-        void* executableCopy(ExecutablePool* allocator)
+        AssemblerLabel label() const
         {
-            if (!m_size)
+            return AssemblerLabel(m_index);
+        }
+
+        void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+        {
+            if (!m_index)
                 return 0;
 
-            void* result = allocator->alloc(m_size);
+            void* result = allocator->alloc(globalData, m_index);
 
             if (!result)
                 return 0;
 
-            ExecutableAllocator::makeWritable(result, m_size);
+            ExecutableAllocator::makeWritable(result, m_index);
 
-            return memcpy(result, m_buffer, m_size);
+            return memcpy(result, m_buffer, m_index);
         }
 
+        void rewindToLabel(AssemblerLabel label)
+        {
+            m_index = label.m_offset;
+        }
+
+#ifndef NDEBUG
+        unsigned debugOffset() { return m_index; }
+#endif
+
     protected:
         void append(const char* data, int size)
         {
-            if (m_size > m_capacity - size)
+            if (!isAvailable(size))
                 grow(size);
 
-            memcpy(m_buffer + m_size, data, size);
-            m_size += size;
+            memcpy(m_buffer + m_index, data, size);
+            m_index += size;
         }
 
         void grow(int extraCapacity = 0)
         {
             m_capacity += m_capacity / 2 + extraCapacity;
 
-            if (m_buffer == m_inlineBuffer) {
-                char* newBuffer = static_cast<char*>(fastMalloc(m_capacity));
-                m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size));
-            } else
-                m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity));
+            m_storage.grow(m_capacity);
+            m_buffer = m_storage.begin();
         }
 
-        char m_inlineBuffer[inlineCapacity];
+    private:
+        Vector<char, inlineCapacity> m_storage;
         char* m_buffer;
         int m_capacity;
-        int m_size;
+        int m_index;
     };
 
 } // namespace JSC
index b1c537e1e3e0d2748e3175adf810ffd16101dbfe..cd9ff9c0ef43aacd592e933fa19af15d3c6b75a7 100644 (file)
@@ -85,7 +85,14 @@ namespace JSC {
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
 class AssemblerBufferWithConstantPool: public AssemblerBuffer {
     typedef SegmentedVector<uint32_t, 512> LoadOffsets;
+    using AssemblerBuffer::putIntegral;
+    using AssemblerBuffer::putIntegralUnchecked;
 public:
+    typedef struct {
+        short high;
+        short low;
+    } TwoShorts;
+
     enum {
         UniqueConst,
         ReusableConst,
@@ -120,6 +127,11 @@ public:
         AssemblerBuffer::ensureSpace(insnSpace);
     }
 
+    void ensureSpaceForAnyOneInstruction()
+    {
+        flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t));
+    }
+
     bool isAligned(int alignment)
     {
         flushIfNoSpaceFor(alignment);
@@ -171,44 +183,32 @@ public:
         correctDeltas(8);
     }
 
-    int size()
+    void putIntegral(TwoShorts value)
     {
-        flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t));
-        return AssemblerBuffer::size();
+        putIntegral(value.high);
+        putIntegral(value.low);
     }
 
-    int uncheckedSize()
+    void putIntegralUnchecked(TwoShorts value)
     {
-        return AssemblerBuffer::size();
+        putIntegralUnchecked(value.high);
+        putIntegralUnchecked(value.low);
     }
 
-    void* executableCopy(ExecutablePool* allocator)
+    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
     {
         flushConstantPool(false);
-        return AssemblerBuffer::executableCopy(allocator);
+        return AssemblerBuffer::executableCopy(globalData, allocator);
     }
 
-    void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
+    void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false)
     {
-        flushIfNoSpaceFor(4, 4);
-
-        m_loadOffsets.append(AssemblerBuffer::size());
-        if (isReusable)
-            for (int i = 0; i < m_numConsts; ++i) {
-                if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
-                    AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i));
-                    correctDeltas(4);
-                    return;
-                }
-            }
-
-        m_pool[m_numConsts] = constant;
-        m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
-
-        AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
-        ++m_numConsts;
+        putIntegralWithConstantInt(insn, constant, isReusable);
+    }
 
-        correctDeltas(4, 4);
+    void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
+    {
+        putIntegralWithConstantInt(insn, constant, isReusable);
     }
 
     // This flushing mechanism can be called after any unconditional jumps.
@@ -246,18 +246,45 @@ private:
         m_lastConstDelta = constSize;
     }
 
+    template<typename IntegralType>
+    void putIntegralWithConstantInt(IntegralType insn, uint32_t constant, bool isReusable)
+    {
+        if (!m_numConsts)
+            m_maxDistance = maxPoolSize;
+        flushIfNoSpaceFor(sizeof(IntegralType), 4);
+
+        m_loadOffsets.append(codeSize());
+        if (isReusable) {
+            for (int i = 0; i < m_numConsts; ++i) {
+                if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
+                    putIntegral(static_cast<IntegralType>(AssemblerType::patchConstantPoolLoad(insn, i)));
+                    correctDeltas(sizeof(IntegralType));
+                    return;
+                }
+            }
+        }
+
+        m_pool[m_numConsts] = constant;
+        m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
+
+        putIntegral(static_cast<IntegralType>(AssemblerType::patchConstantPoolLoad(insn, m_numConsts)));
+        ++m_numConsts;
+
+        correctDeltas(sizeof(IntegralType), 4);
+    }
+
     void flushConstantPool(bool useBarrier = true)
     {
         if (m_numConsts == 0)
             return;
-        int alignPool = (AssemblerBuffer::size() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1);
+        int alignPool = (codeSize() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1);
 
         if (alignPool)
             alignPool = sizeof(uint64_t) - alignPool;
 
         // Callback to protect the constant pool from execution
         if (useBarrier)
-            AssemblerBuffer::putInt(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool));
+            putIntegral(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool));
 
         if (alignPool) {
             if (alignPool & 1)
@@ -268,18 +295,17 @@ private:
                 AssemblerBuffer::putInt(AssemblerType::padForAlign32);
         }
 
-        int constPoolOffset = AssemblerBuffer::size();
+        int constPoolOffset = codeSize();
         append(reinterpret_cast<char*>(m_pool), m_numConsts * sizeof(uint32_t));
 
         // Patch each PC relative load
         for (LoadOffsets::Iterator iter = m_loadOffsets.begin(); iter != m_loadOffsets.end(); ++iter) {
-            void* loadAddr = reinterpret_cast<void*>(m_buffer + *iter);
-            AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast<void*>(m_buffer + constPoolOffset));
+            void* loadAddr = reinterpret_cast<char*>(data()) + *iter;
+            AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast<char*>(data()) + constPoolOffset);
         }
 
         m_loadOffsets.clear();
         m_numConsts = 0;
-        m_maxDistance = maxPoolSize;
     }
 
     void flushIfNoSpaceFor(int nextInsnSize)
index cab28cd905c1695ca447c6c896c5bf918bf0c99d..9500b1ee44f2b454abc41a872fcf2fc8c0c861e6 100644 (file)
@@ -26,8 +26,7 @@
 #ifndef CodeLocation_h
 #define CodeLocation_h
 
-
-#include <MacroAssemblerCodeRef.h>
+#include "MacroAssemblerCodeRef.h"
 
 #if ENABLE(ASSEMBLER)
 
@@ -38,6 +37,7 @@ class CodeLocationLabel;
 class CodeLocationJump;
 class CodeLocationCall;
 class CodeLocationNearCall;
+class CodeLocationDataLabelCompact;
 class CodeLocationDataLabel32;
 class CodeLocationDataLabelPtr;
 
@@ -61,6 +61,7 @@ public:
     CodeLocationNearCall nearCallAtOffset(int offset);
     CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
     CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
+    CodeLocationDataLabelCompact dataLabelCompactAtOffset(int offset);
 
 protected:
     CodeLocationCommon()
@@ -127,6 +128,15 @@ public:
         : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
 };
 
+class CodeLocationDataLabelCompact : public CodeLocationCommon {
+public:
+    CodeLocationDataLabelCompact() { }
+    explicit CodeLocationDataLabelCompact(MacroAssemblerCodePtr location)
+        : CodeLocationCommon(location) { }
+    explicit CodeLocationDataLabelCompact(void* location)
+        : CodeLocationCommon(MacroAssemblerCodePtr(location)) { }
+};
+
 class CodeLocationDataLabelPtr : public CodeLocationCommon {
 public:
     CodeLocationDataLabelPtr() {}
@@ -178,6 +188,12 @@ inline CodeLocationDataLabel32 CodeLocationCommon::dataLabel32AtOffset(int offse
     return CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset);
 }
 
+inline CodeLocationDataLabelCompact CodeLocationCommon::dataLabelCompactAtOffset(int offset)
+{
+    ASSERT_VALID_CODE_OFFSET(offset);
+    return CodeLocationDataLabelCompact(reinterpret_cast<char*>(dataLocation()) + offset);
+}
+
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
index ae58946d97f13a705cecef26db337d6d14c07ba9..59b5a1e6110c5e6197b2144d2bb457b5b3917c1a 100644 (file)
 
 #if ENABLE(ASSEMBLER)
 
+#define DUMP_LINK_STATISTICS 0
+#define DUMP_CODE 0
+
 #include <MacroAssembler.h>
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
+class JSGlobalData;
+
 // LinkBuffer:
 //
 // This class assists in linking code generated by the macro assembler, once code generation
@@ -47,36 +52,47 @@ namespace JSC {
 //   * The address of a Label pointing into the code may be resolved.
 //   * The value referenced by a DataLabel may be set.
 //
-class LinkBuffer : public Noncopyable {
+class LinkBuffer {
+    WTF_MAKE_NONCOPYABLE(LinkBuffer);
     typedef MacroAssemblerCodeRef CodeRef;
     typedef MacroAssemblerCodePtr CodePtr;
     typedef MacroAssembler::Label Label;
     typedef MacroAssembler::Jump Jump;
     typedef MacroAssembler::JumpList JumpList;
     typedef MacroAssembler::Call Call;
+    typedef MacroAssembler::DataLabelCompact DataLabelCompact;
     typedef MacroAssembler::DataLabel32 DataLabel32;
     typedef MacroAssembler::DataLabelPtr DataLabelPtr;
-    typedef MacroAssembler::JmpDst JmpDst;
 #if ENABLE(BRANCH_COMPACTION)
     typedef MacroAssembler::LinkRecord LinkRecord;
     typedef MacroAssembler::JumpLinkType JumpLinkType;
 #endif
 
 public:
-    // Note: Initialization sequence is significant, since executablePool is a PassRefPtr.
-    //       First, executablePool is copied into m_executablePool, then the initialization of
-    //       m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
-    // The linkOffset parameter should only be non-null when recompiling for exception info
-    LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool, void* linkOffset)
+    LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool)
         : m_executablePool(executablePool)
         , m_size(0)
         , m_code(0)
         , m_assembler(masm)
+        , m_globalData(&globalData)
+#ifndef NDEBUG
+        , m_completed(false)
+#endif
+    {
+        linkCode();
+    }
+
+    LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, ExecutableAllocator& allocator)
+        : m_executablePool(allocator.poolForSize(globalData, masm->m_assembler.codeSize()))
+        , m_size(0)
+        , m_code(0)
+        , m_assembler(masm)
+        , m_globalData(&globalData)
 #ifndef NDEBUG
         , m_completed(false)
 #endif
     {
-        linkCode(linkOffset);
+        linkCode();
     }
 
     ~LinkBuffer()
@@ -107,13 +123,13 @@ public:
 
     void patch(DataLabelPtr label, void* value)
     {
-        JmpDst target = applyOffset(label.m_label);
+        AssemblerLabel target = applyOffset(label.m_label);
         MacroAssembler::linkPointer(code(), target, value);
     }
 
     void patch(DataLabelPtr label, CodeLocationLabel value)
     {
-        JmpDst target = applyOffset(label.m_label);
+        AssemblerLabel target = applyOffset(label.m_label);
         MacroAssembler::linkPointer(code(), target, value.executableAddress());
     }
 
@@ -147,6 +163,11 @@ public:
     {
         return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label)));
     }
+    
+    CodeLocationDataLabelCompact locationOf(DataLabelCompact label)
+    {
+        return CodeLocationDataLabelCompact(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label)));
+    }
 
     // This method obtains the return address of the call, given as an offset from
     // the start of the code.
@@ -179,6 +200,13 @@ public:
         return CodePtr(MacroAssembler::AssemblerType_T::getRelocatedAddress(code(), applyOffset(label.m_label)));
     }
 
+#ifndef NDEBUG
+    void* debugAddress()
+    {
+        return m_code;
+    }
+#endif
+
 private:
     template <typename T> T applyOffset(T src)
     {
@@ -195,22 +223,21 @@ private:
         return m_code;
     }
 
-    void linkCode(void* linkOffset)
+    void linkCode()
     {
-        UNUSED_PARAM(linkOffset);
         ASSERT(!m_code);
 #if !ENABLE(BRANCH_COMPACTION)
-        m_code = m_assembler->m_assembler.executableCopy(m_executablePool.get());
-        m_size = m_assembler->size();
+        m_code = m_assembler->m_assembler.executableCopy(*m_globalData, m_executablePool.get());
+        m_size = m_assembler->m_assembler.codeSize();
+        ASSERT(m_code);
 #else
-        size_t initialSize = m_assembler->size();
-        m_code = (uint8_t*)m_executablePool->alloc(initialSize);
+        size_t initialSize = m_assembler->m_assembler.codeSize();
+        m_code = (uint8_t*)m_executablePool->alloc(*m_globalData, initialSize);
         if (!m_code)
             return;
-        ExecutableAllocator::makeWritable(m_code, m_assembler->size());
+        ExecutableAllocator::makeWritable(m_code, initialSize);
         uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
         uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
-        const uint8_t* linkBase = linkOffset ? reinterpret_cast<uint8_t*>(linkOffset) : outData;
         int readPtr = 0;
         int writePtr = 0;
         Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
@@ -221,7 +248,14 @@ private:
             
             // Copy the instructions from the last jump to the current one.
             size_t regionSize = jumpsToLink[i].from() - readPtr;
-            memcpy(outData + writePtr, inData + readPtr, regionSize);
+            uint16_t* copySource = reinterpret_cast<uint16_t*>(inData + readPtr);
+            uint16_t* copyEnd = reinterpret_cast<uint16_t*>(inData + readPtr + regionSize);
+            uint16_t* copyDst = reinterpret_cast<uint16_t*>(outData + writePtr);
+            ASSERT(!(regionSize % 2));
+            ASSERT(!(readPtr % 2));
+            ASSERT(!(writePtr % 2));
+            while (copySource != copyEnd)
+                *copyDst++ = *copySource++;
             m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
             readPtr += regionSize;
             writePtr += regionSize;
@@ -230,11 +264,11 @@ private:
             // branches we need to be precise, forward branches we are pessimistic
             const uint8_t* target;
             if (jumpsToLink[i].to() >= jumpsToLink[i].from())
-                target = linkBase + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
+                target = outData + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
             else
-                target = linkBase + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
+                target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
             
-            JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], linkBase + writePtr, target);
+            JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], outData + writePtr, target);
             // Compact branch if we can...
             if (m_assembler->canCompact(jumpsToLink[i].type())) {
                 // Step back in the write stream
@@ -247,22 +281,25 @@ private:
             jumpsToLink[i].setFrom(writePtr);
         }
         // Copy everything after the last jump
-        memcpy(outData + writePtr, inData + readPtr, m_assembler->size() - readPtr);
-        m_assembler->recordLinkOffsets(readPtr, m_assembler->size(), readPtr - writePtr);
+        memcpy(outData + writePtr, inData + readPtr, initialSize - readPtr);
+        m_assembler->recordLinkOffsets(readPtr, initialSize, readPtr - writePtr);
         
-        // Actually link everything (don't link if we've be given a linkoffset as it's a
-        // waste of time: linkOffset is used for recompiling to get exception info)
-        if (!linkOffset) {
-            for (unsigned i = 0; i < jumpCount; ++i) {
-                uint8_t* location = outData + jumpsToLink[i].from();
-                uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
-                m_assembler->link(jumpsToLink[i], location, target);
-            }
+        for (unsigned i = 0; i < jumpCount; ++i) {
+            uint8_t* location = outData + jumpsToLink[i].from();
+            uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
+            m_assembler->link(jumpsToLink[i], location, target);
         }
 
         jumpsToLink.clear();
-        m_size = writePtr + m_assembler->size() - readPtr;
+        m_size = writePtr + initialSize - readPtr;
         m_executablePool->tryShrink(m_code, initialSize, m_size);
+
+#if DUMP_LINK_STATISTICS
+        dumpLinkStatistics(m_code, initialSize, m_size);
+#endif
+#if DUMP_CODE
+        dumpCode(m_code, m_size);
+#endif
 #endif
     }
 
@@ -277,10 +314,58 @@ private:
         ExecutableAllocator::cacheFlush(code(), m_size);
     }
 
+#if DUMP_LINK_STATISTICS
+    static void dumpLinkStatistics(void* code, size_t initialSize, size_t finalSize)
+    {
+        static unsigned linkCount = 0;
+        static unsigned totalInitialSize = 0;
+        static unsigned totalFinalSize = 0;
+        linkCount++;
+        totalInitialSize += initialSize;
+        totalFinalSize += finalSize;
+        printf("link %p: orig %u, compact %u (delta %u, %.2f%%)\n", 
+               code, static_cast<unsigned>(initialSize), static_cast<unsigned>(finalSize),
+               static_cast<unsigned>(initialSize - finalSize),
+               100.0 * (initialSize - finalSize) / initialSize);
+        printf("\ttotal %u: orig %u, compact %u (delta %u, %.2f%%)\n", 
+               linkCount, totalInitialSize, totalFinalSize, totalInitialSize - totalFinalSize,
+               100.0 * (totalInitialSize - totalFinalSize) / totalInitialSize);
+    }
+#endif
+    
+#if DUMP_CODE
+    static void dumpCode(void* code, size_t size)
+    {
+#if CPU(ARM_THUMB2)
+        // Dump the generated code in an asm file format that can be assembled and then disassembled
+        // for debugging purposes. For example, save this output as jit.s:
+        //   gcc -arch armv7 -c jit.s
+        //   otool -tv jit.o
+        static unsigned codeCount = 0;
+        unsigned short* tcode = static_cast<unsigned short*>(code);
+        size_t tsize = size / sizeof(short);
+        char nameBuf[128];
+        snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++);
+        printf("\t.syntax unified\n"
+               "\t.section\t__TEXT,__text,regular,pure_instructions\n"
+               "\t.globl\t%s\n"
+               "\t.align 2\n"
+               "\t.code 16\n"
+               "\t.thumb_func\t%s\n"
+               "# %p\n"
+               "%s:\n", nameBuf, nameBuf, code, nameBuf);
+        
+        for (unsigned i = 0; i < tsize; i++)
+            printf("\t.short\t0x%x\n", tcode[i]);
+#endif
+    }
+#endif
+    
     RefPtr<ExecutablePool> m_executablePool;
     size_t m_size;
     void* m_code;
     MacroAssembler* m_assembler;
+    JSGlobalData* m_globalData;
 #ifndef NDEBUG
     bool m_completed;
 #endif
index ea352685115d65315d9746fe60a124ba8dacb2d4..4164fa9db0d9f92434e1ee146492f321bb3ef873 100644 (file)
@@ -148,7 +148,7 @@ class MIPSAssembler {
 public:
     typedef MIPSRegisters::RegisterID RegisterID;
     typedef MIPSRegisters::FPRegisterID FPRegisterID;
-    typedef SegmentedVector<int, 64> Jumps;
+    typedef SegmentedVector<AssemblerLabel, 64> Jumps;
 
     MIPSAssembler()
     {
@@ -166,46 +166,6 @@ public:
         OP_SH_FT = 16
     };
 
-    class JmpSrc {
-        friend class MIPSAssembler;
-    public:
-        JmpSrc()
-            : m_offset(-1)
-        {
-        }
-
-    private:
-        JmpSrc(int offset)
-            : m_offset(offset)
-        {
-        }
-
-        int m_offset;
-    };
-
-    class JmpDst {
-        friend class MIPSAssembler;
-    public:
-        JmpDst()
-            : m_offset(-1)
-            , m_used(false)
-        {
-        }
-
-        bool isUsed() const { return m_used; }
-        void used() { m_used = true; }
-    private:
-        JmpDst(int offset)
-            : m_offset(offset)
-            , m_used(false)
-        {
-            ASSERT(m_offset == offset);
-        }
-
-        int m_offset : 31;
-        int m_used : 1;
-    };
-
     void emitInst(MIPSWord op)
     {
         void* oldBase = m_buffer.data();
@@ -287,6 +247,11 @@ public:
         emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT));
     }
 
+    void div(RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x0000001a | (rs << OP_SH_RS) | (rt << OP_SH_RT));
+    }
+
     void mfhi(RegisterID rd)
     {
         emitInst(0x00000010 | (rd << OP_SH_RD));
@@ -392,6 +357,18 @@ public:
                  | (rs << OP_SH_RS));
     }
 
+    void srl(RegisterID rd, RegisterID rt, int shamt)
+    {
+        emitInst(0x00000002 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | ((shamt & 0x1f) << OP_SH_SHAMT));
+    }
+
+    void srlv(RegisterID rd, RegisterID rt, RegisterID rs)
+    {
+        emitInst(0x00000006 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | (rs << OP_SH_RS));
+    }
+
     void lbu(RegisterID rt, RegisterID rs, int offset)
     {
         emitInst(0x90000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
@@ -484,14 +461,9 @@ public:
         emitInst(0x45000000);
     }
 
-    JmpSrc newJmpSrc()
-    {
-        return JmpSrc(m_buffer.size());
-    }
-
     void appendJump()
     {
-        m_jumps.append(m_buffer.size());
+        m_jumps.append(m_buffer.label());
     }
 
     void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
@@ -512,6 +484,12 @@ public:
                  | (ft << OP_SH_FT));
     }
 
+    void divd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200003 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
+                 | (ft << OP_SH_FT));
+    }
+
     void lwc1(FPRegisterID ft, RegisterID rs, int offset)
     {
         emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
@@ -543,12 +521,23 @@ public:
         copDelayNop();
     }
 
+    void mthc1(RegisterID rt, FPRegisterID fs)
+    {
+        emitInst(0x44e00000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
+        copDelayNop();
+    }
+
     void mfc1(RegisterID rt, FPRegisterID fs)
     {
         emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
         copDelayNop();
     }
 
+    void sqrtd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
     void truncwd(FPRegisterID fd, FPRegisterID fs)
     {
         emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS));
@@ -559,6 +548,11 @@ public:
         emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
     }
 
+    void cvtwd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200024 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
     void ceqd(FPRegisterID fs, FPRegisterID ft)
     {
         emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
@@ -621,12 +615,12 @@ public:
 
     // General helpers
 
-    JmpDst label()
+    AssemblerLabel label()
     {
-        return JmpDst(m_buffer.size());
+        return m_buffer.label();
     }
 
-    JmpDst align(int alignment)
+    AssemblerLabel align(int alignment)
     {
         while (!m_buffer.isAligned(alignment))
             bkpt();
@@ -634,44 +628,26 @@ public:
         return label();
     }
 
-    static void* getRelocatedAddress(void* code, JmpSrc jump)
+    static void* getRelocatedAddress(void* code, AssemblerLabel label)
     {
-        ASSERT(jump.m_offset != -1);
-        void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + jump.m_offset);
-        return b;
+        return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
     }
 
-    static void* getRelocatedAddress(void* code, JmpDst label)
+    static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
     {
-        void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + label.m_offset);
-        return b;
-    }
-
-    static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
-    {
-        return to.m_offset - from.m_offset;
-    }
-
-    static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
-    {
-        return to.m_offset - from.m_offset;
-    }
-
-    static int getDifferenceBetweenLabels(JmpSrc from, JmpDst to)
-    {
-        return to.m_offset - from.m_offset;
+        return b.m_offset - a.m_offset;
     }
 
     // Assembler admin methods:
 
-    size_t size() const
+    size_t codeSize() const
     {
-        return m_buffer.size();
+        return m_buffer.codeSize();
     }
 
-    void* executableCopy(ExecutablePool* allocator)
+    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
     {
-        void *result = m_buffer.executableCopy(allocator);
+        void *result = m_buffer.executableCopy(globalData, allocator);
         if (!result)
             return 0;
 
@@ -679,7 +655,11 @@ public:
         return result;
     }
 
-    static unsigned getCallReturnOffset(JmpSrc call)
+#ifndef NDEBUG
+    unsigned debugOffset() { return m_buffer.debugOffset(); }
+#endif
+
+    static unsigned getCallReturnOffset(AssemblerLabel call)
     {
         // The return address is after a call and a delay slot instruction
         return call.m_offset;
@@ -693,10 +673,10 @@ public:
     // writable region of memory; to modify the code in an execute-only execuable
     // pool the 'repatch' and 'relink' methods should be used.
 
-    void linkJump(JmpSrc from, JmpDst to)
+    void linkJump(AssemblerLabel from, AssemblerLabel to)
     {
-        ASSERT(to.m_offset != -1);
-        ASSERT(from.m_offset != -1);
+        ASSERT(to.isSet());
+        ASSERT(from.isSet());
         MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + from.m_offset);
         MIPSWord* toPos = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + to.m_offset);
 
@@ -705,9 +685,9 @@ public:
         linkWithOffset(insn, toPos);
     }
 
-    static void linkJump(void* code, JmpSrc from, void* to)
+    static void linkJump(void* code, AssemblerLabel from, void* to)
     {
-        ASSERT(from.m_offset != -1);
+        ASSERT(from.isSet());
         MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
 
         ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
@@ -715,13 +695,13 @@ public:
         linkWithOffset(insn, to);
     }
 
-    static void linkCall(void* code, JmpSrc from, void* to)
+    static void linkCall(void* code, AssemblerLabel from, void* to)
     {
         MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
         linkCallInternal(insn, to);
     }
 
-    static void linkPointer(void* code, JmpDst from, void* to)
+    static void linkPointer(void* code, AssemblerLabel from, void* to)
     {
         MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
         ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
@@ -766,34 +746,42 @@ public:
         ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord));
     }
 
+    static int32_t readInt32(void* from)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+        int32_t result = (*insn & 0x0000ffff) << 16;
+        insn++;
+        ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
+        result |= *insn & 0x0000ffff
+    }
+    
+    static void repatchCompact(void* where, int32_t value)
+    {
+        repatchInt32(where, value);
+    }
+
     static void repatchPointer(void* from, void* to)
     {
         repatchInt32(from, reinterpret_cast<int32_t>(to));
     }
 
-    static void repatchLoadPtrToLEA(void* from)
+    static void* readPointer(void* from)
     {
-        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
-        insn = insn + 3;
-        ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw
-        /* lw -> addiu */
-        *insn = 0x24000000 | (*insn & 0x03ffffff);
-
-        ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord));
+        return static_cast<void*>(readInt32(from));
     }
 
 private:
-
     /* Update each jump in the buffer of newBase.  */
     void relocateJumps(void* oldBase, void* newBase)
     {
         // Check each jump
         for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
-            int pos = *iter;
+            int pos = iter->m_offset;
             MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(newBase) + pos);
             insn = insn + 2;
             // Need to make sure we have 5 valid instructions after pos
-            if ((unsigned int)pos >= m_buffer.size() - 5 * sizeof(MIPSWord))
+            if ((unsigned int)pos >= m_buffer.codeSize() - 5 * sizeof(MIPSWord))
                 continue;
 
             if ((*insn & 0xfc000000) == 0x08000000) { // j
index ce1be78a8c7698f3206b089ebde56ae5bc73029e..c8506c74a72ab3b8d6e20720189ed8f29366175f 100644 (file)
@@ -50,6 +50,12 @@ namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
 #include "MacroAssemblerX86_64.h"
 namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; };
 
+#elif CPU(SH4)
+#include "MacroAssemblerSH4.h"
+namespace JSC {
+typedef MacroAssemblerSH4 MacroAssemblerBase;
+};
+
 #else
 #error "The MacroAssembler is not supported on this platform."
 #endif
@@ -74,7 +80,7 @@ public:
     // described in terms of other macro assembly methods.
     void pop()
     {
-        addPtr(Imm32(sizeof(void*)), stackPointerRegister);
+        addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister);
     }
     
     void peek(RegisterID dest, int index = 0)
@@ -87,44 +93,44 @@ public:
         storePtr(src, Address(stackPointerRegister, (index * sizeof(void*))));
     }
 
-    void poke(Imm32 value, int index = 0)
+    void poke(TrustedImm32 value, int index = 0)
     {
         store32(value, Address(stackPointerRegister, (index * sizeof(void*))));
     }
 
-    void poke(ImmPtr imm, int index = 0)
+    void poke(TrustedImmPtr imm, int index = 0)
     {
         storePtr(imm, Address(stackPointerRegister, (index * sizeof(void*))));
     }
 
 
     // Backwards banches, these are currently all implemented using existing forwards branch mechanisms.
-    void branchPtr(Condition cond, RegisterID op1, ImmPtr imm, Label target)
+    void branchPtr(RelationalCondition cond, RegisterID op1, TrustedImmPtr imm, Label target)
     {
         branchPtr(cond, op1, imm).linkTo(target, this);
     }
 
-    void branch32(Condition cond, RegisterID op1, RegisterID op2, Label target)
+    void branch32(RelationalCondition cond, RegisterID op1, RegisterID op2, Label target)
     {
         branch32(cond, op1, op2).linkTo(target, this);
     }
 
-    void branch32(Condition cond, RegisterID op1, Imm32 imm, Label target)
+    void branch32(RelationalCondition cond, RegisterID op1, TrustedImm32 imm, Label target)
     {
         branch32(cond, op1, imm).linkTo(target, this);
     }
 
-    void branch32(Condition cond, RegisterID left, Address right, Label target)
+    void branch32(RelationalCondition cond, RegisterID left, Address right, Label target)
     {
         branch32(cond, left, right).linkTo(target, this);
     }
 
-    void branch16(Condition cond, BaseIndex left, RegisterID right, Label target)
+    void branch16(RelationalCondition cond, BaseIndex left, RegisterID right, Label target)
     {
         branch16(cond, left, right).linkTo(target, this);
     }
     
-    void branchTestPtr(Condition cond, RegisterID reg, Label target)
+    void branchTestPtr(ResultCondition cond, RegisterID reg, Label target)
     {
         branchTestPtr(cond, reg).linkTo(target, this);
     }
@@ -144,17 +150,17 @@ public:
         add32(src, dest);
     }
 
-    void addPtr(Imm32 imm, RegisterID srcDest)
+    void addPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         add32(imm, srcDest);
     }
 
-    void addPtr(ImmPtr imm, RegisterID dest)
+    void addPtr(TrustedImmPtr imm, RegisterID dest)
     {
-        add32(Imm32(imm), dest);
+        add32(TrustedImm32(imm), dest);
     }
 
-    void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
+    void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         add32(imm, src, dest);
     }
@@ -164,7 +170,7 @@ public:
         and32(src, dest);
     }
 
-    void andPtr(Imm32 imm, RegisterID srcDest)
+    void andPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         and32(imm, srcDest);
     }
@@ -174,12 +180,12 @@ public:
         or32(src, dest);
     }
 
-    void orPtr(ImmPtr imm, RegisterID dest)
+    void orPtr(TrustedImmPtr imm, RegisterID dest)
     {
-        or32(Imm32(imm), dest);
+        or32(TrustedImm32(imm), dest);
     }
 
-    void orPtr(Imm32 imm, RegisterID dest)
+    void orPtr(TrustedImm32 imm, RegisterID dest)
     {
         or32(imm, dest);
     }
@@ -189,14 +195,14 @@ public:
         sub32(src, dest);
     }
     
-    void subPtr(Imm32 imm, RegisterID dest)
+    void subPtr(TrustedImm32 imm, RegisterID dest)
     {
         sub32(imm, dest);
     }
     
-    void subPtr(ImmPtr imm, RegisterID dest)
+    void subPtr(TrustedImmPtr imm, RegisterID dest)
     {
-        sub32(Imm32(imm), dest);
+        sub32(TrustedImm32(imm), dest);
     }
 
     void xorPtr(RegisterID src, RegisterID dest)
@@ -204,7 +210,7 @@ public:
         xor32(src, dest);
     }
 
-    void xorPtr(Imm32 imm, RegisterID srcDest)
+    void xorPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         xor32(imm, srcDest);
     }
@@ -229,10 +235,15 @@ public:
     {
         return load32WithAddressOffsetPatch(address, dest);
     }
+    
+    DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        return load32WithCompactAddressOffsetPatch(address, dest);
+    }
 
-    void setPtr(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
-        set32(cond, left, right, dest);
+        compare32(cond, left, right, dest);
     }
 
     void storePtr(RegisterID src, ImplicitAddress address)
@@ -250,14 +261,14 @@ public:
         store32(src, address);
     }
 
-    void storePtr(ImmPtr imm, ImplicitAddress address)
+    void storePtr(TrustedImmPtr imm, ImplicitAddress address)
     {
-        store32(Imm32(imm), address);
+        store32(TrustedImm32(imm), address);
     }
 
-    void storePtr(ImmPtr imm, void* address)
+    void storePtr(TrustedImmPtr imm, void* address)
     {
-        store32(Imm32(imm), address);
+        store32(TrustedImm32(imm), address);
     }
 
     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
@@ -266,73 +277,73 @@ public:
     }
 
 
-    Jump branchPtr(Condition cond, RegisterID left, RegisterID right)
+    Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         return branch32(cond, left, right);
     }
 
-    Jump branchPtr(Condition cond, RegisterID left, ImmPtr right)
+    Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
     {
-        return branch32(cond, left, Imm32(right));
+        return branch32(cond, left, TrustedImm32(right));
     }
 
-    Jump branchPtr(Condition cond, RegisterID left, Address right)
+    Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
     {
         return branch32(cond, left, right);
     }
 
-    Jump branchPtr(Condition cond, Address left, RegisterID right)
+    Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
     {
         return branch32(cond, left, right);
     }
 
-    Jump branchPtr(Condition cond, AbsoluteAddress left, RegisterID right)
+    Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         return branch32(cond, left, right);
     }
 
-    Jump branchPtr(Condition cond, Address left, ImmPtr right)
+    Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
     {
-        return branch32(cond, left, Imm32(right));
+        return branch32(cond, left, TrustedImm32(right));
     }
 
-    Jump branchPtr(Condition cond, AbsoluteAddress left, ImmPtr right)
+    Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, TrustedImmPtr right)
     {
-        return branch32(cond, left, Imm32(right));
+        return branch32(cond, left, TrustedImm32(right));
     }
 
-    Jump branchTestPtr(Condition cond, RegisterID reg, RegisterID mask)
+    Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         return branchTest32(cond, reg, mask);
     }
 
-    Jump branchTestPtr(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
         return branchTest32(cond, reg, mask);
     }
 
-    Jump branchTestPtr(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         return branchTest32(cond, address, mask);
     }
 
-    Jump branchTestPtr(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
         return branchTest32(cond, address, mask);
     }
 
 
-    Jump branchAddPtr(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         return branchAdd32(cond, src, dest);
     }
 
-    Jump branchSubPtr(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         return branchSub32(cond, imm, dest);
     }
     using MacroAssemblerBase::branchTest8;
-    Jump branchTest8(Condition cond, ExtendedAddress address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
     {
         return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
     }
index b5b20fa07d220f630746b93f396ea18d559e3d28..2db5df1f87148f365ee62a308202a91d672a353e 100644 (file)
@@ -57,7 +57,11 @@ static bool isVFPPresent()
     }
 #endif
 
+#if (COMPILER(RVCT) && defined(__TARGET_FPU_VFP)) || (COMPILER(GCC) && defined(__VFP_FP__))
+    return true;
+#else
     return false;
+#endif
 }
 
 const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();
index 1bbb0cce9e903b187f542c579f1fec8cc016a082..b365dce7b47af88f21c3dc4eebe5ab5eed8dd309 100644 (file)
@@ -41,8 +41,9 @@ class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> {
     COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes);
 public:
     typedef ARMRegisters::FPRegisterID FPRegisterID;
+    static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
 
-    enum Condition {
+    enum RelationalCondition {
         Equal = ARMAssembler::EQ,
         NotEqual = ARMAssembler::NE,
         Above = ARMAssembler::HI,
@@ -52,7 +53,10 @@ public:
         GreaterThan = ARMAssembler::GT,
         GreaterThanOrEqual = ARMAssembler::GE,
         LessThan = ARMAssembler::LT,
-        LessThanOrEqual = ARMAssembler::LE,
+        LessThanOrEqual = ARMAssembler::LE
+    };
+
+    enum ResultCondition {
         Overflow = ARMAssembler::VS,
         Signed = ARMAssembler::MI,
         Zero = ARMAssembler::EQ,
@@ -86,14 +90,14 @@ public:
         m_assembler.adds_r(dest, dest, src);
     }
 
-    void add32(Imm32 imm, Address address)
+    void add32(TrustedImm32 imm, Address address)
     {
         load32(address, ARMRegisters::S1);
         add32(imm, ARMRegisters::S1);
         store32(ARMRegisters::S1, address);
     }
 
-    void add32(Imm32 imm, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
     }
@@ -109,7 +113,7 @@ public:
         m_assembler.ands_r(dest, dest, src);
     }
 
-    void and32(Imm32 imm, RegisterID dest)
+    void and32(TrustedImm32 imm, RegisterID dest)
     {
         ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
         if (w & ARMAssembler::OP2_INV_IMM)
@@ -127,7 +131,7 @@ public:
         m_assembler.movs_r(dest, m_assembler.lsl_r(dest, ARMRegisters::S0));
     }
 
-    void lshift32(Imm32 imm, RegisterID dest)
+    void lshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
     }
@@ -141,7 +145,7 @@ public:
         m_assembler.muls_r(dest, dest, src);
     }
 
-    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+    void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         move(imm, ARMRegisters::S0);
         m_assembler.muls_r(dest, src, ARMRegisters::S0);
@@ -162,7 +166,7 @@ public:
         m_assembler.orrs_r(dest, dest, src);
     }
 
-    void or32(Imm32 imm, RegisterID dest)
+    void or32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
     }
@@ -176,7 +180,7 @@ public:
         m_assembler.movs_r(dest, m_assembler.asr_r(dest, ARMRegisters::S0));
     }
 
-    void rshift32(Imm32 imm, RegisterID dest)
+    void rshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
     }
@@ -190,7 +194,7 @@ public:
         m_assembler.movs_r(dest, m_assembler.lsr_r(dest, ARMRegisters::S0));
     }
     
-    void urshift32(Imm32 imm, RegisterID dest)
+    void urshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
     }
@@ -200,12 +204,12 @@ public:
         m_assembler.subs_r(dest, dest, src);
     }
 
-    void sub32(Imm32 imm, RegisterID dest)
+    void sub32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
     }
 
-    void sub32(Imm32 imm, Address address)
+    void sub32(TrustedImm32 imm, Address address)
     {
         load32(address, ARMRegisters::S1);
         sub32(imm, ARMRegisters::S1);
@@ -223,11 +227,22 @@ public:
         m_assembler.eors_r(dest, dest, src);
     }
 
-    void xor32(Imm32 imm, RegisterID dest)
+    void xor32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
     }
 
+    void countLeadingZeros32(RegisterID src, RegisterID dest)
+    {
+#if WTF_ARM_ARCH_AT_LEAST(5)
+        m_assembler.clz_r(dest, src);
+#else
+        UNUSED_PARAM(src);
+        UNUSED_PARAM(dest);
+        ASSERT_NOT_REACHED();
+#endif
+    }
+
     void load8(ImplicitAddress address, RegisterID dest)
     {
         m_assembler.dataTransfer32(true, dest, address.base, address.offset, true);
@@ -259,29 +274,26 @@ public:
         m_assembler.dtr_ur(true, dest, address.base, ARMRegisters::S0);
         return dataLabel;
     }
-
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+    
+    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
     {
-        Label label(this);
-        load32(address, dest);
-        return label;
+        DataLabelCompact dataLabel(this);
+        load32WithAddressOffsetPatch(address, dest);
+        return dataLabel;
     }
 
     void load16(BaseIndex address, RegisterID dest)
     {
-        m_assembler.add_r(ARMRegisters::S0, address.base, m_assembler.lsl(address.index, address.scale));
-        if (address.offset>=0)
-            m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset));
-        else
-            m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
+        m_assembler.add_r(ARMRegisters::S1, address.base, m_assembler.lsl(address.index, address.scale));
+        load16(Address(ARMRegisters::S1, address.offset), dest);
     }
     
     void load16(ImplicitAddress address, RegisterID dest)
     {
         if (address.offset >= 0)
-            m_assembler.ldrh_u(dest, address.base, ARMAssembler::getOp2Byte(address.offset));
+            m_assembler.ldrh_u(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(address.offset, ARMRegisters::S0));
         else
-            m_assembler.ldrh_d(dest, address.base, ARMAssembler::getOp2Byte(-address.offset));   
+            m_assembler.ldrh_d(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(-address.offset, ARMRegisters::S0));
     }
 
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
@@ -302,7 +314,7 @@ public:
         m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
     }
 
-    void store32(Imm32 imm, ImplicitAddress address)
+    void store32(TrustedImm32 imm, ImplicitAddress address)
     {
         if (imm.m_isPointer)
             m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
@@ -317,7 +329,7 @@ public:
         m_assembler.dtr_u(false, src, ARMRegisters::S0, 0);
     }
 
-    void store32(Imm32 imm, void* address)
+    void store32(TrustedImm32 imm, void* address)
     {
         m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
         if (imm.m_isPointer)
@@ -343,13 +355,13 @@ public:
         push(ARMRegisters::S1);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         move(imm, ARMRegisters::S0);
         push(ARMRegisters::S0);
     }
 
-    void move(Imm32 imm, RegisterID dest)
+    void move(TrustedImm32 imm, RegisterID dest)
     {
         if (imm.m_isPointer)
             m_assembler.ldr_un_imm(dest, imm.m_value);
@@ -362,9 +374,9 @@ public:
         m_assembler.mov_r(dest, src);
     }
 
-    void move(ImmPtr imm, RegisterID dest)
+    void move(TrustedImmPtr imm, RegisterID dest)
     {
-        move(Imm32(imm), dest);
+        move(TrustedImm32(imm), dest);
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
@@ -386,59 +398,64 @@ public:
             move(src, dest);
     }
 
-    Jump branch8(Condition cond, Address left, Imm32 right)
+    Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         load8(left, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
+    Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
     {
         m_assembler.cmp_r(left, right);
         return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
     }
 
-    Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0)
+    Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0)
     {
         if (right.m_isPointer) {
             m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
             m_assembler.cmp_r(left, ARMRegisters::S0);
-        } else
-            m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
+        } else {
+            ARMWord tmp = m_assembler.getOp2(-right.m_value);
+            if (tmp != ARMAssembler::INVALID_IMM)
+                m_assembler.cmn_r(left, tmp);
+            else
+                m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
+        }
         return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
     }
 
-    Jump branch32(Condition cond, RegisterID left, Address right)
+    Jump branch32(RelationalCondition cond, RegisterID left, Address right)
     {
         load32(right, ARMRegisters::S1);
         return branch32(cond, left, ARMRegisters::S1);
     }
 
-    Jump branch32(Condition cond, Address left, RegisterID right)
+    Jump branch32(RelationalCondition cond, Address left, RegisterID right)
     {
         load32(left, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch32(Condition cond, Address left, Imm32 right)
+    Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         load32(left, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         load32(left, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         load32WithUnalignedHalfWords(left, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
     {
         UNUSED_PARAM(cond);
         UNUSED_PARAM(left);
@@ -447,7 +464,7 @@ public:
         return jump();
     }
 
-    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         load16(left, ARMRegisters::S0);
         move(right, ARMRegisters::S1);
@@ -455,20 +472,20 @@ public:
         return m_assembler.jmp(ARMCondition(cond));
     }
 
-    Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load8(address, ARMRegisters::S1);
         return branchTest32(cond, ARMRegisters::S1, mask);
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+    Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         m_assembler.tst_r(reg, mask);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true);
@@ -479,13 +496,13 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load32(address, ARMRegisters::S1);
         return branchTest32(cond, ARMRegisters::S1, mask);
     }
 
-    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load32(address, ARMRegisters::S1);
         return branchTest32(cond, ARMRegisters::S1, mask);
@@ -506,14 +523,14 @@ public:
         load32(address, ARMRegisters::pc);
     }
 
-    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         add32(src, dest);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         add32(imm, dest);
@@ -530,7 +547,7 @@ public:
         m_assembler.cmp_r(ARMRegisters::S1, m_assembler.asr(dest, 31));
     }
 
-    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -542,7 +559,7 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -555,28 +572,28 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         sub32(src, dest);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         sub32(imm, dest);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchNeg32(Condition cond, RegisterID srcDest)
+    Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         neg32(srcDest);
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
-    Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
         or32(src, dest);
@@ -602,9 +619,7 @@ public:
 
     Call call(RegisterID target)
     {
-        m_assembler.blx(target);
-        JmpSrc jmpSrc;
-        return Call(jmpSrc, Call::None);
+        return Call(m_assembler.blx(target), Call::None);
     }
 
     void call(Address address)
@@ -617,62 +632,48 @@ public:
         m_assembler.bx(linkRegister);
     }
 
-    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
     {
         m_assembler.cmp_r(left, right);
         m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
         m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
     }
 
-    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
         m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
         m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
     }
 
-    void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
-    {
-        // ARM doesn't have byte registers
-        set32(cond, left, right, dest);
-    }
-
-    void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
-    {
-        // ARM doesn't have byte registers
-        load32(left, ARMRegisters::S1);
-        set32(cond, ARMRegisters::S1, right, dest);
-    }
-
-    void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
     {
-        // ARM doesn't have byte registers
-        set32(cond, left, right, dest);
-    }
-
-    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
-    {
-        load32(address, ARMRegisters::S1);
         if (mask.m_value == -1)
-            m_assembler.cmp_r(0, ARMRegisters::S1);
+            m_assembler.cmp_r(0, reg);
         else
-            m_assembler.tst_r(ARMRegisters::S1, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
+            m_assembler.tst_r(reg, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
         m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
         m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
     }
 
-    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
+    {
+        load32(address, ARMRegisters::S1);
+        test32(cond, ARMRegisters::S1, mask, dest);
+    }
+
+    void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
-        // ARM doesn't have byte registers
-        setTest32(cond, address, mask, dest);
+        load8(address, ARMRegisters::S1);
+        test32(cond, ARMRegisters::S1, mask, dest);
     }
 
-    void add32(Imm32 imm, RegisterID src, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
     }
 
-    void add32(Imm32 imm, AbsoluteAddress address)
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
         m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
@@ -681,7 +682,7 @@ public:
         m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
         m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
@@ -690,24 +691,33 @@ public:
         m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
     }
 
-    void load32(void* address, RegisterID dest)
+    void load32(const void* address, RegisterID dest)
     {
         m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
         m_assembler.dtr_u(true, dest, ARMRegisters::S0, 0);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         load32(left.m_ptr, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
     {
         load32(left.m_ptr, ARMRegisters::S1);
         return branch32(cond, ARMRegisters::S1, right);
     }
 
+    void relativeTableJump(RegisterID index, int scale)
+    {
+        ASSERT(scale >= 0 && scale <= 31);
+        m_assembler.add_r(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(index, scale));
+
+        // NOP the default prefetching
+        m_assembler.mov_r(ARMRegisters::r0, ARMRegisters::r0);
+    }
+
     Call call()
     {
 #if WTF_ARM_ARCH_AT_LEAST(5)
@@ -730,21 +740,21 @@ public:
         return Call::fromTailJump(oldJump);
     }
 
-    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         DataLabelPtr dataLabel(this);
         m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
         return dataLabel;
     }
 
-    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1);
         Jump jump = branch32(cond, left, ARMRegisters::S1, true);
         return jump;
     }
 
-    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         load32(left, ARMRegisters::S1);
         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
@@ -752,7 +762,7 @@ public:
         return jump;
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
         store32(ARMRegisters::S1, address);
@@ -761,7 +771,7 @@ public:
 
     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
     {
-        return storePtrWithPatch(ImmPtr(0), address);
+        return storePtrWithPatch(TrustedImmPtr(0), address);
     }
 
     // Floating point operators
@@ -772,7 +782,7 @@ public:
 
     bool supportsFloatingPointTruncate() const
     {
-        return false;
+        return s_isVFPPresent;
     }
 
     bool supportsFloatingPointSqrt() const
@@ -798,7 +808,7 @@ public:
 
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.faddd_r(dest, dest, src);
+        m_assembler.vadd_f64_r(dest, dest, src);
     }
 
     void addDouble(Address src, FPRegisterID dest)
@@ -809,7 +819,7 @@ public:
 
     void divDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.fdivd_r(dest, dest, src);
+        m_assembler.vdiv_f64_r(dest, dest, src);
     }
 
     void divDouble(Address src, FPRegisterID dest)
@@ -821,7 +831,7 @@ public:
 
     void subDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.fsubd_r(dest, dest, src);
+        m_assembler.vsub_f64_r(dest, dest, src);
     }
 
     void subDouble(Address src, FPRegisterID dest)
@@ -832,7 +842,7 @@ public:
 
     void mulDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.fmuld_r(dest, dest, src);
+        m_assembler.vmul_f64_r(dest, dest, src);
     }
 
     void mulDouble(Address src, FPRegisterID dest)
@@ -843,13 +853,13 @@ public:
 
     void sqrtDouble(FPRegisterID src, FPRegisterID dest)
     {
-        m_assembler.fsqrtd_r(dest, src);
+        m_assembler.vsqrt_f64_r(dest, src);
     }
 
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
-        m_assembler.fmsr_r(dest, src);
-        m_assembler.fsitod_r(dest, dest);
+        m_assembler.vmov_vfp_r(dest << 1, src);
+        m_assembler.vcvt_f64_s32_r(dest, dest << 1);
     }
 
     void convertInt32ToDouble(Address src, FPRegisterID dest)
@@ -871,8 +881,8 @@ public:
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
-        m_assembler.fcmpd_r(left, right);
-        m_assembler.fmstat();
+        m_assembler.vcmp_f64_r(left, right);
+        m_assembler.vmrs_apsr();
         if (cond & DoubleConditionBitSpecial)
             m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
         return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
@@ -881,13 +891,17 @@ public:
     // Truncates 'src' to an integer, and places the resulting 'dest'.
     // If the result is not representable as a 32 bit value, branch.
     // May also branch for some values that are representable in 32 bits
-    // (specifically, in this case, INT_MIN).
+    // (specifically, in this case, INT_MIN and INT_MAX).
     Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
     {
-        UNUSED_PARAM(src);
-        UNUSED_PARAM(dest);
-        ASSERT_NOT_REACHED();
-        return jump();
+        m_assembler.vcvtr_s32_f64_r(ARMRegisters::SD0 << 1, src);
+        // If VCVTR.S32.F64 can't fit the result into a 32-bit
+        // integer, it saturates at INT_MAX or INT_MIN. Testing this is
+        // probably quicker than testing FPSCR for exception.
+        m_assembler.vmov_arm_r(dest, ARMRegisters::SD0 << 1);
+        m_assembler.sub_r(ARMRegisters::S0, dest, ARMAssembler::getOp2(0x80000000));
+        m_assembler.cmn_r(ARMRegisters::S0, ARMAssembler::getOp2(1), ARMCondition(NotEqual));
+        return Jump(m_assembler.jmp(ARMCondition(Equal)));
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.
@@ -896,11 +910,11 @@ public:
     // (specifically, in this case, 0).
     void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
     {
-        m_assembler.ftosid_r(ARMRegisters::SD0, src);
-        m_assembler.fmrs_r(dest, ARMRegisters::SD0);
+        m_assembler.vcvt_s32_f64_r(ARMRegisters::SD0 << 1, src);
+        m_assembler.vmov_arm_r(dest, ARMRegisters::SD0 << 1);
 
         // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
-        m_assembler.fsitod_r(ARMRegisters::SD0, ARMRegisters::SD0);
+        m_assembler.vcvt_f64_s32_r(ARMRegisters::SD0, ARMRegisters::SD0 << 1);
         failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0));
 
         // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
@@ -921,8 +935,18 @@ public:
         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
     }
 
+    void nop()
+    {
+        m_assembler.nop();
+    }
+
 protected:
-    ARMAssembler::Condition ARMCondition(Condition cond)
+    ARMAssembler::Condition ARMCondition(RelationalCondition cond)
+    {
+        return static_cast<ARMAssembler::Condition>(cond);
+    }
+
+    ARMAssembler::Condition ARMCondition(ResultCondition cond)
     {
         return static_cast<ARMAssembler::Condition>(cond);
     }
@@ -967,9 +991,9 @@ protected:
                 prepareCall();
                 m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
             } else {
-                ARMWord reg = m_assembler.getImm(offset, tmpReg);
+                m_assembler.moveImm(offset, tmpReg);
                 prepareCall();
-                m_assembler.dtr_ur(true, targetReg, base, reg);
+                m_assembler.dtr_ur(true, targetReg, base, tmpReg);
             }
         } else  {
             offset = -offset;
@@ -981,9 +1005,9 @@ protected:
                 prepareCall();
                 m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
             } else {
-                ARMWord reg = m_assembler.getImm(offset, tmpReg);
+                m_assembler.moveImm(offset, tmpReg);
                 prepareCall();
-                m_assembler.dtr_dr(true, targetReg, base, reg);
+                m_assembler.dtr_dr(true, targetReg, base, tmpReg);
             }
         }
 #if WTF_ARM_ARCH_AT_LEAST(5)
index e3e928d6eb8b96050ec9a7ee44183628d544e0de..70b2552363f79a321392f83dd0e28d5f6c3b42ed 100644 (file)
@@ -48,6 +48,9 @@ public:
     typedef ARMv7Assembler::LinkRecord LinkRecord;
     typedef ARMv7Assembler::JumpType JumpType;
     typedef ARMv7Assembler::JumpLinkType JumpLinkType;
+    // Magic number is the biggest useful offset we can get on ARMv7 with
+    // a LDR_imm_T2 encoding
+    static const int MaximumCompactPtrAlignedAddressOffset = 124;
 
     MacroAssemblerARMv7()
         : m_inUninterruptedSequence(false)
@@ -100,7 +103,7 @@ public:
 
     static const Scale ScalePtr = TimesFour;
 
-    enum Condition {
+    enum RelationalCondition {
         Equal = ARMv7Assembler::ConditionEQ,
         NotEqual = ARMv7Assembler::ConditionNE,
         Above = ARMv7Assembler::ConditionHI,
@@ -110,12 +113,16 @@ public:
         GreaterThan = ARMv7Assembler::ConditionGT,
         GreaterThanOrEqual = ARMv7Assembler::ConditionGE,
         LessThan = ARMv7Assembler::ConditionLT,
-        LessThanOrEqual = ARMv7Assembler::ConditionLE,
+        LessThanOrEqual = ARMv7Assembler::ConditionLE
+    };
+
+    enum ResultCondition {
         Overflow = ARMv7Assembler::ConditionVS,
         Signed = ARMv7Assembler::ConditionMI,
         Zero = ARMv7Assembler::ConditionEQ,
         NonZero = ARMv7Assembler::ConditionNE
     };
+
     enum DoubleCondition {
         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
         DoubleEqual = ARMv7Assembler::ConditionEQ,
@@ -139,7 +146,7 @@ public:
     // Integer arithmetic operations:
     //
     // Operations are typically two operand - operation(source, srcDst)
-    // For many operations the source may be an Imm32, the srcDst operand
+    // For many operations the source may be an TrustedImm32, the srcDst operand
     // may often be a memory location (explictly described using an Address
     // object).
 
@@ -148,12 +155,12 @@ public:
         m_assembler.add(dest, dest, src);
     }
 
-    void add32(Imm32 imm, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID dest)
     {
         add32(imm, dest, dest);
     }
 
-    void add32(Imm32 imm, RegisterID src, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
         if (armImm.isValid())
@@ -164,7 +171,7 @@ public:
         }
     }
 
-    void add32(Imm32 imm, Address address)
+    void add32(TrustedImm32 imm, Address address)
     {
         load32(address, dataTempRegister);
 
@@ -187,7 +194,7 @@ public:
         add32(dataTempRegister, dest);
     }
 
-    void add32(Imm32 imm, AbsoluteAddress address)
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
         load32(address.m_ptr, dataTempRegister);
 
@@ -209,7 +216,7 @@ public:
         m_assembler.ARM_and(dest, dest, src);
     }
 
-    void and32(Imm32 imm, RegisterID dest)
+    void and32(TrustedImm32 imm, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
@@ -220,6 +227,11 @@ public:
         }
     }
 
+    void countLeadingZeros32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.clz(dest, src);
+    }
+
     void lshift32(RegisterID shift_amount, RegisterID dest)
     {
         // Clamp the shift to the range 0..31
@@ -230,7 +242,7 @@ public:
         m_assembler.lsl(dest, dest, dataTempRegister);
     }
 
-    void lshift32(Imm32 imm, RegisterID dest)
+    void lshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.lsl(dest, dest, imm.m_value & 0x1f);
     }
@@ -240,7 +252,7 @@ public:
         m_assembler.smull(dest, dataTempRegister, dest, src);
     }
 
-    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+    void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         move(imm, dataTempRegister);
         m_assembler.smull(dest, dataTempRegister, src, dataTempRegister);
@@ -261,7 +273,7 @@ public:
         m_assembler.orr(dest, dest, src);
     }
 
-    void or32(Imm32 imm, RegisterID dest)
+    void or32(TrustedImm32 imm, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
@@ -282,7 +294,7 @@ public:
         m_assembler.asr(dest, dest, dataTempRegister);
     }
 
-    void rshift32(Imm32 imm, RegisterID dest)
+    void rshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.asr(dest, dest, imm.m_value & 0x1f);
     }
@@ -297,7 +309,7 @@ public:
         m_assembler.lsr(dest, dest, dataTempRegister);
     }
     
-    void urshift32(Imm32 imm, RegisterID dest)
+    void urshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.lsr(dest, dest, imm.m_value & 0x1f);
     }
@@ -307,7 +319,7 @@ public:
         m_assembler.sub(dest, dest, src);
     }
 
-    void sub32(Imm32 imm, RegisterID dest)
+    void sub32(TrustedImm32 imm, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value);
         if (armImm.isValid())
@@ -318,7 +330,7 @@ public:
         }
     }
 
-    void sub32(Imm32 imm, Address address)
+    void sub32(TrustedImm32 imm, Address address)
     {
         load32(address, dataTempRegister);
 
@@ -341,7 +353,7 @@ public:
         sub32(dataTempRegister, dest);
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
         load32(address.m_ptr, dataTempRegister);
 
@@ -363,7 +375,7 @@ public:
         m_assembler.eor(dest, dest, src);
     }
 
-    void xor32(Imm32 imm, RegisterID dest)
+    void xor32(TrustedImm32 imm, RegisterID dest)
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
@@ -378,7 +390,7 @@ public:
     // Memory access operations:
     //
     // Loads are of the form load(address, destination) and stores of the form
-    // store(source, address).  The source for a store may be an Imm32.  Address
+    // store(source, address).  The source for a store may be an TrustedImm32.  Address
     // operand objects to loads and store will be implicitly constructed if a
     // register is passed.
 
@@ -455,9 +467,9 @@ public:
         load32(setupArmAddress(address), dest);
     }
 
-    void load32(void* address, RegisterID dest)
+    void load32(const void* address, RegisterID dest)
     {
-        move(ImmPtr(address), addressTempRegister);
+        move(TrustedImmPtr(address), addressTempRegister);
         m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
     }
 
@@ -468,16 +480,18 @@ public:
 
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
-        DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
+        DataLabel32 label = moveWithPatch(TrustedImm32(address.offset), dataTempRegister);
         load32(ArmAddress(address.base, dataTempRegister), dest);
         return label;
     }
-
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+    
+    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
     {
-        Label label(this);
-        moveFixedWidthEncoding(Imm32(address.offset), dataTempRegister);
-        load32(ArmAddress(address.base, dataTempRegister), dest);
+        DataLabelCompact label(this);
+        ASSERT(address.offset >= 0);
+        ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset);
+        ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7());
+        m_assembler.ldrCompact(dest, address.base, ARMThumbImmediate::makeUInt12(address.offset));
         return label;
     }
 
@@ -492,14 +506,14 @@ public:
         if (armImm.isValid())
             m_assembler.ldrh(dest, address.base, armImm);
         else {
-            move(Imm32(address.offset), dataTempRegister);
+            move(TrustedImm32(address.offset), dataTempRegister);
             m_assembler.ldrh(dest, address.base, dataTempRegister);
         }
     }
 
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
-        DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister);
+        DataLabel32 label = moveWithPatch(TrustedImm32(address.offset), dataTempRegister);
         store32(src, ArmAddress(address.base, dataTempRegister));
         return label;
     }
@@ -514,19 +528,19 @@ public:
         store32(src, setupArmAddress(address));
     }
 
-    void store32(Imm32 imm, ImplicitAddress address)
+    void store32(TrustedImm32 imm, ImplicitAddress address)
     {
         move(imm, dataTempRegister);
         store32(dataTempRegister, setupArmAddress(address));
     }
 
-    void store32(RegisterID src, void* address)
+    void store32(RegisterID src, const void* address)
     {
-        move(ImmPtr(address), addressTempRegister);
+        move(TrustedImmPtr(address), addressTempRegister);
         m_assembler.str(src, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
     }
 
-    void store32(Imm32 imm, void* address)
+    void store32(TrustedImm32 imm, const void* address)
     {
         move(imm, dataTempRegister);
         store32(dataTempRegister, address);
@@ -561,7 +575,7 @@ public:
 
         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
         if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) {
-            add32(Imm32(offset), base, addressTempRegister);
+            add32(TrustedImm32(offset), base, addressTempRegister);
             base = addressTempRegister;
             offset = 0;
         }
@@ -571,7 +585,7 @@ public:
 
     void loadDouble(const void* address, FPRegisterID dest)
     {
-        move(ImmPtr(address), addressTempRegister);
+        move(TrustedImmPtr(address), addressTempRegister);
         m_assembler.vldr(dest, addressTempRegister, 0);
     }
 
@@ -582,7 +596,7 @@ public:
 
         // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2.
         if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) {
-            add32(Imm32(offset), base, addressTempRegister);
+            add32(TrustedImm32(offset), base, addressTempRegister);
             base = addressTempRegister;
             offset = 0;
         }
@@ -672,7 +686,7 @@ public:
             Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE);
             unordered.link(this);
             // We get here if either unordered or equal.
-            Jump result = makeJump();
+            Jump result = jump();
             notEqual.link(this);
             return result;
         }
@@ -720,7 +734,7 @@ public:
         Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE);
         unordered.link(this);
         // We get here if either unordered or equal.
-        Jump result = makeJump();
+        Jump result = jump();
         notEqual.link(this);
         return result;
     }
@@ -751,7 +765,7 @@ public:
         push(dataTempRegister);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         move(imm, dataTempRegister);
         push(dataTempRegister);
@@ -761,7 +775,7 @@ public:
     //
     // Move values in registers.
 
-    void move(Imm32 imm, RegisterID dest)
+    void move(TrustedImm32 imm, RegisterID dest)
     {
         uint32_t value = imm.m_value;
 
@@ -787,9 +801,9 @@ public:
         m_assembler.mov(dest, src);
     }
 
-    void move(ImmPtr imm, RegisterID dest)
+    void move(TrustedImmPtr imm, RegisterID dest)
     {
-        move(Imm32(imm), dest);
+        move(TrustedImm32(imm), dest);
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
@@ -811,6 +825,10 @@ public:
             move(src, dest);
     }
 
+    void nop()
+    {
+        m_assembler.nop();
+    }
 
     // Forwards / external control flow operations:
     //
@@ -824,7 +842,7 @@ public:
     // used (representing the names 'below' and 'above').
     //
     // Operands to the comparision are provided in the expected order, e.g.
-    // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
+    // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
     // treated as a signed 32bit value, is less than or equal to 5.
     //
     // jz and jnz test whether the first operand is equal to zero, and take
@@ -832,7 +850,7 @@ public:
 private:
 
     // Should we be using TEQ for equal/not-equal?
-    void compare32(RegisterID left, Imm32 right)
+    void compare32(RegisterID left, TrustedImm32 right)
     {
         int32_t imm = right.m_value;
         if (!imm)
@@ -844,13 +862,13 @@ private:
             else if ((armImm = ARMThumbImmediate::makeEncodedImm(-imm)).isValid())
                 m_assembler.cmn(left, armImm);
             else {
-                move(Imm32(imm), dataTempRegister);
+                move(TrustedImm32(imm), dataTempRegister);
                 m_assembler.cmp(left, dataTempRegister);
             }
         }
     }
 
-    void test32(RegisterID reg, Imm32 mask)
+    void test32(RegisterID reg, TrustedImm32 mask)
     {
         int32_t imm = mask.m_value;
 
@@ -868,65 +886,65 @@ private:
     }
 
 public:
-    Jump branch32(Condition cond, RegisterID left, RegisterID right)
+    Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         m_assembler.cmp(left, right);
         return Jump(makeBranch(cond));
     }
 
-    Jump branch32(Condition cond, RegisterID left, Imm32 right)
+    Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
         compare32(left, right);
         return Jump(makeBranch(cond));
     }
 
-    Jump branch32(Condition cond, RegisterID left, Address right)
+    Jump branch32(RelationalCondition cond, RegisterID left, Address right)
     {
         load32(right, dataTempRegister);
         return branch32(cond, left, dataTempRegister);
     }
 
-    Jump branch32(Condition cond, Address left, RegisterID right)
+    Jump branch32(RelationalCondition cond, Address left, RegisterID right)
     {
         load32(left, dataTempRegister);
         return branch32(cond, dataTempRegister, right);
     }
 
-    Jump branch32(Condition cond, Address left, Imm32 right)
+    Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
         load32(left, addressTempRegister);
         return branch32(cond, addressTempRegister, right);
     }
 
-    Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
         load32(left, addressTempRegister);
         return branch32(cond, addressTempRegister, right);
     }
 
-    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
         load32WithUnalignedHalfWords(left, addressTempRegister);
         return branch32(cond, addressTempRegister, right);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         load32(left.m_ptr, dataTempRegister);
         return branch32(cond, dataTempRegister, right);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
     {
         // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
         load32(left.m_ptr, addressTempRegister);
         return branch32(cond, addressTempRegister, right);
     }
 
-    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
     {
         load16(left, dataTempRegister);
         m_assembler.lsl(addressTempRegister, right, 16);
@@ -934,87 +952,76 @@ public:
         return branch32(cond, dataTempRegister, addressTempRegister);
     }
 
-    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
         load16(left, addressTempRegister);
         m_assembler.lsl(addressTempRegister, addressTempRegister, 16);
-        return branch32(cond, addressTempRegister, Imm32(right.m_value << 16));
+        return branch32(cond, addressTempRegister, TrustedImm32(right.m_value << 16));
     }
 
-    Jump branch8(Condition cond, RegisterID left, Imm32 right)
+    Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
         compare32(left, right);
         return Jump(makeBranch(cond));
     }
 
-    Jump branch8(Condition cond, Address left, Imm32 right)
+    Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         // use addressTempRegister incase the branch8 we call uses dataTempRegister. :-/
         load8(left, addressTempRegister);
         return branch8(cond, addressTempRegister, right);
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+    Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         m_assembler.tst(reg, mask);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         test32(reg, mask);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         // use addressTempRegister incase the branchTest32 we call uses dataTempRegister. :-/
         load32(address, addressTempRegister);
         return branchTest32(cond, addressTempRegister, mask);
     }
 
-    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         // use addressTempRegister incase the branchTest32 we call uses dataTempRegister. :-/
         load32(address, addressTempRegister);
         return branchTest32(cond, addressTempRegister, mask);
     }
 
-    Jump branchTest8(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         test32(reg, mask);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/
         load8(address, addressTempRegister);
         return branchTest8(cond, addressTempRegister, mask);
     }
 
-    Jump jump()
-    {
-        return Jump(makeJump());
-    }
-
     void jump(RegisterID target)
     {
-        m_assembler.bx(target, ARMv7Assembler::JumpFixed);
+        m_assembler.bx(target);
     }
 
     // Address is a memory location containing the address to jump to
     void jump(Address address)
     {
         load32(address, dataTempRegister);
-        m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed);
+        m_assembler.bx(dataTempRegister);
     }
 
 
@@ -1028,16 +1035,14 @@ public:
     // * jo operations branch if the (signed) arithmetic
     //   operation caused an overflow to occur.
     
-    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         m_assembler.add_S(dest, dest, src);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
             m_assembler.add_S(dest, dest, armImm);
@@ -1048,40 +1053,43 @@ public:
         return Jump(makeBranch(cond));
     }
 
-    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
     {
-        ASSERT_UNUSED(cond, cond == Overflow);
-        m_assembler.smull(dest, dataTempRegister, dest, src);
-        m_assembler.asr(addressTempRegister, dest, 31);
-        return branch32(NotEqual, addressTempRegister, dataTempRegister);
+        m_assembler.smull(dest, dataTempRegister, src1, src2);
+
+        if (cond == Overflow) {
+            m_assembler.asr(addressTempRegister, dest, 31);
+            return branch32(NotEqual, addressTempRegister, dataTempRegister);
+        }
+
+        return branchTest32(cond, dest);
     }
 
-    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        return branchMul32(cond, src, dest, dest);
+    }
+
+    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
-        ASSERT_UNUSED(cond, cond == Overflow);
         move(imm, dataTempRegister);
-        m_assembler.smull(dest, dataTempRegister, src, dataTempRegister);
-        m_assembler.asr(addressTempRegister, dest, 31);
-        return branch32(NotEqual, addressTempRegister, dataTempRegister);
+        return branchMul32(cond, dataTempRegister, src, dest);
     }
 
-    Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
         m_assembler.orr_S(dest, dest, src);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         m_assembler.sub_S(dest, dest, src);
         return Jump(makeBranch(cond));
     }
 
-    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
             m_assembler.sub_S(dest, dest, armImm);
@@ -1092,6 +1100,18 @@ public:
         return Jump(makeBranch(cond));
     }
     
+    void relativeTableJump(RegisterID index, int scale)
+    {
+        ASSERT(scale >= 0 && scale <= 31);
+
+        // dataTempRegister will point after the jump if index register contains zero
+        move(ARMRegisters::pc, dataTempRegister);
+        m_assembler.add(dataTempRegister, dataTempRegister, ARMThumbImmediate::makeEncodedImm(9));
+
+        ShiftTypeAndAmount shift(SRType_LSL, scale);
+        m_assembler.add(dataTempRegister, dataTempRegister, index, shift);
+        jump(dataTempRegister);
+    }
 
     // Miscellaneous operations:
 
@@ -1100,35 +1120,35 @@ public:
         m_assembler.bkpt(0);
     }
 
-    Call nearCall()
+    ALWAYS_INLINE Call nearCall()
     {
-        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
-        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::LinkableNear);
+        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
+        return Call(m_assembler.blx(dataTempRegister), Call::LinkableNear);
     }
 
-    Call call()
+    ALWAYS_INLINE Call call()
     {
-        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
-        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable);
+        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
+        return Call(m_assembler.blx(dataTempRegister), Call::Linkable);
     }
 
-    Call call(RegisterID target)
+    ALWAYS_INLINE Call call(RegisterID target)
     {
-        return Call(m_assembler.blx(target, ARMv7Assembler::JumpFixed), Call::None);
+        return Call(m_assembler.blx(target), Call::None);
     }
 
-    Call call(Address address)
+    ALWAYS_INLINE Call call(Address address)
     {
         load32(address, dataTempRegister);
-        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::None);
+        return Call(m_assembler.blx(dataTempRegister), Call::None);
     }
 
-    void ret()
+    ALWAYS_INLINE void ret()
     {
-        m_assembler.bx(linkRegister, ARMv7Assembler::JumpFixed);
+        m_assembler.bx(linkRegister);
     }
 
-    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
     {
         m_assembler.cmp(left, right);
         m_assembler.it(armV7Condition(cond), false);
@@ -1136,13 +1156,13 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
-    void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
+    void compare32(RelationalCondition cond, Address left, RegisterID right, RegisterID dest)
     {
         load32(left, dataTempRegister);
-        set32(cond, dataTempRegister, right, dest);
+        compare32(cond, dataTempRegister, right, dest);
     }
 
-    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         compare32(left, right);
         m_assembler.it(armV7Condition(cond), false);
@@ -1150,26 +1170,11 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
-    void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
-    {
-        set32(cond, left, right, dest);
-    }
-
-    void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
-    {
-        set32(cond, left, right, dest);
-    }
-
-    void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
-    {
-        set32(cond, left, right, dest);
-    }
-
     // FIXME:
     // The mask should be optional... paerhaps the argument order should be
     // dest-src, operations always have a dest? ... possibly not true, considering
     // asm ops like test, or pseudo ops like pop().
-    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
         load32(address, dataTempRegister);
         test32(dataTempRegister, mask);
@@ -1178,7 +1183,7 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
-    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
         load8(address, dataTempRegister);
         test32(dataTempRegister, mask);
@@ -1187,48 +1192,48 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
-    DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst)
+    ALWAYS_INLINE DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dst)
     {
         moveFixedWidthEncoding(imm, dst);
         return DataLabel32(this);
     }
 
-    DataLabelPtr moveWithPatch(ImmPtr imm, RegisterID dst)
+    ALWAYS_INLINE DataLabelPtr moveWithPatch(TrustedImmPtr imm, RegisterID dst)
     {
-        moveFixedWidthEncoding(Imm32(imm), dst);
+        moveFixedWidthEncoding(TrustedImm32(imm), dst);
         return DataLabelPtr(this);
     }
 
-    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    ALWAYS_INLINE Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
         return branch32(cond, left, dataTempRegister);
     }
 
-    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    ALWAYS_INLINE Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         load32(left, addressTempRegister);
         dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
         return branch32(cond, addressTempRegister, dataTempRegister);
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    ALWAYS_INLINE DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister);
         store32(dataTempRegister, address);
         return label;
     }
-    DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(ImmPtr(0), address); }
+    ALWAYS_INLINE DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
 
 
-    Call tailRecursiveCall()
+    ALWAYS_INLINE Call tailRecursiveCall()
     {
         // Like a normal call, but don't link.
-        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
-        return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable);
+        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
+        return Call(m_assembler.bx(dataTempRegister), Call::Linkable);
     }
 
-    Call makeTailRecursiveCall(Jump oldJump)
+    ALWAYS_INLINE Call makeTailRecursiveCall(Jump oldJump)
     {
         oldJump.link(this);
         return tailRecursiveCall();
@@ -1246,20 +1251,21 @@ protected:
         return m_inUninterruptedSequence;
     }
 
-    ARMv7Assembler::JmpSrc makeJump()
+    ALWAYS_INLINE Jump jump()
     {
-        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
-        return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition);
+        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
+        return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition);
     }
 
-    ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond)
+    ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond)
     {
         m_assembler.it(cond, true, true);
-        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
-        return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond);
+        moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister);
+        return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond);
     }
-    ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
-    ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); }
+    ALWAYS_INLINE Jump makeBranch(RelationalCondition cond) { return makeBranch(armV7Condition(cond)); }
+    ALWAYS_INLINE Jump makeBranch(ResultCondition cond) { return makeBranch(armV7Condition(cond)); }
+    ALWAYS_INLINE Jump makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); }
 
     ArmAddress setupArmAddress(BaseIndex address)
     {
@@ -1268,7 +1274,7 @@ protected:
             if (imm.isValid())
                 m_assembler.add(addressTempRegister, address.base, imm);
             else {
-                move(Imm32(address.offset), addressTempRegister);
+                move(TrustedImm32(address.offset), addressTempRegister);
                 m_assembler.add(addressTempRegister, addressTempRegister, address.base);
             }
 
@@ -1282,7 +1288,7 @@ protected:
         if ((address.offset >= -0xff) && (address.offset <= 0xfff))
             return ArmAddress(address.base, address.offset);
 
-        move(Imm32(address.offset), addressTempRegister);
+        move(TrustedImm32(address.offset), addressTempRegister);
         return ArmAddress(address.base, addressTempRegister);
     }
 
@@ -1291,7 +1297,7 @@ protected:
         if ((address.offset >= -0xff) && (address.offset <= 0xfff))
             return ArmAddress(address.base, address.offset);
 
-        move(Imm32(address.offset), addressTempRegister);
+        move(TrustedImm32(address.offset), addressTempRegister);
         return ArmAddress(address.base, addressTempRegister);
     }
 
@@ -1304,21 +1310,26 @@ protected:
         if (imm.isValid())
             m_assembler.add(addressTempRegister, address.base, imm);
         else {
-            move(Imm32(address.offset), addressTempRegister);
+            move(TrustedImm32(address.offset), addressTempRegister);
             m_assembler.add(addressTempRegister, addressTempRegister, address.base);
         }
 
         return addressTempRegister;
     }
 
-    void moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
+    void moveFixedWidthEncoding(TrustedImm32 imm, RegisterID dst)
     {
         uint32_t value = imm.m_value;
         m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff));
         m_assembler.movt(dst, ARMThumbImmediate::makeUInt16(value >> 16));
     }
 
-    ARMv7Assembler::Condition armV7Condition(Condition cond)
+    ARMv7Assembler::Condition armV7Condition(RelationalCondition cond)
+    {
+        return static_cast<ARMv7Assembler::Condition>(cond);
+    }
+
+    ARMv7Assembler::Condition armV7Condition(ResultCondition cond)
     {
         return static_cast<ARMv7Assembler::Condition>(cond);
     }
index 543b0fa2415032bf14cddd0531b263a2929e9f8d..6d47cb97587fce4e57b93e01c16bcdca29fed503 100644 (file)
@@ -65,15 +65,47 @@ public:
     {
     }
 
+    template<typename returnType>
+    FunctionPtr(returnType(*value)())
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1>
+    FunctionPtr(returnType(*value)(argType1))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2>
+    FunctionPtr(returnType(*value)(argType1, argType2))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3>
+    FunctionPtr(returnType(*value)(argType1, argType2, argType3))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
+    template<typename returnType, typename argType1, typename argType2, typename argType3, typename argType4>
+    FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4))
+        : m_value((void*)value)
+    {
+        ASSERT_VALID_CODE_POINTER(m_value);
+    }
+
     template<typename FunctionType>
     explicit FunctionPtr(FunctionType* value)
-#if COMPILER(RVCT)
-     // RVTC compiler needs C-style cast as it fails with the following error
-     // Error:  #694: reinterpret_cast cannot cast away const or other type qualifiers
-        : m_value((void*)(value))
-#else
-        : m_value(reinterpret_cast<void*>(value))
-#endif
+        // Using a C-ctyle cast here to avoid compiler error on RVTC:
+        // Error:  #694: reinterpret_cast cannot cast away const or other type qualifiers
+        // (I guess on RVTC function pointers have a different constness to GCC/MSVC?)
+        : m_value((void*)value)
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
@@ -152,7 +184,7 @@ public:
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
-    bool operator!()
+    bool operator!() const
     {
         return !m_value;
     }
index 9853c3408d733e33b128d41b6f1a234d46c807c6..9cdfffc8bc7c9c5beeeeaf9a1539589074504e78 100644 (file)
 
 #if ENABLE(ASSEMBLER) && CPU(MIPS)
 
-#include "AbstractMacroAssembler.h"
 #include "MIPSAssembler.h"
+#include "AbstractMacroAssembler.h"
 
 namespace JSC {
 
 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
 public:
+    typedef MIPSRegisters::FPRegisterID FPRegisterID;
 
     MacroAssemblerMIPS()
         : m_fixedWidth(false)
@@ -56,7 +57,9 @@ public:
     // FP temp register
     static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
 
-    enum Condition {
+    static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
+
+    enum RelationalCondition {
         Equal,
         NotEqual,
         Above,
@@ -66,7 +69,10 @@ public:
         GreaterThan,
         GreaterThanOrEqual,
         LessThan,
-        LessThanOrEqual,
+        LessThanOrEqual
+    };
+
+    enum ResultCondition {
         Overflow,
         Signed,
         Zero,
@@ -94,7 +100,7 @@ public:
     // Integer arithmetic operations:
     //
     // Operations are typically two operand - operation(source, srcDst)
-    // For many operations the source may be an Imm32, the srcDst operand
+    // For many operations the source may be an TrustedImm32, the srcDst operand
     // may often be a memory location (explictly described using an Address
     // object).
 
@@ -103,12 +109,12 @@ public:
         m_assembler.addu(dest, dest, src);
     }
 
-    void add32(Imm32 imm, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID dest)
     {
         add32(imm, dest, dest);
     }
 
-    void add32(Imm32 imm, RegisterID src, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
             && !m_fixedWidth) {
@@ -126,7 +132,7 @@ public:
         }
     }
 
-    void add32(Imm32 imm, Address address)
+    void add32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
             && !m_fixedWidth) {
@@ -206,7 +212,7 @@ public:
         }
     }
 
-    void add32(Imm32 imm, AbsoluteAddress address)
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
         /*
            li   addrTemp, address
@@ -215,7 +221,7 @@ public:
            addu dataTemp, dataTemp, immTemp
            sw   dataTemp, 0(addrTemp)
         */
-        move(ImmPtr(address.m_ptr), addrTempRegister);
+        move(TrustedImmPtr(address.m_ptr), addrTempRegister);
         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
         if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
             && !m_fixedWidth)
@@ -232,7 +238,7 @@ public:
         m_assembler.andInsn(dest, dest, src);
     }
 
-    void and32(Imm32 imm, RegisterID dest)
+    void and32(TrustedImm32 imm, RegisterID dest)
     {
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
@@ -249,7 +255,7 @@ public:
         }
     }
 
-    void lshift32(Imm32 imm, RegisterID dest)
+    void lshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.sll(dest, dest, imm.m_value);
     }
@@ -264,7 +270,7 @@ public:
         m_assembler.mul(dest, dest, src);
     }
 
-    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+    void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
@@ -280,6 +286,11 @@ public:
         }
     }
 
+    void neg32(RegisterID srcDest)
+    {
+        m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
+    }
+
     void not32(RegisterID srcDest)
     {
         m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
@@ -290,7 +301,7 @@ public:
         m_assembler.orInsn(dest, dest, src);
     }
 
-    void or32(Imm32 imm, RegisterID dest)
+    void or32(TrustedImm32 imm, RegisterID dest)
     {
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
             return;
@@ -314,17 +325,27 @@ public:
         m_assembler.srav(dest, dest, shiftAmount);
     }
 
-    void rshift32(Imm32 imm, RegisterID dest)
+    void rshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.sra(dest, dest, imm.m_value);
     }
 
+    void urshift32(RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.srlv(dest, dest, shiftAmount);
+    }
+
+    void urshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.srl(dest, dest, imm.m_value);
+    }
+
     void sub32(RegisterID src, RegisterID dest)
     {
         m_assembler.subu(dest, dest, src);
     }
 
-    void sub32(Imm32 imm, RegisterID dest)
+    void sub32(TrustedImm32 imm, RegisterID dest)
     {
         if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
             && !m_fixedWidth) {
@@ -342,7 +363,7 @@ public:
         }
     }
 
-    void sub32(Imm32 imm, Address address)
+    void sub32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
             && !m_fixedWidth) {
@@ -397,7 +418,7 @@ public:
         sub32(dataTempRegister, dest);
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
         /*
            li   addrTemp, address
@@ -406,7 +427,7 @@ public:
            subu dataTemp, dataTemp, immTemp
            sw   dataTemp, 0(addrTemp)
         */
-        move(ImmPtr(address.m_ptr), addrTempRegister);
+        move(TrustedImmPtr(address.m_ptr), addrTempRegister);
         m_assembler.lw(dataTempRegister, addrTempRegister, 0);
 
         if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
@@ -425,7 +446,7 @@ public:
         m_assembler.xorInsn(dest, dest, src);
     }
 
-    void xor32(Imm32 imm, RegisterID dest)
+    void xor32(TrustedImm32 imm, RegisterID dest)
     {
         /*
             li  immTemp, imm
@@ -435,10 +456,15 @@ public:
         m_assembler.xorInsn(dest, dest, immTempRegister);
     }
 
+    void sqrtDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.sqrtd(dst, src);
+    }
+
     // Memory access operations:
     //
     // Loads are of the form load(address, destination) and stores of the form
-    // store(source, address).  The source for a store may be an Imm32.  Address
+    // store(source, address).  The source for a store may be an TrustedImm32.  Address
     // operand objects to loads and store will be implicitly constructed if a
     // register is passed.
 
@@ -560,13 +586,13 @@ public:
         }
     }
 
-    void load32(void* address, RegisterID dest)
+    void load32(const void* address, RegisterID dest)
     {
         /*
             li  addrTemp, address
             lw  dest, 0(addrTemp)
         */
-        move(ImmPtr(address), addrTempRegister);
+        move(TrustedImmPtr(address), addrTempRegister);
         m_assembler.lw(dest, addrTempRegister, 0);
     }
 
@@ -580,33 +606,36 @@ public:
             lw  dest, 0(addrTemp)
         */
         DataLabel32 dataLabel(this);
-        move(Imm32(address.offset), addrTempRegister);
+        move(TrustedImm32(address.offset), addrTempRegister);
         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
         m_assembler.lw(dest, addrTempRegister, 0);
         m_fixedWidth = false;
         return dataLabel;
     }
-
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+    
+    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
     {
-        m_fixedWidth = true;
-        /*
-            lui         addrTemp, address.offset >> 16
-            ori         addrTemp, addrTemp, address.offset & 0xffff
-            addu        addrTemp, addrTemp, address.base
-            lw          dest, 0(addrTemp)
-        */
-        Label label(this);
-        move(Imm32(address.offset), addrTempRegister);
-        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
-        m_assembler.lw(dest, addrTempRegister, 0);
-        m_fixedWidth = false;
-        return label;
+        DataLabelCompact dataLabel(this);
+        load32WithAddressOffsetPatch(address, dest);
+        return dataLabel;
     }
 
-    Label loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
+    /* Need to use zero-extened load half-word for load16.  */
+    void load16(ImplicitAddress address, RegisterID dest)
     {
-        return loadPtrWithPatchToLEA(address, dest);
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lhu(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lhu     dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        }
     }
 
     /* Need to use zero-extened load half-word for load16.  */
@@ -649,7 +678,7 @@ public:
             sw  src, 0(addrTemp)
         */
         DataLabel32 dataLabel(this);
-        move(Imm32(address.offset), addrTempRegister);
+        move(TrustedImm32(address.offset), addrTempRegister);
         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
         m_assembler.sw(src, addrTempRegister, 0);
         m_fixedWidth = false;
@@ -702,7 +731,7 @@ public:
         }
     }
 
-    void store32(Imm32 imm, ImplicitAddress address)
+    void store32(TrustedImm32 imm, ImplicitAddress address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
             && !m_fixedWidth) {
@@ -732,17 +761,17 @@ public:
         }
     }
 
-    void store32(RegisterID src, void* address)
+    void store32(RegisterID src, const void* address)
     {
         /*
             li  addrTemp, address
             sw  src, 0(addrTemp)
         */
-        move(ImmPtr(address), addrTempRegister);
+        move(TrustedImmPtr(address), addrTempRegister);
         m_assembler.sw(src, addrTempRegister, 0);
     }
 
-    void store32(Imm32 imm, void* address)
+    void store32(TrustedImm32 imm, const void* address)
     {
         /*
             li  immTemp, imm
@@ -750,11 +779,11 @@ public:
             sw  src, 0(addrTemp)
         */
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
-            move(ImmPtr(address), addrTempRegister);
+            move(TrustedImmPtr(address), addrTempRegister);
             m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
         } else {
             move(imm, immTempRegister);
-            move(ImmPtr(address), addrTempRegister);
+            move(TrustedImmPtr(address), addrTempRegister);
             m_assembler.sw(immTempRegister, addrTempRegister, 0);
         }
     }
@@ -779,6 +808,15 @@ public:
 #endif
     }
 
+    bool supportsFloatingPointSqrt() const
+    {
+#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
+        return true;
+#else
+        return false;
+#endif
+    }
+
     // Stack manipulation operations:
     //
     // The ABI is assumed to provide a stack abstraction to memory,
@@ -805,7 +843,7 @@ public:
         push(dataTempRegister);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         move(imm, immTempRegister);
         push(immTempRegister);
@@ -815,7 +853,7 @@ public:
     //
     // Move values in registers.
 
-    void move(Imm32 imm, RegisterID dest)
+    void move(TrustedImm32 imm, RegisterID dest)
     {
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
@@ -832,9 +870,9 @@ public:
             m_assembler.move(dest, src);
     }
 
-    void move(ImmPtr imm, RegisterID dest)
+    void move(TrustedImmPtr imm, RegisterID dest)
     {
-        move(Imm32(imm), dest);
+        move(TrustedImm32(imm), dest);
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
@@ -868,13 +906,13 @@ public:
     // used (representing the names 'below' and 'above').
     //
     // Operands to the comparision are provided in the expected order, e.g.
-    // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
+    // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
     // treated as a signed 32bit value, is less than or equal to 5.
     //
     // jz and jnz test whether the first operand is equal to zero, and take
     // an optional second operand of a mask under which to perform the test.
 
-    Jump branch8(Condition cond, Address left, Imm32 right)
+    Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         // Make sure the immediate value is unsigned 8 bits.
         ASSERT(!(right.m_value & 0xFFFFFF00));
@@ -883,11 +921,11 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch32(Condition cond, RegisterID left, RegisterID right)
+    Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
     {
-        if (cond == Equal || cond == Zero)
+        if (cond == Equal)
             return branchEqual(left, right);
-        if (cond == NotEqual || cond == NonZero)
+        if (cond == NotEqual)
             return branchNotEqual(left, right);
         if (cond == Above) {
             m_assembler.sltu(cmpTempRegister, right, left);
@@ -921,70 +959,37 @@ public:
             m_assembler.slt(cmpTempRegister, right, left);
             return branchEqual(cmpTempRegister, MIPSRegisters::zero);
         }
-        if (cond == Overflow) {
-            /*
-                xor     cmpTemp, left, right
-                bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
-                nop
-                subu    cmpTemp, left, right
-                xor     cmpTemp, cmpTemp, left
-                bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
-                nop
-                b       Overflow
-                nop
-                nop
-                nop
-                nop
-                nop
-              No_overflow:
-            */
-            m_assembler.xorInsn(cmpTempRegister, left, right);
-            m_assembler.bgez(cmpTempRegister, 11);
-            m_assembler.nop();
-            m_assembler.subu(cmpTempRegister, left, right);
-            m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
-            m_assembler.bgez(cmpTempRegister, 7);
-            m_assembler.nop();
-            return jump();
-        }
-        if (cond == Signed) {
-            m_assembler.subu(cmpTempRegister, left, right);
-            // Check if the result is negative.
-            m_assembler.slt(cmpTempRegister, cmpTempRegister,
-                            MIPSRegisters::zero);
-            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
-        }
         ASSERT(0);
 
         return Jump();
     }
 
-    Jump branch32(Condition cond, RegisterID left, Imm32 right)
+    Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
         move(right, immTempRegister);
         return branch32(cond, left, immTempRegister);
     }
 
-    Jump branch32(Condition cond, RegisterID left, Address right)
+    Jump branch32(RelationalCondition cond, RegisterID left, Address right)
     {
         load32(right, dataTempRegister);
         return branch32(cond, left, dataTempRegister);
     }
 
-    Jump branch32(Condition cond, Address left, RegisterID right)
+    Jump branch32(RelationalCondition cond, Address left, RegisterID right)
     {
         load32(left, dataTempRegister);
         return branch32(cond, dataTempRegister, right);
     }
 
-    Jump branch32(Condition cond, Address left, Imm32 right)
+    Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         load32(left, dataTempRegister);
         move(right, immTempRegister);
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         load32(left, dataTempRegister);
         // Be careful that the previous load32() uses immTempRegister.
@@ -993,7 +998,7 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         load32WithUnalignedHalfWords(left, dataTempRegister);
         // Be careful that the previous load32WithUnalignedHalfWords()
@@ -1003,26 +1008,26 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         load32(left.m_ptr, dataTempRegister);
         return branch32(cond, dataTempRegister, right);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
     {
         load32(left.m_ptr, dataTempRegister);
         move(right, immTempRegister);
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
     {
         load16(left, dataTempRegister);
         return branch32(cond, dataTempRegister, right);
     }
 
-    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         ASSERT(!(right.m_value & 0xFFFF0000));
         load16(left, dataTempRegister);
@@ -1032,7 +1037,7 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+    Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         m_assembler.andInsn(cmpTempRegister, reg, mask);
@@ -1041,7 +1046,7 @@ public:
         return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         if (mask.m_value == -1 && !m_fixedWidth) {
@@ -1053,19 +1058,19 @@ public:
         return branchTest32(cond, reg, immTempRegister);
     }
 
-    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load32(address, dataTempRegister);
         return branchTest32(cond, dataTempRegister, mask);
     }
 
-    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load32(address, dataTempRegister);
         return branchTest32(cond, dataTempRegister, mask);
     }
 
-    Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load8(address, dataTempRegister);
         return branchTest32(cond, dataTempRegister, mask);
@@ -1101,7 +1106,7 @@ public:
     // * jo operations branch if the (signed) arithmetic
     //   operation caused an overflow to occur.
 
-    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -1148,13 +1153,13 @@ public:
         return Jump();
     }
 
-    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         move(imm, immTempRegister);
         return branchAdd32(cond, immTempRegister, dest);
     }
 
-    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -1199,14 +1204,14 @@ public:
         return Jump();
     }
 
-    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         move(imm, immTempRegister);
         move(src, dest);
         return branchMul32(cond, immTempRegister, dest);
     }
 
-    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -1253,12 +1258,33 @@ public:
         return Jump();
     }
 
-    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         move(imm, immTempRegister);
         return branchSub32(cond, immTempRegister, dest);
     }
 
+    Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Signed) {
+            or32(src, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            or32(src, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            or32(src, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
     // Miscellaneous operations:
 
     void breakpoint()
@@ -1273,7 +1299,7 @@ public:
         m_assembler.nop();
         m_assembler.jal();
         m_assembler.nop();
-        return Call(m_assembler.newJmpSrc(), Call::LinkableNear);
+        return Call(m_assembler.label(), Call::LinkableNear);
     }
 
     Call call()
@@ -1282,14 +1308,14 @@ public:
         m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
         m_assembler.jalr(MIPSRegisters::t9);
         m_assembler.nop();
-        return Call(m_assembler.newJmpSrc(), Call::Linkable);
+        return Call(m_assembler.label(), Call::Linkable);
     }
 
     Call call(RegisterID target)
     {
         m_assembler.jalr(target);
         m_assembler.nop();
-        return Call(m_assembler.newJmpSrc(), Call::None);
+        return Call(m_assembler.label(), Call::None);
     }
 
     Call call(Address address)
@@ -1299,7 +1325,7 @@ public:
         m_assembler.jalr(MIPSRegisters::t9);
         m_assembler.nop();
         m_fixedWidth = false;
-        return Call(m_assembler.newJmpSrc(), Call::None);
+        return Call(m_assembler.label(), Call::None);
     }
 
     void ret()
@@ -1308,12 +1334,12 @@ public:
         m_assembler.nop();
     }
 
-    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
     {
-        if (cond == Equal || cond == Zero) {
+        if (cond == Equal) {
             m_assembler.xorInsn(dest, left, right);
             m_assembler.sltiu(dest, dest, 1);
-        } else if (cond == NotEqual || cond == NonZero) {
+        } else if (cond == NotEqual) {
             m_assembler.xorInsn(dest, left, right);
             m_assembler.sltu(dest, MIPSRegisters::zero, dest);
         } else if (cond == Above)
@@ -1336,36 +1362,16 @@ public:
         else if (cond == LessThanOrEqual) {
             m_assembler.slt(dest, right, left);
             m_assembler.xori(dest, dest, 1);
-        } else if (cond == Overflow) {
-            /*
-                xor     cmpTemp, left, right
-                bgez    Done, cmpTemp   # same sign bit -> no overflow
-                move    dest, 0
-                subu    cmpTemp, left, right
-                xor     cmpTemp, cmpTemp, left # diff sign bit -> overflow
-                slt     dest, cmpTemp, 0
-              Done:
-            */
-            m_assembler.xorInsn(cmpTempRegister, left, right);
-            m_assembler.bgez(cmpTempRegister, 4);
-            m_assembler.move(dest, MIPSRegisters::zero);
-            m_assembler.subu(cmpTempRegister, left, right);
-            m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
-            m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero);
-        } else if (cond == Signed) {
-            m_assembler.subu(dest, left, right);
-            // Check if the result is negative.
-            m_assembler.slt(dest, dest, MIPSRegisters::zero);
         }
     }
 
-    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         move(right, immTempRegister);
-        set32(cond, left, immTempRegister, dest);
+        compare32(cond, left, immTempRegister, dest);
     }
 
-    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         load8(address, dataTempRegister);
@@ -1385,7 +1391,7 @@ public:
         }
     }
 
-    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         load32(address, dataTempRegister);
@@ -1405,7 +1411,7 @@ public:
         }
     }
 
-    DataLabel32 moveWithPatch(Imm32 imm, RegisterID dest)
+    DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest)
     {
         m_fixedWidth = true;
         DataLabel32 label(this);
@@ -1414,7 +1420,7 @@ public:
         return label;
     }
 
-    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         m_fixedWidth = true;
         DataLabelPtr label(this);
@@ -1423,7 +1429,7 @@ public:
         return label;
     }
 
-    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         m_fixedWidth = true;
         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
@@ -1432,7 +1438,7 @@ public:
         return temp;
     }
 
-    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         m_fixedWidth = true;
         load32(left, dataTempRegister);
@@ -1442,7 +1448,7 @@ public:
         return temp;
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         m_fixedWidth = true;
         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
@@ -1453,18 +1459,18 @@ public:
 
     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
     {
-        return storePtrWithPatch(ImmPtr(0), address);
+        return storePtrWithPatch(TrustedImmPtr(0), address);
     }
 
     Call tailRecursiveCall()
     {
         // Like a normal call, but don't update the returned address register
         m_fixedWidth = true;
-        move(Imm32(0), MIPSRegisters::t9);
+        move(TrustedImm32(0), MIPSRegisters::t9);
         m_assembler.jr(MIPSRegisters::t9);
         m_assembler.nop();
         m_fixedWidth = false;
-        return Call(m_assembler.newJmpSrc(), Call::Linkable);
+        return Call(m_assembler.label(), Call::Linkable);
     }
 
     Call makeTailRecursiveCall(Jump oldJump)
@@ -1482,7 +1488,7 @@ public:
             lwc1        dest, 0(addrTemp)
             lwc1        dest+1, 4(addrTemp)
          */
-        move(Imm32(address.offset), addrTempRegister);
+        move(TrustedImm32(address.offset), addrTempRegister);
         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
         m_assembler.lwc1(dest, addrTempRegister, 0);
         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
@@ -1503,6 +1509,28 @@ public:
 #endif
     }
 
+    void loadDouble(const void* address, FPRegisterID dest)
+    {
+#if WTF_MIPS_ISA(1)
+        /*
+            li          addrTemp, address
+            lwc1        dest, 0(addrTemp)
+            lwc1        dest+1, 4(addrTemp)
+         */
+        move(TrustedImmPtr(address), addrTempRegister);
+        m_assembler.lwc1(dest, addrTempRegister, 0);
+        m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
+#else
+        /*
+            li          addrTemp, address
+            ldc1        dest, 0(addrTemp)
+        */
+        move(TrustedImmPtr(address), addrTempRegister);
+        m_assembler.ldc1(dest, addrTempRegister, 0);
+#endif
+    }
+
+
     void storeDouble(FPRegisterID src, ImplicitAddress address)
     {
 #if WTF_MIPS_ISA(1)
@@ -1512,7 +1540,7 @@ public:
             swc1        dest, 0(addrTemp)
             swc1        dest+1, 4(addrTemp)
          */
-        move(Imm32(address.offset), addrTempRegister);
+        move(TrustedImm32(address.offset), addrTempRegister);
         m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
         m_assembler.swc1(src, addrTempRegister, 0);
         m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
@@ -1566,12 +1594,31 @@ public:
         m_assembler.muld(dest, dest, fpTempRegister);
     }
 
+    void divDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.divd(dest, dest, src);
+    }
+
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
         m_assembler.mtc1(src, fpTempRegister);
         m_assembler.cvtdw(dest, fpTempRegister);
     }
 
+    void convertInt32ToDouble(Address src, FPRegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        m_assembler.mtc1(dataTempRegister, fpTempRegister);
+        m_assembler.cvtdw(dest, fpTempRegister);
+    }
+
+    void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+    {
+        load32(src.m_ptr, dataTempRegister);
+        m_assembler.mtc1(dataTempRegister, fpTempRegister);
+        m_assembler.cvtdw(dest, fpTempRegister);
+    }
+
     void insertRelaxationWords()
     {
         /* We need four words for relaxation. */
@@ -1587,7 +1634,7 @@ public:
         m_assembler.bc1t();
         m_assembler.nop();
         insertRelaxationWords();
-        return Jump(m_assembler.newJmpSrc());
+        return Jump(m_assembler.label());
     }
 
     Jump branchFalse()
@@ -1596,7 +1643,7 @@ public:
         m_assembler.bc1f();
         m_assembler.nop();
         insertRelaxationWords();
-        return Jump(m_assembler.newJmpSrc());
+        return Jump(m_assembler.label());
     }
 
     Jump branchEqual(RegisterID rs, RegisterID rt)
@@ -1605,7 +1652,7 @@ public:
         m_assembler.beq(rs, rt, 0);
         m_assembler.nop();
         insertRelaxationWords();
-        return Jump(m_assembler.newJmpSrc());
+        return Jump(m_assembler.label());
     }
 
     Jump branchNotEqual(RegisterID rs, RegisterID rt)
@@ -1614,7 +1661,7 @@ public:
         m_assembler.bne(rs, rt, 0);
         m_assembler.nop();
         insertRelaxationWords();
-        return Jump(m_assembler.newJmpSrc());
+        return Jump(m_assembler.label());
     }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
@@ -1624,7 +1671,7 @@ public:
             return branchTrue();
         }
         if (cond == DoubleNotEqual) {
-            m_assembler.ceqd(left, right);
+            m_assembler.cueqd(left, right);
             return branchFalse(); // false
         }
         if (cond == DoubleGreaterThan) {
@@ -1632,7 +1679,7 @@ public:
             return branchFalse(); // false
         }
         if (cond == DoubleGreaterThanOrEqual) {
-            m_assembler.cnged(right, left);
+            m_assembler.cnged(left, right);
             return branchFalse(); // false
         }
         if (cond == DoubleLessThan) {
@@ -1647,6 +1694,10 @@ public:
             m_assembler.cueqd(left, right);
             return branchTrue();
         }
+        if (cond == DoubleNotEqualOrUnordered) {
+            m_assembler.ceqd(left, right);
+            return branchFalse(); // false
+        }
         if (cond == DoubleGreaterThanOrUnordered) {
             m_assembler.coled(left, right);
             return branchFalse(); // false
@@ -1676,7 +1727,53 @@ public:
     {
         m_assembler.truncwd(fpTempRegister, src);
         m_assembler.mfc1(dest, fpTempRegister);
-        return branch32(Equal, dest, Imm32(0x7fffffff));
+        return branch32(Equal, dest, TrustedImm32(0x7fffffff));
+    }
+
+    // Convert 'src' to an integer, and places the resulting 'dest'.
+    // If the result is not representable as a 32 bit value, branch.
+    // May also branch for some values that are representable in 32 bits
+    // (specifically, in this case, 0).
+    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+    {
+        m_assembler.cvtwd(fpTempRegister, src);
+        m_assembler.mfc1(dest, fpTempRegister);
+
+        // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
+        failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
+
+        // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
+        convertInt32ToDouble(dest, fpTemp);
+        failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src));
+    }
+
+    Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
+    {
+#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
+        m_assembler.mtc1(MIPSRegisters::zero, scratch);
+        m_assembler.mthc1(MIPSRegisters::zero, scratch);
+#else
+        m_assembler.mtc1(MIPSRegisters::zero, scratch);
+        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
+#endif
+        return branchDouble(DoubleNotEqual, reg, scratch);
+    }
+
+    Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
+    {
+#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
+        m_assembler.mtc1(MIPSRegisters::zero, scratch);
+        m_assembler.mthc1(MIPSRegisters::zero, scratch);
+#else
+        m_assembler.mtc1(MIPSRegisters::zero, scratch);
+        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
+#endif
+        return branchDouble(DoubleEqualOrUnordered, reg, scratch);
+    }
+
+    void nop()
+    {
+        m_assembler.nop();
     }
 
 private:
diff --git a/assembler/MacroAssemblerSH4.cpp b/assembler/MacroAssemblerSH4.cpp
new file mode 100644 (file)
index 0000000..ee11f55
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 STMicroelectronics. All rights reserved.
+ * Copyright (C) 2008 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.
+*/
+
+#include "config.h"
+
+#if ENABLE(ASSEMBLER) && CPU(SH4)
+
+#include "MacroAssemblerSH4.h"
+
+namespace JSC {
+
+void MacroAssemblerSH4::linkCall(void* code, Call call, FunctionPtr function)
+{
+    SH4Assembler::linkCall(code, call.m_jmp, function.value());
+}
+
+void MacroAssemblerSH4::repatchCall(CodeLocationCall call, CodeLocationLabel destination)
+{
+    SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
+}
+
+void MacroAssemblerSH4::repatchCall(CodeLocationCall call, FunctionPtr destination)
+{
+    SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
+}
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
diff --git a/assembler/MacroAssemblerSH4.h b/assembler/MacroAssemblerSH4.h
new file mode 100644 (file)
index 0000000..8bed14c
--- /dev/null
@@ -0,0 +1,1766 @@
+/*
+ * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
+ * Copyright (C) 2008 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 MacroAssemblerSH4_h
+#define MacroAssemblerSH4_h
+
+#if ENABLE(ASSEMBLER) && CPU(SH4)
+
+#include "AbstractMacroAssembler.h"
+#include "SH4Assembler.h"
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+class MacroAssemblerSH4 : public AbstractMacroAssembler<SH4Assembler> {
+public:
+    typedef SH4Assembler::FPRegisterID FPRegisterID;
+
+    static const Scale ScalePtr = TimesFour;
+    static const FPRegisterID fscratch = SH4Registers::fr10;
+    static const RegisterID stackPointerRegister = SH4Registers::sp;
+    static const RegisterID linkRegister = SH4Registers::pr;
+    static const RegisterID scratchReg3 = SH4Registers::r13;
+
+    static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
+
+    enum RelationalCondition {
+        Equal = SH4Assembler::EQ,
+        NotEqual = SH4Assembler::NE,
+        Above = SH4Assembler::HI,
+        AboveOrEqual = SH4Assembler::HS,
+        Below = SH4Assembler::LI,
+        BelowOrEqual = SH4Assembler::LS,
+        GreaterThan = SH4Assembler::GT,
+        GreaterThanOrEqual = SH4Assembler::GE,
+        LessThan = SH4Assembler::LT,
+        LessThanOrEqual = SH4Assembler::LE
+    };
+
+    enum ResultCondition {
+        Overflow = SH4Assembler::OF,
+        Signed = SH4Assembler::SI,
+        Zero = SH4Assembler::EQ,
+        NonZero = SH4Assembler::NE
+    };
+
+    enum DoubleCondition {
+        // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
+        DoubleEqual = SH4Assembler::EQ,
+        DoubleNotEqual = SH4Assembler::NE,
+        DoubleGreaterThan = SH4Assembler::GT,
+        DoubleGreaterThanOrEqual = SH4Assembler::GE,
+        DoubleLessThan = SH4Assembler::LT,
+        DoubleLessThanOrEqual = SH4Assembler::LE,
+        // If either operand is NaN, these conditions always evaluate to true.
+        DoubleEqualOrUnordered = SH4Assembler::EQU,
+        DoubleNotEqualOrUnordered = SH4Assembler::NEU,
+        DoubleGreaterThanOrUnordered = SH4Assembler::GTU,
+        DoubleGreaterThanOrEqualOrUnordered = SH4Assembler::GEU,
+        DoubleLessThanOrUnordered = SH4Assembler::LTU,
+        DoubleLessThanOrEqualOrUnordered = SH4Assembler::LEU,
+    };
+
+    RegisterID claimScratch()
+    {
+        return m_assembler.claimScratch();
+    }
+
+    void releaseScratch(RegisterID reg)
+    {
+        m_assembler.releaseScratch(reg);
+    }
+
+    // Integer arithmetic operations
+
+    void add32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.addlRegReg(src, dest);
+    }
+
+    void add32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (m_assembler.isImmediate(imm.m_value)) {
+            m_assembler.addlImm8r(imm.m_value, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm.m_value, scr);
+        m_assembler.addlRegReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (src != dest)
+            m_assembler.movlRegReg(src, dest);
+        add32(imm, dest);
+    }
+
+    void add32(TrustedImm32 imm, Address address)
+    {
+        RegisterID scr = claimScratch();
+        load32(address, scr);
+        add32(imm, scr);
+        store32(scr, address);
+        releaseScratch(scr);
+    }
+
+    void add32(Address src, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        load32(src, scr);
+        m_assembler.addlRegReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void and32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.andlRegReg(src, dest);
+    }
+
+    void and32(TrustedImm32 imm, RegisterID dest)
+    {
+        if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
+            m_assembler.andlImm8r(imm.m_value, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant((imm.m_value), scr);
+        m_assembler.andlRegReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void lshift32(RegisterID shiftamount, RegisterID dest)
+    {
+        m_assembler.shllRegReg(dest, shiftamount);
+    }
+
+    void rshift32(int imm, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(-imm, scr);
+        m_assembler.shaRegReg(dest, scr);
+        releaseScratch(scr);
+    }
+
+    void lshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) {
+            m_assembler.shllImm8r(imm.m_value, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm.m_value, scr);
+        m_assembler.shllRegReg(dest, scr);
+        releaseScratch(scr);
+    }
+
+    void mul32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.imullRegReg(src, dest);
+        m_assembler.stsmacl(dest);
+    }
+
+    void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        move(imm, scr);
+        if  (src != dest)
+            move(src, dest);
+        mul32(scr,  dest);
+        releaseScratch(scr);
+    }
+
+    void not32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.notlReg(src, dest);
+    }
+
+    void or32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.orlRegReg(src, dest);
+    }
+
+    void or32(TrustedImm32 imm, RegisterID dest)
+    {
+        if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) {
+            m_assembler.orlImm8r(imm.m_value, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm.m_value, scr);
+        m_assembler.orlRegReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void rshift32(RegisterID shiftamount, RegisterID dest)
+    {
+        compare32(32, shiftamount, Equal);
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
+        m_assembler.branch(BT_OPCODE, 1);
+        m_assembler.neg(shiftamount, shiftamount);
+        m_assembler.shaRegReg(dest, shiftamount);
+    }
+
+    void rshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (imm.m_value & 0x1f)
+            rshift32(imm.m_value & 0x1f, dest);
+    }
+
+    void sub32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.sublRegReg(src, dest);
+    }
+
+    void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
+    {
+        RegisterID result = claimScratch();
+
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
+        m_assembler.movlMemReg(scratchReg, result);
+
+        if (m_assembler.isImmediate(-imm.m_value))
+            m_assembler.addlImm8r(-imm.m_value, result);
+        else {
+            m_assembler.loadConstant(imm.m_value, scratchReg3);
+            m_assembler.sublRegReg(scratchReg3, result);
+        }
+
+        store32(result, scratchReg);
+        releaseScratch(result);
+    }
+
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        RegisterID result = claimScratch();
+        RegisterID scratchReg = claimScratch();
+
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
+        m_assembler.movlMemReg(scratchReg, result);
+
+        if (m_assembler.isImmediate(-imm.m_value))
+            m_assembler.addlImm8r(-imm.m_value, result);
+        else {
+            m_assembler.loadConstant(imm.m_value, scratchReg3);
+            m_assembler.sublRegReg(scratchReg3, result);
+        }
+
+        store32(result, scratchReg);
+        releaseScratch(result);
+        releaseScratch(scratchReg);
+    }
+
+    void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg)
+    {
+        RegisterID result = claimScratch();
+
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
+        m_assembler.movlMemReg(scratchReg, result);
+
+        if (m_assembler.isImmediate(imm.m_value))
+            m_assembler.addlImm8r(imm.m_value, result);
+        else {
+            m_assembler.loadConstant(imm.m_value, scratchReg3);
+            m_assembler.addlRegReg(scratchReg3, result);
+        }
+
+        store32(result, scratchReg);
+        releaseScratch(result);
+    }
+
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        RegisterID result = claimScratch();
+        RegisterID scratchReg = claimScratch();
+
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg);
+        m_assembler.movlMemReg(scratchReg, result);
+
+        if (m_assembler.isImmediate(imm.m_value))
+            m_assembler.addlImm8r(imm.m_value, result);
+        else {
+            m_assembler.loadConstant(imm.m_value, scratchReg3);
+            m_assembler.addlRegReg(scratchReg3, result);
+        }
+
+        store32(result, scratchReg);
+        releaseScratch(result);
+        releaseScratch(scratchReg);
+    }
+
+    void sub32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (m_assembler.isImmediate(-imm.m_value)) {
+            m_assembler.addlImm8r(-imm.m_value, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm.m_value, scr);
+        m_assembler.sublRegReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void sub32(Address src, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        load32(src, scr);
+        m_assembler.sublRegReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void xor32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.xorlRegReg(src, dest);
+    }
+
+    void xor32(TrustedImm32 imm, RegisterID srcDest)
+    {
+        if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant((imm.m_value), scr);
+            m_assembler.xorlRegReg(scr, srcDest);
+            releaseScratch(scr);
+            return;
+        }
+
+        m_assembler.xorlImm8r(imm.m_value, srcDest);
+    }
+
+    void compare32(int imm, RegisterID dst, RelationalCondition cond)
+    {
+        if (((cond == Equal) || (cond == NotEqual)) && (dst == SH4Registers::r0) && m_assembler.isImmediate(imm)) {
+            m_assembler.cmpEqImmR0(imm, dst);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm, scr);
+        m_assembler.cmplRegReg(scr, dst, SH4Condition(cond));
+        releaseScratch(scr);
+    }
+
+    void compare32(int offset, RegisterID base, RegisterID left, RelationalCondition cond)
+    {
+        RegisterID scr = claimScratch();
+        if (!offset) {
+            m_assembler.movlMemReg(base, scr);
+            m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
+            releaseScratch(scr);
+            return;
+        }
+
+        if ((offset < 0) || (offset >= 64)) {
+            m_assembler.loadConstant(offset, scr);
+            m_assembler.addlRegReg(base, scr);
+            m_assembler.movlMemReg(scr, scr);
+            m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
+            releaseScratch(scr);
+            return;
+        }
+
+        m_assembler.movlMemReg(offset >> 2, base, scr);
+        m_assembler.cmplRegReg(scr, left, SH4Condition(cond));
+        releaseScratch(scr);
+    }
+
+    void testImm(int imm, int offset, RegisterID base)
+    {
+        RegisterID scr = claimScratch();
+        RegisterID scr1 = claimScratch();
+
+        if ((offset < 0) || (offset >= 64)) {
+            m_assembler.loadConstant(offset, scr);
+            m_assembler.addlRegReg(base, scr);
+            m_assembler.movlMemReg(scr, scr);
+        } else if (offset)
+            m_assembler.movlMemReg(offset >> 2, base, scr);
+        else
+            m_assembler.movlMemReg(base, scr);
+        if (m_assembler.isImmediate(imm))
+            m_assembler.movImm8(imm, scr1);
+        else
+            m_assembler.loadConstant(imm, scr1);
+
+        m_assembler.testlRegReg(scr, scr1);
+        releaseScratch(scr);
+        releaseScratch(scr1);
+    }
+
+    void testlImm(int imm, RegisterID dst)
+    {
+        if ((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0)) {
+            m_assembler.testlImm8r(imm, dst);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm, scr);
+        m_assembler.testlRegReg(scr, dst);
+        releaseScratch(scr);
+    }
+
+    void compare32(RegisterID right, int offset, RegisterID base, RelationalCondition cond)
+    {
+        if (!offset) {
+            RegisterID scr = claimScratch();
+            m_assembler.movlMemReg(base, scr);
+            m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
+            releaseScratch(scr);
+            return;
+        }
+
+        if ((offset < 0) || (offset >= 64)) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(offset, scr);
+            m_assembler.addlRegReg(base, scr);
+            m_assembler.movlMemReg(scr, scr);
+            m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
+            releaseScratch(scr);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.movlMemReg(offset >> 2, base, scr);
+        m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
+        releaseScratch(scr);
+    }
+
+    void compare32(int imm, int offset, RegisterID base, RelationalCondition cond)
+    {
+        if (!offset) {
+            RegisterID scr = claimScratch();
+            RegisterID scr1 = claimScratch();
+            m_assembler.movlMemReg(base, scr);
+            m_assembler.loadConstant(imm, scr1);
+            m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
+            releaseScratch(scr1);
+            releaseScratch(scr);
+            return;
+        }
+
+        if ((offset < 0) || (offset >= 64)) {
+            RegisterID scr = claimScratch();
+            RegisterID scr1 = claimScratch();
+            m_assembler.loadConstant(offset, scr);
+            m_assembler.addlRegReg(base, scr);
+            m_assembler.movlMemReg(scr, scr);
+            m_assembler.loadConstant(imm, scr1);
+            m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
+            releaseScratch(scr1);
+            releaseScratch(scr);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        RegisterID scr1 = claimScratch();
+        m_assembler.movlMemReg(offset >> 2, base, scr);
+        m_assembler.loadConstant(imm, scr1);
+        m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
+        releaseScratch(scr1);
+        releaseScratch(scr);
+    }
+
+    // Memory access operation
+
+    void load32(ImplicitAddress address, RegisterID dest)
+    {
+        load32(address.base, address.offset, dest);
+    }
+
+    void load8(ImplicitAddress address, RegisterID dest)
+    {
+        load8(address.base, address.offset, dest);
+    }
+
+    void load32(BaseIndex address, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+        add32(address.base, scr);
+        load32(scr, address.offset, dest);
+        releaseScratch(scr);
+    }
+
+    void load32(void* address, RegisterID dest)
+    {
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dest);
+        m_assembler.movlMemReg(dest, dest);
+    }
+
+    void load32(RegisterID base, int offset, RegisterID dest)
+    {
+        if (!offset) {
+            m_assembler.movlMemReg(base, dest);
+            return;
+        }
+
+        if ((offset >= 0) && (offset < 64)) {
+            m_assembler.movlMemReg(offset >> 2, base, dest);
+            return;
+        }
+
+        if ((dest == SH4Registers::r0) && (dest != base)) {
+            m_assembler.loadConstant((offset), dest);
+            m_assembler.movlR0mr(base, dest);
+            return;
+        }
+
+        RegisterID scr;
+        if (dest == base)
+            scr = claimScratch();
+        else
+            scr = dest;
+        m_assembler.loadConstant((offset), scr);
+        m_assembler.addlRegReg(base, scr);
+        m_assembler.movlMemReg(scr, dest);
+
+        if (dest == base)
+            releaseScratch(scr);
+    }
+
+    void load8(RegisterID base, int offset, RegisterID dest)
+    {
+        if (!offset) {
+            m_assembler.movbMemReg(base, dest);
+            return;
+        }
+
+        if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) {
+            m_assembler.movbMemReg(offset, base, dest);
+            return;
+        }
+
+        if (base != dest) {
+            m_assembler.loadConstant((offset), dest);
+            m_assembler.addlRegReg(base, dest);
+            m_assembler.movbMemReg(dest, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant((offset), scr);
+        m_assembler.addlRegReg(base, scr);
+        m_assembler.movbMemReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void load32(RegisterID r0, RegisterID src, RegisterID dst)
+    {
+        ASSERT(r0 == SH4Registers::r0);
+        m_assembler.movlR0mr(src, dst);
+    }
+
+    void load32(RegisterID src, RegisterID dst)
+    {
+        m_assembler.movlMemReg(src, dst);
+    }
+
+    void load16(ImplicitAddress address, RegisterID dest)
+    {
+        if (!address.offset) {
+            m_assembler.movwMemReg(address.base, dest);
+            return;
+        }
+
+        if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) {
+            m_assembler.movwMemReg(address.offset, address.base, dest);
+            return;
+        }
+
+        if (address.base != dest) {
+            m_assembler.loadConstant((address.offset), dest);
+            m_assembler.addlRegReg(address.base, dest);
+            m_assembler.movwMemReg(dest, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant((address.offset), scr);
+        m_assembler.addlRegReg(address.base, scr);
+        m_assembler.movwMemReg(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void load16(RegisterID src, RegisterID dest)
+    {
+        m_assembler.movwMemReg(src, dest);
+    }
+
+    void load16(RegisterID r0, RegisterID src, RegisterID dest)
+    {
+        ASSERT(r0 == SH4Registers::r0);
+        m_assembler.movwR0mr(src, dest);
+    }
+
+    void load16(BaseIndex address, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+
+        if (address.offset)
+            add32(TrustedImm32(address.offset), scr);
+        if (scr == SH4Registers::r0)
+            m_assembler.movwR0mr(address.base, scr);
+        else {
+            add32(address.base, scr);
+            load16(scr, scr);
+        }
+
+        extuw(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void store32(RegisterID src, ImplicitAddress address)
+    {
+        RegisterID scr = claimScratch();
+        store32(src, address.offset, address.base, scr);
+        releaseScratch(scr);
+    }
+
+    void store32(RegisterID src, int offset, RegisterID base, RegisterID scr)
+    {
+        if (!offset) {
+            m_assembler.movlRegMem(src, base);
+            return;
+        }
+
+        if ((offset >=0) && (offset < 64)) {
+            m_assembler.movlRegMem(src, offset >> 2, base);
+            return;
+        }
+
+        m_assembler.loadConstant((offset), scr);
+        if (scr == SH4Registers::r0) {
+            m_assembler.movlRegMemr0(src, base);
+            return;
+        }
+
+        m_assembler.addlRegReg(base, scr);
+        m_assembler.movlRegMem(src, scr);
+    }
+
+    void store32(RegisterID src, RegisterID offset, RegisterID base)
+    {
+        ASSERT(offset == SH4Registers::r0);
+        m_assembler.movlRegMemr0(src, base);
+    }
+
+    void store32(RegisterID src, RegisterID dst)
+    {
+        m_assembler.movlRegMem(src, dst);
+    }
+
+    void store32(TrustedImm32 imm, ImplicitAddress address)
+    {
+        RegisterID scr = claimScratch();
+        RegisterID scr1 = claimScratch();
+        m_assembler.loadConstant((imm.m_value), scr);
+        store32(scr, address.offset, address.base, scr1);
+        releaseScratch(scr);
+        releaseScratch(scr1);
+    }
+
+    void store32(RegisterID src, BaseIndex address)
+    {
+        RegisterID scr = claimScratch();
+
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+        add32(address.base, scr);
+        store32(src, Address(scr, address.offset));
+
+        releaseScratch(scr);
+    }
+
+    void store32(TrustedImm32 imm, void* address)
+    {
+        RegisterID scr = claimScratch();
+        RegisterID scr1 = claimScratch();
+        m_assembler.loadConstant((imm.m_value), scr);
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1);
+        m_assembler.movlMemReg(scr, scr1);
+        releaseScratch(scr);
+        releaseScratch(scr1);
+    }
+
+    void store32(RegisterID src, void* address)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
+        m_assembler.movlMemReg(src, scr);
+        releaseScratch(scr);
+    }
+
+    DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        DataLabel32 label(this);
+        m_assembler.loadConstantUnReusable(address.offset, scr);
+        m_assembler.addlRegReg(address.base, scr);
+        m_assembler.movlMemReg(scr, dest);
+        releaseScratch(scr);
+        return label;
+    }
+    
+    DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        DataLabelCompact label(this);
+        m_assembler.loadConstantUnReusable(address.offset, scr);
+        m_assembler.addlRegReg(address.base, scr);
+        m_assembler.movlMemReg(scr, dest);
+        releaseScratch(scr);
+        return label;
+    }
+
+    DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
+    {
+        RegisterID scr = claimScratch();
+        DataLabel32 label(this);
+        m_assembler.loadConstantUnReusable(address.offset, scr);
+        m_assembler.addlRegReg(address.base, scr);
+        m_assembler.movlRegMem(src, scr);
+        releaseScratch(scr);
+        return label;
+    }
+
+     // Floating-point operations
+
+    bool supportsFloatingPoint() const { return true; }
+    bool supportsFloatingPointTruncate() const { return true; }
+    bool supportsFloatingPointSqrt() const { return true; }
+
+    void loadDouble(ImplicitAddress address, FPRegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+
+        m_assembler.loadConstant(address.offset, scr);
+        if (address.base == SH4Registers::r0) {
+            m_assembler.fmovsReadr0r(scr, (FPRegisterID)(dest + 1));
+            m_assembler.addlImm8r(4, scr);
+            m_assembler.fmovsReadr0r(scr, dest);
+            releaseScratch(scr);
+            return;
+        }
+
+        m_assembler.addlRegReg(address.base, scr);
+        m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
+        m_assembler.fmovsReadrm(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void loadDouble(const void* address, FPRegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr);
+        m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1));
+        m_assembler.fmovsReadrm(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void storeDouble(FPRegisterID src, ImplicitAddress address)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(address.offset, scr);
+        m_assembler.addlRegReg(address.base, scr);
+        m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr);
+        m_assembler.addlImm8r(4, scr);
+        m_assembler.fmovsWriterm(src, scr);
+        releaseScratch(scr);
+    }
+
+    void addDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.daddRegReg(src, dest);
+    }
+
+    void addDouble(Address address, FPRegisterID dest)
+    {
+        loadDouble(address, fscratch);
+        addDouble(fscratch, dest);
+    }
+
+    void subDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.dsubRegReg(src, dest);
+    }
+
+    void subDouble(Address address, FPRegisterID dest)
+    {
+        loadDouble(address, fscratch);
+        subDouble(fscratch, dest);
+    }
+
+    void mulDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.dmulRegReg(src, dest);
+    }
+
+    void mulDouble(Address address, FPRegisterID dest)
+    {
+        loadDouble(address, fscratch);
+        mulDouble(fscratch, dest);
+    }
+
+    void divDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.ddivRegReg(src, dest);
+    }
+
+    void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
+    {
+        m_assembler.ldsrmfpul(src);
+        m_assembler.floatfpulDreg(dest);
+    }
+
+    void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr);
+        convertInt32ToDouble(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void convertInt32ToDouble(Address src, FPRegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        load32(src, scr);
+        convertInt32ToDouble(scr, dest);
+        releaseScratch(scr);
+    }
+
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+        add32(address.base, scr);
+
+        if (address.offset)
+            add32(TrustedImm32(address.offset), scr);
+
+        RegisterID scr1 = claimScratch();
+        load16(scr, scr1);
+        add32(TrustedImm32(2), scr);
+        load16(scr, dest);
+        move(TrustedImm32(16), scr);
+        m_assembler.shllRegReg(dest, scr);
+        or32(scr1, dest);
+
+        releaseScratch(scr);
+        releaseScratch(scr1);
+    }
+
+    Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        RegisterID scr = scratchReg3;
+        load32WithUnalignedHalfWords(left, scr);
+        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+            m_assembler.testlRegReg(scr, scr);
+        else
+            compare32(right.m_value, scr, cond);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
+    {
+        m_assembler.movImm8(0, scratchReg3);
+        convertInt32ToDouble(scratchReg3, scratch);
+        return branchDouble(DoubleNotEqual, reg, scratch);
+    }
+
+    Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
+    {
+        m_assembler.movImm8(0, scratchReg3);
+        convertInt32ToDouble(scratchReg3, scratch);
+        return branchDouble(DoubleEqualOrUnordered, reg, scratch);
+    }
+
+    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+    {
+        if (cond == DoubleEqual) {
+            m_assembler.dcmppeq(right, left);
+            return branchTrue();
+        }
+
+        if (cond == DoubleNotEqual) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+            m_assembler.dcnvds(right);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+            m_assembler.branch(BT_OPCODE, 8);
+            m_assembler.dcnvds(left);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.branch(BT_OPCODE, 4);
+            m_assembler.dcmppeq(right, left);
+            releaseScratch(scr);
+            return branchFalse();
+        }
+
+        if (cond == DoubleGreaterThan) {
+            m_assembler.dcmppgt(right, left);
+            return branchTrue();
+        }
+
+        if (cond == DoubleGreaterThanOrEqual) {
+            m_assembler.dcmppgt(left, right);
+            return branchFalse();
+        }
+
+        if (cond == DoubleLessThan) {
+            m_assembler.dcmppgt(left, right);
+            return branchTrue();
+        }
+
+        if (cond == DoubleLessThanOrEqual) {
+            m_assembler.dcmppgt(right, left);
+            return branchFalse();
+        }
+
+        if (cond == DoubleEqualOrUnordered) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+            m_assembler.dcnvds(right);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+            m_assembler.branch(BT_OPCODE, 5);
+            m_assembler.dcnvds(left);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.branch(BT_OPCODE, 1);
+            m_assembler.dcmppeq(left, right);
+            releaseScratch(scr);
+            return branchTrue();
+        }
+
+        if (cond == DoubleGreaterThanOrUnordered) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+            m_assembler.dcnvds(right);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+            m_assembler.branch(BT_OPCODE, 5);
+            m_assembler.dcnvds(left);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.branch(BT_OPCODE, 1);
+            m_assembler.dcmppgt(right, left);
+            releaseScratch(scr);
+            return branchTrue();
+        }
+
+        if (cond == DoubleGreaterThanOrEqualOrUnordered) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+            m_assembler.dcnvds(right);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+            m_assembler.branch(BT_OPCODE, 5);
+            m_assembler.dcnvds(left);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.branch(BT_OPCODE, 1);
+            m_assembler.dcmppgt(left, right);
+            releaseScratch(scr);
+            return branchFalse();
+        }
+
+        if (cond == DoubleLessThanOrUnordered) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+            m_assembler.dcnvds(right);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+            m_assembler.branch(BT_OPCODE, 5);
+            m_assembler.dcnvds(left);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.branch(BT_OPCODE, 1);
+            m_assembler.dcmppgt(left, right);
+            releaseScratch(scr);
+            return branchTrue();
+        }
+
+        if (cond == DoubleLessThanOrEqualOrUnordered) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+            m_assembler.dcnvds(right);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+            m_assembler.branch(BT_OPCODE, 5);
+            m_assembler.dcnvds(left);
+            m_assembler.stsfpulReg(scr);
+            m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+            m_assembler.branch(BT_OPCODE, 1);
+            m_assembler.dcmppgt(right, left);
+            releaseScratch(scr);
+            return branchFalse();
+        }
+
+        ASSERT(cond == DoubleNotEqualOrUnordered);
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(0x7fbfffff, scratchReg3);
+        m_assembler.dcnvds(right);
+        m_assembler.stsfpulReg(scr);
+        m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t));
+        m_assembler.branch(BT_OPCODE, 5);
+        m_assembler.dcnvds(left);
+        m_assembler.stsfpulReg(scr);
+        m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal));
+        m_assembler.branch(BT_OPCODE, 1);
+        m_assembler.dcmppeq(right, left);
+        releaseScratch(scr);
+        return branchFalse();
+    }
+
+    Jump branchTrue()
+    {
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
+        Jump m_jump = Jump(m_assembler.je());
+        m_assembler.loadConstantUnReusable(0x0, scratchReg3);
+        m_assembler.nop();
+        m_assembler.nop();
+        return m_jump;
+    }
+
+    Jump branchFalse()
+    {
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t));
+        Jump m_jump = Jump(m_assembler.jne());
+        m_assembler.loadConstantUnReusable(0x0, scratchReg3);
+        m_assembler.nop();
+        m_assembler.nop();
+        return m_jump;
+    }
+
+    Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        RegisterID scr = claimScratch();
+        move(left.index, scr);
+        lshift32(TrustedImm32(left.scale), scr);
+        add32(left.base, scr);
+        load32(scr, left.offset, scr);
+        compare32(right.m_value, scr, cond);
+        releaseScratch(scr);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    void sqrtDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        if (dest != src)
+            m_assembler.dmovRegReg(src, dest);
+        m_assembler.dsqrt(dest);
+    }
+
+    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        RegisterID addressTempRegister = claimScratch();
+        load8(address, addressTempRegister);
+        Jump jmp = branchTest32(cond, addressTempRegister, mask);
+        releaseScratch(addressTempRegister);
+        return jmp;
+    }
+
+    void signExtend32ToPtr(RegisterID src, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+    }
+
+    Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
+    {
+        RegisterID addressTempRegister = claimScratch();
+        load8(left, addressTempRegister);
+        Jump jmp = branch32(cond, addressTempRegister, right);
+        releaseScratch(addressTempRegister);
+        return jmp;
+    }
+
+    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    {
+        m_assembler.ftrcdrmfpul(src);
+        m_assembler.stsfpulReg(dest);
+        m_assembler.loadConstant(0x7fffffff, scratchReg3);
+        m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t));
+        m_assembler.branch(BT_OPCODE, 2);
+        m_assembler.addlImm8r(1, scratchReg3);
+        m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal));
+        return branchTrue();
+    }
+
+    // Stack manipulation operations
+
+    void pop(RegisterID dest)
+    {
+        m_assembler.popReg(dest);
+    }
+
+    void push(RegisterID src)
+    {
+        m_assembler.pushReg(src);
+    }
+
+    void push(Address address)
+    {
+        if (!address.offset) {
+            push(address.base);
+            return;
+        }
+
+        if ((address.offset < 0) || (address.offset >= 64)) {
+            RegisterID scr = claimScratch();
+            m_assembler.loadConstant(address.offset, scr);
+            m_assembler.addlRegReg(address.base, scr);
+            m_assembler.movlMemReg(scr, SH4Registers::sp);
+            m_assembler.addlImm8r(-4, SH4Registers::sp);
+            releaseScratch(scr);
+            return;
+        }
+
+        m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp);
+        m_assembler.addlImm8r(-4, SH4Registers::sp);
+    }
+
+    void push(TrustedImm32 imm)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(imm.m_value, scr);
+        push(scr);
+        releaseScratch(scr);
+    }
+
+    // Register move operations
+
+    void move(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.loadConstant(imm.m_value, dest);
+    }
+
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
+    {
+        DataLabelPtr dataLabel(this);
+        m_assembler.loadConstantUnReusable(reinterpret_cast<uint32_t>(initialValue.m_value), dest, true);
+        return dataLabel;
+    }
+
+    void move(RegisterID src, RegisterID dest)
+    {
+        m_assembler.movlRegReg(src, dest);
+    }
+
+    void move(TrustedImmPtr imm, RegisterID dest)
+    {
+        m_assembler.loadConstant(imm.asIntptr(), dest);
+    }
+
+    void extuw(RegisterID src, RegisterID dst)
+    {
+        m_assembler.extuw(src, dst);
+    }
+
+    void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
+    {
+        m_assembler.cmplRegReg(right, left, SH4Condition(cond));
+        if (cond != NotEqual) {
+            m_assembler.movt(dest);
+            return;
+        }
+
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
+        m_assembler.movImm8(0, dest);
+        m_assembler.branch(BT_OPCODE, 0);
+        m_assembler.movImm8(1, dest);
+    }
+
+    void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
+    {
+        if (left != dest) {
+            move(right, dest);
+            compare32(cond, left, dest, dest);
+            return;
+        }
+
+        RegisterID scr = claimScratch();
+        move(right, scr);
+        compare32(cond, left, scr, dest);
+        releaseScratch(scr);
+    }
+
+    void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+
+        load8(address, dest);
+        if (mask.m_value == -1)
+            compare32(0, dest, static_cast<RelationalCondition>(cond));
+        else
+            testlImm(mask.m_value, dest);
+        if (cond != NonZero) {
+            m_assembler.movt(dest);
+            return;
+        }
+
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
+        m_assembler.movImm8(0, dest);
+        m_assembler.branch(BT_OPCODE, 0);
+        m_assembler.movImm8(1, dest);
+    }
+
+    void loadPtrLinkReg(ImplicitAddress address)
+    {
+        RegisterID scr = claimScratch();
+        load32(address, scr);
+        m_assembler.ldspr(scr);
+        releaseScratch(scr);
+    }
+
+    Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
+    {
+        m_assembler.cmplRegReg(right, left, SH4Condition(cond));
+        /* BT label => BF off
+           nop         LDR reg
+           nop         braf @reg
+           nop         nop
+         */
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
+    {
+        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
+            m_assembler.testlRegReg(left, left);
+        else
+            compare32(right.m_value, left, cond);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch32(RelationalCondition cond, RegisterID left, Address right)
+    {
+        compare32(right.offset, right.base, left, cond);
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch32(RelationalCondition cond, Address left, RegisterID right)
+    {
+        compare32(right, left.offset, left.base, cond);
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
+    {
+        compare32(right.m_value, left.offset, left.base, cond);
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
+    {
+        RegisterID scr = claimScratch();
+
+        move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr);
+        m_assembler.cmplRegReg(right, scr, SH4Condition(cond));
+        releaseScratch(scr);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
+    {
+        RegisterID addressTempRegister = claimScratch();
+
+        m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister);
+        m_assembler.movlMemReg(addressTempRegister, addressTempRegister);
+        compare32(right.m_value, addressTempRegister, cond);
+        releaseScratch(addressTempRegister);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branch16(RelationalCondition cond,  BaseIndex left, RegisterID right)
+    {
+        RegisterID scr = claimScratch();
+
+        move(left.index, scr);
+        lshift32(TrustedImm32(left.scale), scr);
+
+        if (left.offset)
+            add32(TrustedImm32(left.offset), scr);
+        add32(left.base, scr);
+        load16(scr, scr);
+        extuw(scr, scr);
+        releaseScratch(scr);
+
+        return branch32(cond, scr, right);
+    }
+
+    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        RegisterID scr = claimScratch();
+
+        move(left.index, scr);
+        lshift32(TrustedImm32(left.scale), scr);
+
+        if (left.offset)
+            add32(TrustedImm32(left.offset), scr);
+        add32(left.base, scr);
+        load16(scr, scr);
+        extuw(scr, scr);
+        RegisterID scr1 = claimScratch();
+        m_assembler.loadConstant(right.m_value, scr1);
+        releaseScratch(scr);
+        releaseScratch(scr1);
+
+        return branch32(cond, scr, scr1);
+    }
+
+    Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+
+        m_assembler.testlRegReg(reg, mask);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+
+        if (mask.m_value == -1)
+            m_assembler.testlRegReg(reg, reg);
+        else
+            testlImm(mask.m_value, reg);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+
+        if (mask.m_value == -1)
+            compare32(0, address.offset, address.base, static_cast<RelationalCondition>(cond));
+        else
+            testImm(mask.m_value, address.offset, address.base);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        RegisterID scr = claimScratch();
+
+        move(address.index, scr);
+        lshift32(TrustedImm32(address.scale), scr);
+        add32(address.base, scr);
+        load32(scr, address.offset, scr);
+
+        if (mask.m_value == -1)
+            m_assembler.testlRegReg(scr, scr);
+        else
+            testlImm(mask.m_value, scr);
+
+        releaseScratch(scr);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump jump()
+    {
+        return Jump(m_assembler.jmp());
+    }
+
+    void jump(RegisterID target)
+    {
+        m_assembler.jmpReg(target);
+    }
+
+    void jump(Address address)
+    {
+        RegisterID scr = claimScratch();
+
+        if ((address.offset < 0) || (address.offset >= 64)) {
+            m_assembler.loadConstant(address.offset, scr);
+            m_assembler.addlRegReg(address.base, scr);
+            m_assembler.movlMemReg(scr, scr);
+        } else if (address.offset)
+            m_assembler.movlMemReg(address.offset >> 2, address.base, scr);
+        else
+            m_assembler.movlMemReg(address.base, scr);
+        m_assembler.jmpReg(scr);
+
+        releaseScratch(scr);
+    }
+
+    // Arithmetic control flow operations
+
+    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        if (cond == Overflow) {
+            m_assembler.addvlRegReg(src, dest);
+            return branchTrue();
+        }
+
+        if (cond == Signed) {
+            m_assembler.addlRegReg(src, dest);
+            // Check if dest is negative
+            m_assembler.cmppz(dest);
+            return branchFalse();
+        }
+
+        m_assembler.addlRegReg(src, dest);
+        compare32(0, dest, Equal);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        move(imm, scratchReg3);
+        return branchAdd32(cond, scratchReg3, dest);
+    }
+
+    Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        if (cond == Overflow) {
+            RegisterID scr1 = claimScratch();
+            RegisterID scr = claimScratch();
+            m_assembler.dmullRegReg(src, dest);
+            m_assembler.stsmacl(dest);
+            m_assembler.movImm8(-31, scr);
+            m_assembler.movlRegReg(dest, scr1);
+            m_assembler.shaRegReg(scr1, scr);
+            m_assembler.stsmach(scr);
+            m_assembler.cmplRegReg(scr, scr1, SH4Condition(Equal));
+            releaseScratch(scr1);
+            releaseScratch(scr);
+            return branchFalse();
+        }
+
+        m_assembler.imullRegReg(src, dest);
+        m_assembler.stsmacl(dest);
+        if (cond == Signed) {
+            // Check if dest is negative
+            m_assembler.cmppz(dest);
+            return branchFalse();
+        }
+
+        compare32(0, dest, static_cast<RelationalCondition>(cond));
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        move(imm, scratchReg3);
+        if (src != dest)
+            move(src, dest);
+
+        return branchMul32(cond, scratchReg3, dest);
+    }
+
+    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        if (cond == Overflow) {
+            m_assembler.subvlRegReg(src, dest);
+            return branchTrue();
+        }
+
+        if (cond == Signed) {
+            // Check if dest is negative
+            m_assembler.sublRegReg(src, dest);
+            compare32(0, dest, LessThan);
+            return branchTrue();
+        }
+
+        sub32(src, dest);
+        compare32(0, dest, static_cast<RelationalCondition>(cond));
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        move(imm, scratchReg3);
+        return branchSub32(cond, scratchReg3, dest);
+    }
+
+    Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
+
+        if (cond == Signed) {
+            or32(src, dest);
+            compare32(0, dest, static_cast<RelationalCondition>(LessThan));
+            return branchTrue();
+        }
+
+        or32(src, dest);
+        compare32(0, dest, static_cast<RelationalCondition>(cond));
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+    {
+        m_assembler.ftrcdrmfpul(src);
+        m_assembler.stsfpulReg(dest);
+        convertInt32ToDouble(dest, fscratch);
+        failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src));
+
+        if (dest == SH4Registers::r0)
+            m_assembler.cmpEqImmR0(0, dest);
+        else {
+            m_assembler.movImm8(0, scratchReg3);
+            m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal));
+        }
+        failureCases.append(branchTrue());
+    }
+
+    void neg32(RegisterID dst)
+    {
+        m_assembler.neg(dst, dst);
+    }
+
+    void not32(RegisterID dst)
+    {
+        m_assembler.notlReg(dst, dst);
+    }
+
+    void urshift32(RegisterID shiftamount, RegisterID dest)
+    {
+        compare32(32, shiftamount, Equal);
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 4);
+        m_assembler.branch(BT_OPCODE, 1);
+        m_assembler.neg(shiftamount, shiftamount);
+        m_assembler.shllRegReg(dest, shiftamount);
+    }
+
+    void urshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        RegisterID scr = claimScratch();
+        m_assembler.loadConstant(-(imm.m_value), scr);
+        m_assembler.shaRegReg(dest, scr);
+        releaseScratch(scr);
+    }
+
+    Call call()
+    {
+        return Call(m_assembler.call(), Call::Linkable);
+    }
+
+    Call nearCall()
+    {
+        return Call(m_assembler.call(), Call::LinkableNear);
+    }
+
+    Call call(RegisterID target)
+    {
+        return Call(m_assembler.call(target), Call::None);
+    }
+
+    void call(Address address, RegisterID target)
+    {
+        load32(address.base, address.offset, target);
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
+        m_assembler.branch(JSR_OPCODE, target);
+        m_assembler.nop();
+    }
+
+    void breakpoint()
+    {
+        m_assembler.bkpt();
+        m_assembler.nop();
+    }
+
+    Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
+    {
+        RegisterID dataTempRegister = claimScratch();
+
+        dataLabel = moveWithPatch(initialRightValue, dataTempRegister);
+        m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond));
+        releaseScratch(dataTempRegister);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
+    {
+        RegisterID scr = claimScratch();
+
+        m_assembler.loadConstant(left.offset, scr);
+        m_assembler.addlRegReg(left.base, scr);
+        m_assembler.movlMemReg(scr, scr);
+        RegisterID scr1 = claimScratch();
+        dataLabel = moveWithPatch(initialRightValue, scr1);
+        m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond));
+        releaseScratch(scr);
+        releaseScratch(scr1);
+
+        if (cond == NotEqual)
+            return branchFalse();
+        return branchTrue();
+    }
+
+    void ret()
+    {
+        m_assembler.ret();
+        m_assembler.nop();
+    }
+
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
+    {
+        RegisterID scr = claimScratch();
+        DataLabelPtr label = moveWithPatch(initialValue, scr);
+        store32(scr, address);
+        releaseScratch(scr);
+        return label;
+    }
+
+    DataLabelPtr storePtrWithPatch(ImplicitAddress address) { return storePtrWithPatch(TrustedImmPtr(0), address); }
+
+    int sizeOfConstantPool()
+    {
+        return m_assembler.sizeOfConstantPool();
+    }
+
+    Call tailRecursiveCall()
+    {
+        RegisterID scr = claimScratch();
+
+        m_assembler.loadConstantUnReusable(0x0, scr, true);
+        Jump m_jump = Jump(m_assembler.jmp(scr));
+        releaseScratch(scr);
+
+        return Call::fromTailJump(m_jump);
+    }
+
+    Call makeTailRecursiveCall(Jump oldJump)
+    {
+        oldJump.link(this);
+        return tailRecursiveCall();
+    }
+
+    void nop()
+    {
+        m_assembler.nop();
+    }
+
+protected:
+    SH4Assembler::Condition SH4Condition(RelationalCondition cond)
+    {
+        return static_cast<SH4Assembler::Condition>(cond);
+    }
+
+    SH4Assembler::Condition SH4Condition(ResultCondition cond)
+    {
+        return static_cast<SH4Assembler::Condition>(cond);
+    }
+private:
+    friend class LinkBuffer;
+    friend class RepatchBuffer;
+
+    static void linkCall(void*, Call, FunctionPtr);
+    static void repatchCall(CodeLocationCall, CodeLocationLabel);
+    static void repatchCall(CodeLocationCall, FunctionPtr);
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER)
+
+#endif // MacroAssemblerSH4_h
index 0918996302022e211db69da6a2cd08f82f145d6b..a1657e6e01ecc2720c01b4e17eba2d04d274f79e 100644 (file)
@@ -52,32 +52,32 @@ public:
     using MacroAssemblerX86Common::loadDouble;
     using MacroAssemblerX86Common::convertInt32ToDouble;
 
-    void add32(Imm32 imm, RegisterID src, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         m_assembler.leal_mr(imm.m_value, src, dest);
     }
 
-    void add32(Imm32 imm, AbsoluteAddress address)
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.addl_im(imm.m_value, address.m_ptr);
     }
     
-    void addWithCarry32(Imm32 imm, AbsoluteAddress address)
+    void addWithCarry32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.adcl_im(imm.m_value, address.m_ptr);
     }
     
-    void and32(Imm32 imm, AbsoluteAddress address)
+    void and32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.andl_im(imm.m_value, address.m_ptr);
     }
     
-    void or32(Imm32 imm, AbsoluteAddress address)
+    void or32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.orl_im(imm.m_value, address.m_ptr);
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
         m_assembler.subl_im(imm.m_value, address.m_ptr);
     }
@@ -98,7 +98,7 @@ public:
         m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
     }
 
-    void store32(Imm32 imm, void* address)
+    void store32(TrustedImm32 imm, void* address)
     {
         m_assembler.movl_i32m(imm.m_value, address);
     }
@@ -108,13 +108,13 @@ public:
         m_assembler.movl_rm(src, address);
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
         m_assembler.cmpl_rm(right, left.m_ptr);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
+    Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
     {
         m_assembler.cmpl_im(right.m_value, left.m_ptr);
         return Jump(m_assembler.jCC(x86Condition(cond)));
@@ -136,39 +136,32 @@ public:
     }
 
 
-    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         m_assembler.movl_i32r(initialValue.asIntptr(), dest);
         return DataLabelPtr(this);
     }
 
-    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
         dataLabel = DataLabelPtr(this);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base);
         dataLabel = DataLabelPtr(this);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
         return DataLabelPtr(this);
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        Label label(this);
-        load32(address, dest);
-        return label;
-    }
-
     bool supportsFloatingPoint() const { return m_isSSE2Present; }
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
     bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
index 0731065ef73785a6f54625d2cef25cb08e2287c7..933b36b29327e6920327ddfc5dceb9b2a4aad1ac 100644 (file)
@@ -40,8 +40,10 @@ class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
 
 public:
     typedef X86Assembler::FPRegisterID FPRegisterID;
+    
+    static const int MaximumCompactPtrAlignedAddressOffset = 127;
 
-    enum Condition {
+    enum RelationalCondition {
         Equal = X86Assembler::ConditionE,
         NotEqual = X86Assembler::ConditionNE,
         Above = X86Assembler::ConditionA,
@@ -51,7 +53,10 @@ public:
         GreaterThan = X86Assembler::ConditionG,
         GreaterThanOrEqual = X86Assembler::ConditionGE,
         LessThan = X86Assembler::ConditionL,
-        LessThanOrEqual = X86Assembler::ConditionLE,
+        LessThanOrEqual = X86Assembler::ConditionLE
+    };
+
+    enum ResultCondition {
         Overflow = X86Assembler::ConditionO,
         Signed = X86Assembler::ConditionS,
         Zero = X86Assembler::ConditionE,
@@ -83,7 +88,7 @@ public:
     // Integer arithmetic operations:
     //
     // Operations are typically two operand - operation(source, srcDst)
-    // For many operations the source may be an Imm32, the srcDst operand
+    // For many operations the source may be an TrustedImm32, the srcDst operand
     // may often be a memory location (explictly described using an Address
     // object).
 
@@ -92,12 +97,12 @@ public:
         m_assembler.addl_rr(src, dest);
     }
 
-    void add32(Imm32 imm, Address address)
+    void add32(TrustedImm32 imm, Address address)
     {
         m_assembler.addl_im(imm.m_value, address.offset, address.base);
     }
 
-    void add32(Imm32 imm, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.addl_ir(imm.m_value, dest);
     }
@@ -117,7 +122,7 @@ public:
         m_assembler.andl_rr(src, dest);
     }
 
-    void and32(Imm32 imm, RegisterID dest)
+    void and32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.andl_ir(imm.m_value, dest);
     }
@@ -132,36 +137,64 @@ public:
         m_assembler.andl_mr(src.offset, src.base, dest);
     }
 
-    void and32(Imm32 imm, Address address)
+    void and32(TrustedImm32 imm, Address address)
     {
         m_assembler.andl_im(imm.m_value, address.offset, address.base);
     }
 
-    void lshift32(Imm32 imm, RegisterID dest)
+    void and32(RegisterID op1, RegisterID op2, RegisterID dest)
     {
-        m_assembler.shll_i8r(imm.m_value, dest);
+        if (op1 == op2)
+            zeroExtend32ToPtr(op1, dest);
+        else if (op1 == dest)
+            and32(op2, dest);
+        else {
+            move(op2, dest);
+            and32(op1, dest);
+        }
     }
-    
+
+    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(src, dest);
+        and32(imm, dest);
+    }
+
     void lshift32(RegisterID shift_amount, RegisterID dest)
     {
-        // On x86 we can only shift by ecx; if asked to shift by another register we'll
-        // need rejig the shift amount into ecx first, and restore the registers afterwards.
-        if (shift_amount != X86Registers::ecx) {
-            swap(shift_amount, X86Registers::ecx);
+        ASSERT(shift_amount != dest);
 
-            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
-            if (dest == shift_amount)
-                m_assembler.shll_CLr(X86Registers::ecx);
-            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
-            else if (dest == X86Registers::ecx)
-                m_assembler.shll_CLr(shift_amount);
-            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
-            else
-                m_assembler.shll_CLr(dest);
-        
-            swap(shift_amount, X86Registers::ecx);
-        } else
+        if (shift_amount == X86Registers::ecx)
             m_assembler.shll_CLr(dest);
+        else {
+            // On x86 we can only shift by ecx; if asked to shift by another register we'll
+            // need rejig the shift amount into ecx first, and restore the registers afterwards.
+            // If we dest is ecx, then shift the swapped register!
+            swap(shift_amount, X86Registers::ecx);
+            m_assembler.shll_CLr(dest == X86Registers::ecx ? shift_amount : dest);
+            swap(shift_amount, X86Registers::ecx);
+        }
+    }
+
+    void lshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
+    {
+        ASSERT(shift_amount != dest);
+
+        if (src != dest)
+            move(src, dest);
+        lshift32(shift_amount, dest);
+    }
+
+    void lshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.shll_i8r(imm.m_value, dest);
+    }
+    
+    void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+        lshift32(imm, dest);
     }
     
     void mul32(RegisterID src, RegisterID dest)
@@ -174,7 +207,7 @@ public:
         m_assembler.imull_mr(src.offset, src.base, dest);
     }
     
-    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+    void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         m_assembler.imull_i32r(src, imm.m_value, dest);
     }
@@ -204,7 +237,7 @@ public:
         m_assembler.orl_rr(src, dest);
     }
 
-    void or32(Imm32 imm, RegisterID dest)
+    void or32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.orl_ir(imm.m_value, dest);
     }
@@ -219,76 +252,114 @@ public:
         m_assembler.orl_mr(src.offset, src.base, dest);
     }
 
-    void or32(Imm32 imm, Address address)
+    void or32(TrustedImm32 imm, Address address)
     {
         m_assembler.orl_im(imm.m_value, address.offset, address.base);
     }
 
+    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        if (op1 == op2)
+            zeroExtend32ToPtr(op1, dest);
+        else if (op1 == dest)
+            or32(op2, dest);
+        else {
+            move(op2, dest);
+            or32(op1, dest);
+        }
+    }
+
+    void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(src, dest);
+        or32(imm, dest);
+    }
+
     void rshift32(RegisterID shift_amount, RegisterID dest)
     {
-        // On x86 we can only shift by ecx; if asked to shift by another register we'll
-        // need rejig the shift amount into ecx first, and restore the registers afterwards.
-        if (shift_amount != X86Registers::ecx) {
-            swap(shift_amount, X86Registers::ecx);
+        ASSERT(shift_amount != dest);
 
-            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
-            if (dest == shift_amount)
-                m_assembler.sarl_CLr(X86Registers::ecx);
-            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
-            else if (dest == X86Registers::ecx)
-                m_assembler.sarl_CLr(shift_amount);
-            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
-            else
-                m_assembler.sarl_CLr(dest);
-        
-            swap(shift_amount, X86Registers::ecx);
-        } else
+        if (shift_amount == X86Registers::ecx)
             m_assembler.sarl_CLr(dest);
+        else {
+            // On x86 we can only shift by ecx; if asked to shift by another register we'll
+            // need rejig the shift amount into ecx first, and restore the registers afterwards.
+            // If we dest is ecx, then shift the swapped register!
+            swap(shift_amount, X86Registers::ecx);
+            m_assembler.sarl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
+            swap(shift_amount, X86Registers::ecx);
+        }
     }
 
-    void rshift32(Imm32 imm, RegisterID dest)
+    void rshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
+    {
+        ASSERT(shift_amount != dest);
+
+        if (src != dest)
+            move(src, dest);
+        rshift32(shift_amount, dest);
+    }
+
+    void rshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.sarl_i8r(imm.m_value, dest);
     }
     
+    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+        rshift32(imm, dest);
+    }
+    
     void urshift32(RegisterID shift_amount, RegisterID dest)
     {
-        // On x86 we can only shift by ecx; if asked to shift by another register we'll
-        // need rejig the shift amount into ecx first, and restore the registers afterwards.
-        if (shift_amount != X86Registers::ecx) {
+        ASSERT(shift_amount != dest);
+
+        if (shift_amount == X86Registers::ecx)
+            m_assembler.shrl_CLr(dest);
+        else {
+            // On x86 we can only shift by ecx; if asked to shift by another register we'll
+            // need rejig the shift amount into ecx first, and restore the registers afterwards.
+            // If we dest is ecx, then shift the swapped register!
             swap(shift_amount, X86Registers::ecx);
-            
-            // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx"
-            if (dest == shift_amount)
-                m_assembler.shrl_CLr(X86Registers::ecx);
-            // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx"
-            else if (dest == X86Registers::ecx)
-                m_assembler.shrl_CLr(shift_amount);
-            // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx"
-            else
-                m_assembler.shrl_CLr(dest);
-            
+            m_assembler.shrl_CLr(dest == X86Registers::ecx ? shift_amount : dest);
             swap(shift_amount, X86Registers::ecx);
-        } else
-            m_assembler.shrl_CLr(dest);
+        }
     }
-    
-    void urshift32(Imm32 imm, RegisterID dest)
+
+    void urshift32(RegisterID src, RegisterID shift_amount, RegisterID dest)
     {
-        m_assembler.shrl_i8r(imm.m_value, dest);
+        ASSERT(shift_amount != dest);
+
+        if (src != dest)
+            move(src, dest);
+        urshift32(shift_amount, dest);
     }
 
+    void urshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.shrl_i8r(imm.m_value, dest);
+    }
+    
+    void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        if (src != dest)
+            move(src, dest);
+        urshift32(imm, dest);
+    }
+    
     void sub32(RegisterID src, RegisterID dest)
     {
         m_assembler.subl_rr(src, dest);
     }
     
-    void sub32(Imm32 imm, RegisterID dest)
+    void sub32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.subl_ir(imm.m_value, dest);
     }
     
-    void sub32(Imm32 imm, Address address)
+    void sub32(TrustedImm32 imm, Address address)
     {
         m_assembler.subl_im(imm.m_value, address.offset, address.base);
     }
@@ -309,12 +380,12 @@ public:
         m_assembler.xorl_rr(src, dest);
     }
 
-    void xor32(Imm32 imm, Address dest)
+    void xor32(TrustedImm32 imm, Address dest)
     {
         m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
     }
 
-    void xor32(Imm32 imm, RegisterID dest)
+    void xor32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.xorl_ir(imm.m_value, dest);
     }
@@ -329,6 +400,24 @@ public:
         m_assembler.xorl_mr(src.offset, src.base, dest);
     }
     
+    void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        if (op1 == op2)
+            move(TrustedImm32(0), dest);
+        else if (op1 == dest)
+            xor32(op2, dest);
+        else {
+            move(op2, dest);
+            xor32(op1, dest);
+        }
+    }
+
+    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(src, dest);
+        xor32(imm, dest);
+    }
+
     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
     {
         m_assembler.sqrtsd_rr(src, dst);
@@ -337,7 +426,7 @@ public:
     // Memory access operations:
     //
     // Loads are of the form load(address, destination) and stores of the form
-    // store(source, address).  The source for a store may be an Imm32.  Address
+    // store(source, address).  The source for a store may be an TrustedImm32.  Address
     // operand objects to loads and store will be implicitly constructed if a
     // register is passed.
 
@@ -361,6 +450,25 @@ public:
         m_assembler.movl_mr_disp32(address.offset, address.base, dest);
         return DataLabel32(this);
     }
+    
+    DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        m_assembler.movl_mr_disp8(address.offset, address.base, dest);
+        return DataLabelCompact(this);
+    }
+    
+    static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
+    {
+        ASSERT(value >= 0);
+        ASSERT(value < MaximumCompactPtrAlignedAddressOffset);
+        AssemblerType_T::repatchCompact(dataLabelCompact.dataLocation(), value);
+    }
+    
+    DataLabelCompact loadCompactWithAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        m_assembler.movl_mr_disp8(address.offset, address.base, dest);
+        return DataLabelCompact(this);
+    }
 
     void load16(BaseIndex address, RegisterID dest)
     {
@@ -388,7 +496,7 @@ public:
         m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
     }
 
-    void store32(Imm32 imm, ImplicitAddress address)
+    void store32(TrustedImm32 imm, ImplicitAddress address)
     {
         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
     }
@@ -398,6 +506,13 @@ public:
     //
     // Presently only supports SSE, not x87 floating point.
 
+    void moveDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        if (src != dest)
+            m_assembler.movsd_rr(src, dest);
+    }
+
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -416,6 +531,17 @@ public:
         m_assembler.addsd_rr(src, dest);
     }
 
+    void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        if (op1 == dest)
+            addDouble(op2, dest);
+        else {
+            moveDouble(op2, dest);
+            addDouble(op1, dest);
+        }
+    }
+
     void addDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -428,6 +554,15 @@ public:
         m_assembler.divsd_rr(src, dest);
     }
 
+    void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        // B := A / B is invalid.
+        ASSERT(op1 == dest || op2 != dest);
+
+        moveDouble(op1, dest);
+        divDouble(op2, dest);
+    }
+
     void divDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -440,6 +575,15 @@ public:
         m_assembler.subsd_rr(src, dest);
     }
 
+    void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        // B := A - B is invalid.
+        ASSERT(op1 == dest || op2 != dest);
+
+        moveDouble(op1, dest);
+        subDouble(op2, dest);
+    }
+
     void subDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -452,6 +596,17 @@ public:
         m_assembler.mulsd_rr(src, dest);
     }
 
+    void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        ASSERT(isSSE2Present());
+        if (op1 == dest)
+            mulDouble(op2, dest);
+        else {
+            moveDouble(op2, dest);
+            mulDouble(op1, dest);
+        }
+    }
+
     void mulDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -501,11 +656,12 @@ public:
     // If the result is not representable as a 32 bit value, branch.
     // May also branch for some values that are representable in 32 bits
     // (specifically, in this case, INT_MIN).
-    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
+    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
     {
         ASSERT(isSSE2Present());
         m_assembler.cvttsd2si_rr(src, dest);
-        return branch32(Equal, dest, Imm32(0x80000000));
+        return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.
@@ -564,7 +720,7 @@ public:
         m_assembler.push_m(address.offset, address.base);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         m_assembler.push_i32(imm.m_value);
     }
@@ -574,9 +730,9 @@ public:
     //
     // Move values in registers.
 
-    void move(Imm32 imm, RegisterID dest)
+    void move(TrustedImm32 imm, RegisterID dest)
     {
-        // Note: on 64-bit the Imm32 value is zero extended into the register, it
+        // Note: on 64-bit the TrustedImm32 value is zero extended into the register, it
         // may be useful to have a separate version that sign extends the value?
         if (!imm.m_value)
             m_assembler.xorl_rr(dest, dest);
@@ -593,7 +749,7 @@ public:
             m_assembler.movq_rr(src, dest);
     }
 
-    void move(ImmPtr imm, RegisterID dest)
+    void move(TrustedImmPtr imm, RegisterID dest)
     {
         m_assembler.movq_i64r(imm.asIntptr(), dest);
     }
@@ -620,7 +776,7 @@ public:
             m_assembler.movl_rr(src, dest);
     }
 
-    void move(ImmPtr imm, RegisterID dest)
+    void move(TrustedImmPtr imm, RegisterID dest)
     {
         m_assembler.movl_i32r(imm.asIntptr(), dest);
     }
@@ -655,26 +811,26 @@ public:
     // used (representing the names 'below' and 'above').
     //
     // Operands to the comparision are provided in the expected order, e.g.
-    // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
+    // jle32(reg1, TrustedImm32(5)) will branch if the value held in reg1, when
     // treated as a signed 32bit value, is less than or equal to 5.
     //
     // jz and jnz test whether the first operand is equal to zero, and take
     // an optional second operand of a mask under which to perform the test.
 
 public:
-    Jump branch8(Condition cond, Address left, Imm32 right)
+    Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         m_assembler.cmpb_im(right.m_value, left.offset, left.base);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch32(Condition cond, RegisterID left, RegisterID right)
+    Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         m_assembler.cmpl_rr(right, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch32(Condition cond, RegisterID left, Imm32 right)
+    Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right)
     {
         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
             m_assembler.testl_rr(left, left);
@@ -683,42 +839,51 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branch32(Condition cond, RegisterID left, Address right)
+    Jump branch32(RelationalCondition cond, TrustedImm32 left, RegisterID right)
+    {
+        if (((cond == Equal) || (cond == NotEqual)) && !left.m_value)
+            m_assembler.testl_rr(right, right);
+        else
+            m_assembler.cmpl_ir(left.m_value, right);
+        return Jump(m_assembler.jCC(x86Condition(commute(cond))));
+    }
+    
+    Jump branch32(RelationalCondition cond, RegisterID left, Address right)
     {
         m_assembler.cmpl_mr(right.offset, right.base, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branch32(Condition cond, Address left, RegisterID right)
+    Jump branch32(RelationalCondition cond, Address left, RegisterID right)
     {
         m_assembler.cmpl_rm(right, left.offset, left.base);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch32(Condition cond, Address left, Imm32 right)
+    Jump branch32(RelationalCondition cond, Address left, TrustedImm32 right)
     {
         m_assembler.cmpl_im(right.m_value, left.offset, left.base);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch32(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch32WithUnalignedHalfWords(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         return branch32(cond, left, right);
     }
 
-    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
     {
         m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
+    Jump branch16(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
     {
         ASSERT(!(right.m_value & 0xFFFF0000));
 
@@ -726,16 +891,14 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+    Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         m_assembler.testl_rr(reg, mask);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         // if we are only interested in the low seven bits, this can be tested with a testb
         if (mask.m_value == -1)
             m_assembler.testl_rr(reg, reg);
@@ -746,9 +909,8 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         if (mask.m_value == -1)
             m_assembler.cmpl_im(0, address.offset, address.base);
         else
@@ -756,9 +918,8 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
         if (mask.m_value == -1)
             m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
         else
@@ -766,9 +927,21 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
+        // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
+        ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
+        if (mask.m_value == -1)
+            m_assembler.testb_rr(reg, reg);
+        else
+            m_assembler.testb_i8r(mask.m_value, reg);
+        return Jump(m_assembler.jCC(x86Condition(cond)));
+    }
+
+    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
+        ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
         if (mask.m_value == -1)
             m_assembler.cmpb_im(0, address.offset, address.base);
         else
@@ -776,9 +949,10 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ASSERT((cond == Zero) || (cond == NonZero));
+        // Byte in TrustedImm32 is not well defined, so be a little permisive here, but don't accept nonsense values.
+        ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
         if (mask.m_value == -1)
             m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
         else
@@ -813,107 +987,135 @@ public:
     // * jo operations branch if the (signed) arithmetic
     //   operation caused an overflow to occur.
     
-    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         add32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         add32(imm, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchAdd32(Condition cond, Imm32 src, Address dest)
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 src, Address dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         add32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchAdd32(Condition cond, RegisterID src, Address dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID src, Address dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         add32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchAdd32(Condition cond, Address src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         add32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
+    {
+        if (src1 == dest)
+            return branchAdd32(cond, src2, dest);
+        move(src2, dest);
+        return branchAdd32(cond, src1, dest);
+    }
+
+    Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(src, dest);
+        return branchAdd32(cond, imm, dest);
+    }
+
+    Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT(cond == Overflow);
         mul32(src, dest);
+        if (cond != Overflow)
+            m_assembler.testl_rr(dest, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchMul32(Condition cond, Address src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, Address src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         mul32(src, dest);
+        if (cond != Overflow)
+            m_assembler.testl_rr(dest, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
-        ASSERT(cond == Overflow);
         mul32(imm, src, dest);
+        if (cond != Overflow)
+            m_assembler.testl_rr(dest, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
+    {
+        if (src1 == dest)
+            return branchMul32(cond, src2, dest);
+        move(src2, dest);
+        return branchMul32(cond, src1, dest);
+    }
+
+    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         sub32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
-    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         sub32(imm, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchSub32(Condition cond, Imm32 imm, Address dest)
+    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, Address dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         sub32(imm, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchSub32(Condition cond, RegisterID src, Address dest)
+    Jump branchSub32(ResultCondition cond, RegisterID src, Address dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         sub32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchSub32(Condition cond, Address src, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, Address src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         sub32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchNeg32(Condition cond, RegisterID srcDest)
+    Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest)
+    {
+        // B := A - B is invalid.
+        ASSERT(src1 == dest || src2 != dest);
+
+        move(src1, dest);
+        return branchSub32(cond, src2, dest);
+    }
+
+    Jump branchSub32(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
+    {
+        move(src1, dest);
+        return branchSub32(cond, src2, dest);
+    }
+
+    Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         neg32(srcDest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
         or32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
@@ -946,35 +1148,14 @@ public:
         m_assembler.ret();
     }
 
-    void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
-    {
-        m_assembler.cmpl_rr(right, left);
-        m_assembler.setCC_r(x86Condition(cond), dest);
-    }
-
-    void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
-    {
-        m_assembler.cmpl_mr(left.offset, left.base, right);
-        m_assembler.setCC_r(x86Condition(cond), dest);
-    }
-
-    void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
-    {
-        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
-            m_assembler.testl_rr(left, left);
-        else
-            m_assembler.cmpl_ir(right.m_value, left);
-        m_assembler.setCC_r(x86Condition(cond), dest);
-    }
-
-    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
     {
         m_assembler.cmpl_rr(right, left);
         m_assembler.setCC_r(x86Condition(cond), dest);
         m_assembler.movzbl_rr(dest, dest);
     }
 
-    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
             m_assembler.testl_rr(left, left);
@@ -989,7 +1170,7 @@ public:
     // dest-src, operations always have a dest? ... possibly not true, considering
     // asm ops like test, or pseudo ops like pop().
 
-    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test8(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
         if (mask.m_value == -1)
             m_assembler.cmpb_im(0, address.offset, address.base);
@@ -999,7 +1180,7 @@ public:
         m_assembler.movzbl_rr(dest, dest);
     }
 
-    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
     {
         if (mask.m_value == -1)
             m_assembler.cmpl_im(0, address.offset, address.base);
@@ -1009,8 +1190,43 @@ public:
         m_assembler.movzbl_rr(dest, dest);
     }
 
+    // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
+    static RelationalCondition invert(RelationalCondition cond)
+    {
+        return static_cast<RelationalCondition>(cond ^ 1);
+    }
+
+    // Commute a relational condition, returns a new condition that will produce
+    // the same results given the same inputs but with their positions exchanged.
+    static RelationalCondition commute(RelationalCondition cond)
+    {
+        // Equality is commutative!
+        if (cond == Equal || cond == NotEqual)
+            return cond;
+
+        // Based on the values of x86 condition codes, remap > with < and >= with <=
+        if (cond >= LessThan) {
+            ASSERT(cond == LessThan || cond == LessThanOrEqual || cond == GreaterThan || cond == GreaterThanOrEqual);
+            return static_cast<RelationalCondition>(X86Assembler::ConditionL + X86Assembler::ConditionG - cond);
+        }
+
+        // As above, for unsigned conditions.
+        ASSERT(cond == Below || cond == BelowOrEqual || cond == Above || cond == AboveOrEqual);
+        return static_cast<RelationalCondition>(X86Assembler::ConditionB + X86Assembler::ConditionA - cond);
+    }
+    
+    void nop()
+    {
+        m_assembler.nop();
+    }
+
 protected:
-    X86Assembler::Condition x86Condition(Condition cond)
+    X86Assembler::Condition x86Condition(RelationalCondition cond)
+    {
+        return static_cast<X86Assembler::Condition>(cond);
+    }
+
+    X86Assembler::Condition x86Condition(ResultCondition cond)
     {
         return static_cast<X86Assembler::Condition>(cond);
     }
index 168c93f650d1d501e2087a57014584e734b610c2..b95bc2ee75765ea22da91e2e8b4510c475ef4a3e 100644 (file)
@@ -48,30 +48,31 @@ public:
     using MacroAssemblerX86Common::load32;
     using MacroAssemblerX86Common::store32;
     using MacroAssemblerX86Common::call;
+    using MacroAssemblerX86Common::addDouble;
     using MacroAssemblerX86Common::loadDouble;
     using MacroAssemblerX86Common::convertInt32ToDouble;
 
-    void add32(Imm32 imm, AbsoluteAddress address)
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
-        move(ImmPtr(address.m_ptr), scratchRegister);
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
         add32(imm, Address(scratchRegister));
     }
     
-    void and32(Imm32 imm, AbsoluteAddress address)
+    void and32(TrustedImm32 imm, AbsoluteAddress address)
     {
-        move(ImmPtr(address.m_ptr), scratchRegister);
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
         and32(imm, Address(scratchRegister));
     }
     
-    void or32(Imm32 imm, AbsoluteAddress address)
+    void or32(TrustedImm32 imm, AbsoluteAddress address)
     {
-        move(ImmPtr(address.m_ptr), scratchRegister);
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
         or32(imm, Address(scratchRegister));
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
-        move(ImmPtr(address.m_ptr), scratchRegister);
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
         sub32(imm, Address(scratchRegister));
     }
 
@@ -88,17 +89,23 @@ public:
 
     void loadDouble(const void* address, FPRegisterID dest)
     {
-        move(ImmPtr(address), scratchRegister);
+        move(TrustedImmPtr(address), scratchRegister);
         loadDouble(scratchRegister, dest);
     }
 
-    void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+    void addDouble(AbsoluteAddress address, FPRegisterID dest)
     {
-        move(Imm32(*static_cast<int32_t*>(src.m_ptr)), scratchRegister);
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
+        m_assembler.addsd_mr(0, scratchRegister, dest);
+    }
+
+    void convertInt32ToDouble(TrustedImm32 imm, FPRegisterID dest)
+    {
+        move(imm, scratchRegister);
         m_assembler.cvtsi2sd_rr(scratchRegister, dest);
     }
 
-    void store32(Imm32 imm, void* address)
+    void store32(TrustedImm32 imm, void* address)
     {
         move(X86Registers::eax, scratchRegister);
         move(imm, X86Registers::eax);
@@ -108,26 +115,26 @@ public:
 
     Call call()
     {
-        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+        DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
         Call result = Call(m_assembler.call(scratchRegister), Call::Linkable);
-        ASSERT(differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11);
+        ASSERT_UNUSED(label, differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11);
         return result;
     }
 
     Call tailRecursiveCall()
     {
-        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+        DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
         Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
-        ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
+        ASSERT_UNUSED(label, differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
         return Call::fromTailJump(newJump);
     }
 
     Call makeTailRecursiveCall(Jump oldJump)
     {
         oldJump.link(this);
-        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+        DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
         Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
-        ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
+        ASSERT_UNUSED(label, differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
         return Call::fromTailJump(newJump);
     }
 
@@ -137,30 +144,30 @@ public:
         m_assembler.addq_rr(src, dest);
     }
 
-    void addPtr(Imm32 imm, RegisterID srcDest)
+    void addPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         m_assembler.addq_ir(imm.m_value, srcDest);
     }
 
-    void addPtr(ImmPtr imm, RegisterID dest)
+    void addPtr(TrustedImmPtr imm, RegisterID dest)
     {
         move(imm, scratchRegister);
         m_assembler.addq_rr(scratchRegister, dest);
     }
 
-    void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
+    void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         m_assembler.leaq_mr(imm.m_value, src, dest);
     }
 
-    void addPtr(Imm32 imm, Address address)
+    void addPtr(TrustedImm32 imm, Address address)
     {
         m_assembler.addq_im(imm.m_value, address.offset, address.base);
     }
 
-    void addPtr(Imm32 imm, AbsoluteAddress address)
+    void addPtr(TrustedImm32 imm, AbsoluteAddress address)
     {
-        move(ImmPtr(address.m_ptr), scratchRegister);
+        move(TrustedImmPtr(address.m_ptr), scratchRegister);
         addPtr(imm, Address(scratchRegister));
     }
     
@@ -169,7 +176,7 @@ public:
         m_assembler.andq_rr(src, dest);
     }
 
-    void andPtr(Imm32 imm, RegisterID srcDest)
+    void andPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         m_assembler.andq_ir(imm.m_value, srcDest);
     }
@@ -179,28 +186,46 @@ public:
         m_assembler.orq_rr(src, dest);
     }
 
-    void orPtr(ImmPtr imm, RegisterID dest)
+    void orPtr(TrustedImmPtr imm, RegisterID dest)
     {
         move(imm, scratchRegister);
         m_assembler.orq_rr(scratchRegister, dest);
     }
 
-    void orPtr(Imm32 imm, RegisterID dest)
+    void orPtr(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.orq_ir(imm.m_value, dest);
     }
 
+    void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        if (op1 == op2)
+            move(op1, dest);
+        else if (op1 == dest)
+            orPtr(op2, dest);
+        else {
+            move(op2, dest);
+            orPtr(op1, dest);
+        }
+    }
+
+    void orPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(src, dest);
+        orPtr(imm, dest);
+    }
+
     void subPtr(RegisterID src, RegisterID dest)
     {
         m_assembler.subq_rr(src, dest);
     }
     
-    void subPtr(Imm32 imm, RegisterID dest)
+    void subPtr(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.subq_ir(imm.m_value, dest);
     }
     
-    void subPtr(ImmPtr imm, RegisterID dest)
+    void subPtr(TrustedImmPtr imm, RegisterID dest)
     {
         move(imm, scratchRegister);
         m_assembler.subq_rr(scratchRegister, dest);
@@ -211,7 +236,7 @@ public:
         m_assembler.xorq_rr(src, dest);
     }
 
-    void xorPtr(Imm32 imm, RegisterID srcDest)
+    void xorPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         m_assembler.xorq_ir(imm.m_value, srcDest);
     }
@@ -227,7 +252,7 @@ public:
         m_assembler.movq_mr(address.offset, address.base, address.index, address.scale, dest);
     }
 
-    void loadPtr(void* address, RegisterID dest)
+    void loadPtr(const void* address, RegisterID dest)
     {
         if (dest == X86Registers::eax)
             m_assembler.movq_mEAX(address);
@@ -243,6 +268,12 @@ public:
         m_assembler.movq_mr_disp32(address.offset, address.base, dest);
         return DataLabel32(this);
     }
+    
+    DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        m_assembler.movq_mr_disp8(address.offset, address.base, dest);
+        return DataLabelCompact(this);
+    }
 
     void storePtr(RegisterID src, ImplicitAddress address)
     {
@@ -265,7 +296,7 @@ public:
         }
     }
 
-    void storePtr(ImmPtr imm, ImplicitAddress address)
+    void storePtr(TrustedImmPtr imm, ImplicitAddress address)
     {
         move(imm, scratchRegister);
         storePtr(scratchRegister, address);
@@ -287,7 +318,7 @@ public:
         m_assembler.movq_rr(src, dest);
     }
 
-    void setPtr(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
     {
         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
             m_assembler.testq_rr(left, left);
@@ -297,49 +328,49 @@ public:
         m_assembler.movzbl_rr(dest, dest);
     }
 
-    Jump branchPtr(Condition cond, RegisterID left, RegisterID right)
+    Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         m_assembler.cmpq_rr(right, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchPtr(Condition cond, RegisterID left, ImmPtr right)
+    Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
     {
         move(right, scratchRegister);
         return branchPtr(cond, left, scratchRegister);
     }
 
-    Jump branchPtr(Condition cond, RegisterID left, Address right)
+    Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
     {
         m_assembler.cmpq_mr(right.offset, right.base, left);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchPtr(Condition cond, AbsoluteAddress left, RegisterID right)
+    Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
     {
-        move(ImmPtr(left.m_ptr), scratchRegister);
+        move(TrustedImmPtr(left.m_ptr), scratchRegister);
         return branchPtr(cond, Address(scratchRegister), right);
     }
 
-    Jump branchPtr(Condition cond, Address left, RegisterID right)
+    Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
     {
         m_assembler.cmpq_rm(right, left.offset, left.base);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchPtr(Condition cond, Address left, ImmPtr right)
+    Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
     {
         move(right, scratchRegister);
         return branchPtr(cond, left, scratchRegister);
     }
 
-    Jump branchTestPtr(Condition cond, RegisterID reg, RegisterID mask)
+    Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         m_assembler.testq_rr(reg, mask);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTestPtr(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
     {
         // if we are only interested in the low seven bits, this can be tested with a testb
         if (mask.m_value == -1)
@@ -351,7 +382,13 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTestPtr(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        loadPtr(address.m_ptr, scratchRegister);
+        return branchTestPtr(cond, scratchRegister, mask);
+    }
+
+    Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         if (mask.m_value == -1)
             m_assembler.cmpq_im(0, address.offset, address.base);
@@ -360,7 +397,7 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchTestPtr(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
         if (mask.m_value == -1)
             m_assembler.cmpq_im(0, address.offset, address.base, address.index, address.scale);
@@ -370,39 +407,37 @@ public:
     }
 
 
-    Jump branchAddPtr(Condition cond, RegisterID src, RegisterID dest)
+    Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         addPtr(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    Jump branchSubPtr(Condition cond, Imm32 imm, RegisterID dest)
+    Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
         subPtr(imm, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
-    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         m_assembler.movq_i64r(initialValue.asIntptr(), dest);
         return DataLabelPtr(this);
     }
 
-    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         dataLabel = moveWithPatch(initialRightValue, scratchRegister);
         return branchPtr(cond, left, scratchRegister);
     }
 
-    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
     {
         dataLabel = moveWithPatch(initialRightValue, scratchRegister);
         return branchPtr(cond, left, scratchRegister);
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         DataLabelPtr label = moveWithPatch(initialValue, scratchRegister);
         storePtr(scratchRegister, address);
@@ -410,20 +445,13 @@ public:
     }
 
     using MacroAssemblerX86Common::branchTest8;
-    Jump branchTest8(Condition cond, ExtendedAddress address, Imm32 mask = Imm32(-1))
+    Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        ImmPtr addr(reinterpret_cast<void*>(address.offset));
+        TrustedImmPtr addr(reinterpret_cast<void*>(address.offset));
         MacroAssemblerX86Common::move(addr, scratchRegister);
         return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask);
     }
 
-    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
-    {
-        Label label(this);
-        loadPtr(address, dest);
-        return label;
-    }
-
     bool supportsFloatingPoint() const { return true; }
     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
     bool supportsFloatingPointTruncate() const { return true; }
@@ -436,7 +464,7 @@ private:
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
         if (!call.isFlagSet(Call::Near))
-            X86Assembler::linkPointer(code, X86Assembler::labelFor(call.m_jmp, -REPTACH_OFFSET_CALL_R11), function.value());
+            X86Assembler::linkPointer(code, call.m_jmp.labelAtOffset(-REPTACH_OFFSET_CALL_R11), function.value());
         else
             X86Assembler::linkCall(code, call.m_jmp, function.value());
     }
index 72cf6b27f09e3507e9cdfec0c7cff904260cc03f..6ea6d8df3f6443bbcfa4e3e65dce4775790d08e6 100644 (file)
@@ -87,14 +87,14 @@ public:
         MacroAssembler::repatchInt32(dataLabel32, value);
     }
 
-    void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value)
+    void repatch(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
     {
-        MacroAssembler::repatchPointer(dataLabelPtr, value);
+        MacroAssembler::repatchCompact(dataLabelCompact, value);
     }
 
-    void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
+    void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value)
     {
-        MacroAssembler::repatchLoadPtrToLEA(instruction);
+        MacroAssembler::repatchPointer(dataLabelPtr, value);
     }
 
     void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label)
diff --git a/assembler/SH4Assembler.h b/assembler/SH4Assembler.h
new file mode 100644 (file)
index 0000000..1d089e5
--- /dev/null
@@ -0,0 +1,2026 @@
+/*
+ * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved.
+ * Copyright (C) 2008 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 SH4Assembler_h
+#define SH4Assembler_h
+
+#if ENABLE(ASSEMBLER) && CPU(SH4)
+
+#include "AssemblerBuffer.h"
+#include "AssemblerBufferWithConstantPool.h"
+#include <stdarg.h>
+#include <stdint.h>
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+#ifndef NDEBUG
+#define SH4_ASSEMBLER_TRACING
+#endif
+
+namespace JSC {
+typedef uint16_t SH4Word;
+
+enum {
+    INVALID_OPCODE = 0xffff,
+    ADD_OPCODE = 0x300c,
+    ADDIMM_OPCODE = 0x7000,
+    ADDC_OPCODE = 0x300e,
+    ADDV_OPCODE = 0x300f,
+    AND_OPCODE = 0x2009,
+    ANDIMM_OPCODE = 0xc900,
+    DIV0_OPCODE = 0x2007,
+    DIV1_OPCODE = 0x3004,
+    BF_OPCODE = 0x8b00,
+    BFS_OPCODE = 0x8f00,
+    BRA_OPCODE = 0xa000,
+    BRAF_OPCODE = 0x0023,
+    NOP_OPCODE = 0x0009,
+    BSR_OPCODE = 0xb000,
+    RTS_OPCODE = 0x000b,
+    BT_OPCODE = 0x8900,
+    BTS_OPCODE = 0x8d00,
+    BSRF_OPCODE = 0x0003,
+    BRK_OPCODE = 0x003b,
+    FTRC_OPCODE = 0xf03d,
+    CMPEQ_OPCODE = 0x3000,
+    CMPEQIMM_OPCODE = 0x8800,
+    CMPGE_OPCODE = 0x3003,
+    CMPGT_OPCODE = 0x3007,
+    CMPHI_OPCODE = 0x3006,
+    CMPHS_OPCODE = 0x3002,
+    CMPPL_OPCODE = 0x4015,
+    CMPPZ_OPCODE = 0x4011,
+    CMPSTR_OPCODE = 0x200c,
+    DT_OPCODE = 0x4010,
+    FCMPEQ_OPCODE = 0xf004,
+    FCMPGT_OPCODE = 0xf005,
+    FMOV_OPCODE = 0xf00c,
+    FADD_OPCODE = 0xf000,
+    FMUL_OPCODE = 0xf002,
+    FSUB_OPCODE = 0xf001,
+    FDIV_OPCODE = 0xf003,
+    FNEG_OPCODE = 0xf04d,
+    JMP_OPCODE = 0x402b,
+    JSR_OPCODE = 0x400b,
+    LDSPR_OPCODE = 0x402a,
+    LDSLPR_OPCODE = 0x4026,
+    MOV_OPCODE = 0x6003,
+    MOVIMM_OPCODE = 0xe000,
+    MOVB_WRITE_RN_OPCODE = 0x2000,
+    MOVB_WRITE_RNDEC_OPCODE = 0x2004,
+    MOVB_WRITE_R0RN_OPCODE = 0x0004,
+    MOVB_WRITE_OFFGBR_OPCODE = 0xc000,
+    MOVB_WRITE_OFFRN_OPCODE = 0x8000,
+    MOVB_READ_RM_OPCODE = 0x6000,
+    MOVB_READ_RMINC_OPCODE = 0x6004,
+    MOVB_READ_R0RM_OPCODE = 0x000c,
+    MOVB_READ_OFFGBR_OPCODE = 0xc400,
+    MOVB_READ_OFFRM_OPCODE = 0x8400,
+    MOVL_WRITE_RN_OPCODE = 0x2002,
+    MOVL_WRITE_RNDEC_OPCODE = 0x2006,
+    MOVL_WRITE_R0RN_OPCODE = 0x0006,
+    MOVL_WRITE_OFFGBR_OPCODE = 0xc200,
+    MOVL_WRITE_OFFRN_OPCODE = 0x1000,
+    MOVL_READ_RM_OPCODE = 0x6002,
+    MOVL_READ_RMINC_OPCODE = 0x6006,
+    MOVL_READ_R0RM_OPCODE = 0x000e,
+    MOVL_READ_OFFGBR_OPCODE = 0xc600,
+    MOVL_READ_OFFPC_OPCODE = 0xd000,
+    MOVL_READ_OFFRM_OPCODE = 0x5000,
+    MOVW_WRITE_RN_OPCODE = 0x2001,
+    MOVW_READ_RM_OPCODE = 0x6001,
+    MOVW_READ_R0RM_OPCODE = 0x000d,
+    MOVW_READ_OFFRM_OPCODE = 0x8500,
+    MOVW_READ_OFFPC_OPCODE = 0x9000,
+    MOVA_READ_OFFPC_OPCODE = 0xc700,
+    MOVT_OPCODE = 0x0029,
+    MULL_OPCODE = 0x0007,
+    DMULL_L_OPCODE = 0x3005,
+    STSMACL_OPCODE = 0x001a,
+    STSMACH_OPCODE = 0x000a,
+    DMULSL_OPCODE = 0x300d,
+    NEG_OPCODE = 0x600b,
+    NEGC_OPCODE = 0x600a,
+    NOT_OPCODE = 0x6007,
+    OR_OPCODE = 0x200b,
+    ORIMM_OPCODE = 0xcb00,
+    ORBIMM_OPCODE = 0xcf00,
+    SETS_OPCODE = 0x0058,
+    SETT_OPCODE = 0x0018,
+    SHAD_OPCODE = 0x400c,
+    SHAL_OPCODE = 0x4020,
+    SHAR_OPCODE = 0x4021,
+    SHLD_OPCODE = 0x400d,
+    SHLL_OPCODE = 0x4000,
+    SHLL2_OPCODE = 0x4008,
+    SHLL8_OPCODE = 0x4018,
+    SHLL16_OPCODE = 0x4028,
+    SHLR_OPCODE = 0x4001,
+    SHLR2_OPCODE = 0x4009,
+    SHLR8_OPCODE = 0x4019,
+    SHLR16_OPCODE = 0x4029,
+    STSPR_OPCODE = 0x002a,
+    STSLPR_OPCODE = 0x4022,
+    FLOAT_OPCODE = 0xf02d,
+    SUB_OPCODE = 0x3008,
+    SUBC_OPCODE = 0x300a,
+    SUBV_OPCODE = 0x300b,
+    TST_OPCODE = 0x2008,
+    TSTIMM_OPCODE = 0xc800,
+    TSTB_OPCODE = 0xcc00,
+    EXTUW_OPCODE = 0x600d,
+    XOR_OPCODE = 0x200a,
+    XORIMM_OPCODE = 0xca00,
+    XORB_OPCODE = 0xce00,
+    FMOVS_READ_RM_INC_OPCODE = 0xf009,
+    FMOVS_READ_RM_OPCODE = 0xf008,
+    FMOVS_READ_R0RM_OPCODE = 0xf006,
+    FMOVS_WRITE_RN_OPCODE = 0xf00a,
+    FMOVS_WRITE_RN_DEC_OPCODE = 0xf00b,
+    FMOVS_WRITE_R0RN_OPCODE = 0xf007,
+    FCNVDS_DRM_FPUL_OPCODE = 0xf0bd,
+    LDS_RM_FPUL_OPCODE = 0x405a,
+    FLDS_FRM_FPUL_OPCODE = 0xf01d,
+    STS_FPUL_RN_OPCODE = 0x005a,
+    FSTS_FPUL_FRN_OPCODE = 0xF00d,
+    LDSFPSCR_OPCODE = 0x406a,
+    STSFPSCR_OPCODE = 0x006a,
+    LDSRMFPUL_OPCODE = 0x405a,
+    FSTSFPULFRN_OPCODE = 0xf00d,
+    FSQRT_OPCODE = 0xf06d,
+    FSCHG_OPCODE = 0xf3fd,
+    CLRT_OPCODE = 8,
+};
+
+namespace SH4Registers {
+typedef enum {
+    r0,
+    r1,
+    r2,
+    r3,
+    r4,
+    r5,
+    r6,
+    r7,
+    r8,
+    r9,
+    r10,
+    r11,
+    r12,
+    r13,
+    r14, fp = r14,
+    r15, sp = r15,
+    pc,
+    pr,
+} RegisterID;
+
+typedef enum {
+    fr0, dr0 = fr0,
+    fr1,
+    fr2, dr2 = fr2,
+    fr3,
+    fr4, dr4 = fr4,
+    fr5,
+    fr6, dr6 = fr6,
+    fr7,
+    fr8, dr8 = fr8,
+    fr9,
+    fr10, dr10 = fr10,
+    fr11,
+    fr12, dr12 = fr12,
+    fr13,
+    fr14, dr14 = fr14,
+    fr15,
+} FPRegisterID;
+}
+
+inline uint16_t getOpcodeGroup1(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4));
+}
+
+inline uint16_t getOpcodeGroup2(uint16_t opc, int rm)
+{
+    return (opc | ((rm & 0xf) << 8));
+}
+
+inline uint16_t getOpcodeGroup3(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 8) | (rn & 0xff));
+}
+
+inline uint16_t getOpcodeGroup4(uint16_t opc, int rm, int rn, int offset)
+{
+    return (opc | ((rm & 0xf) << 8) | ((rn & 0xf) << 4) | (offset & 0xf));
+}
+
+inline uint16_t getOpcodeGroup5(uint16_t opc, int rm)
+{
+    return (opc | (rm & 0xff));
+}
+
+inline uint16_t getOpcodeGroup6(uint16_t opc, int rm)
+{
+    return (opc | (rm & 0xfff));
+}
+
+inline uint16_t getOpcodeGroup7(uint16_t opc, int rm)
+{
+    return (opc | ((rm & 0x7) << 9));
+}
+
+inline uint16_t getOpcodeGroup8(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0x7) << 9) | ((rn & 0x7) << 5));
+}
+
+inline uint16_t getOpcodeGroup9(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 8) | ((rn & 0x7) << 5));
+}
+
+inline uint16_t getOpcodeGroup10(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0x7) << 9) | ((rn & 0xf) << 4));
+}
+
+inline uint16_t getOpcodeGroup11(uint16_t opc, int rm, int rn)
+{
+    return (opc | ((rm & 0xf) << 4) | (rn & 0xf));
+}
+
+inline uint16_t getRn(uint16_t x)
+{
+    return ((x & 0xf00) >> 8);
+}
+
+inline uint16_t getRm(uint16_t x)
+{
+    return ((x & 0xf0) >> 4);
+}
+
+inline uint16_t getDisp(uint16_t x)
+{
+    return (x & 0xf);
+}
+
+inline uint16_t getImm8(uint16_t x)
+{
+    return (x & 0xff);
+}
+
+inline uint16_t getImm12(uint16_t x)
+{
+    return (x & 0xfff);
+}
+
+inline uint16_t getDRn(uint16_t x)
+{
+    return ((x & 0xe00) >> 9);
+}
+
+inline uint16_t getDRm(uint16_t x)
+{
+    return ((x & 0xe0) >> 5);
+}
+
+class SH4Assembler {
+public:
+    typedef SH4Registers::RegisterID RegisterID;
+    typedef SH4Registers::FPRegisterID FPRegisterID;
+    typedef AssemblerBufferWithConstantPool<512, 4, 2, SH4Assembler> SH4Buffer;
+    static const RegisterID scratchReg1 = SH4Registers::r3;
+    static const RegisterID scratchReg2 = SH4Registers::r11;
+    static const uint32_t maxInstructionSize = 16;
+
+    enum {
+        padForAlign8 = 0x00,
+        padForAlign16 = 0x0009,
+        padForAlign32 = 0x00090009,
+    };
+
+    SH4Assembler()
+    {
+        m_claimscratchReg = 0x0;
+    }
+
+    // SH4 condition codes
+    typedef enum {
+        EQ = 0x0, // Equal
+        NE = 0x1, // Not Equal
+        HS = 0x2, // Unsigend Greater Than equal
+        HI = 0x3, // Unsigend Greater Than
+        LS = 0x4, // Unsigend Lower or Same
+        LI = 0x5, // Unsigend Lower
+        GE = 0x6, // Greater or Equal
+        LT = 0x7, // Less Than
+        GT = 0x8, // Greater Than
+        LE = 0x9, // Less or Equal
+        OF = 0xa, // OverFlow
+        SI = 0xb, // Signed
+        EQU= 0xc, // Equal or unordered(NaN)
+        NEU= 0xd,
+        GTU= 0xe,
+        GEU= 0xf,
+        LTU= 0x10,
+        LEU= 0x11,
+    } Condition;
+
+    // Opaque label types
+public:
+    bool isImmediate(int constant)
+    {
+        return ((constant <= 127) && (constant >= -128));
+    }
+
+    RegisterID claimScratch()
+    {
+        ASSERT((m_claimscratchReg != 0x3));
+
+        if (!(m_claimscratchReg & 0x1)) {
+            m_claimscratchReg = (m_claimscratchReg | 0x1);
+            return scratchReg1;
+        }
+
+        m_claimscratchReg = (m_claimscratchReg | 0x2);
+        return scratchReg2;
+    }
+
+    void releaseScratch(RegisterID scratchR)
+    {
+        if (scratchR == scratchReg1)
+            m_claimscratchReg = (m_claimscratchReg & 0x2);
+        else
+            m_claimscratchReg = (m_claimscratchReg & 0x1);
+    }
+
+    // Stack operations
+
+    void pushReg(RegisterID reg)
+    {
+        if (reg == SH4Registers::pr) {
+            oneShortOp(getOpcodeGroup2(STSLPR_OPCODE, SH4Registers::sp));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup1(MOVL_WRITE_RNDEC_OPCODE, SH4Registers::sp, reg));
+    }
+
+    void popReg(RegisterID reg)
+    {
+        if (reg == SH4Registers::pr) {
+            oneShortOp(getOpcodeGroup2(LDSLPR_OPCODE, SH4Registers::sp));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, reg, SH4Registers::sp));
+    }
+
+    void movt(RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup2(MOVT_OPCODE, dst);
+        oneShortOp(opc);
+    }
+
+    // Arithmetic operations
+
+    void addlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(ADD_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void addclRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(ADDC_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void addvlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(ADDV_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void addlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 127) && (imm8 >= -128));
+
+        uint16_t opc = getOpcodeGroup3(ADDIMM_OPCODE, dst, imm8);
+        oneShortOp(opc);
+    }
+
+    void andlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(AND_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void andlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 255) && (imm8 >= 0));
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup5(ANDIMM_OPCODE, imm8);
+        oneShortOp(opc);
+    }
+
+    void div1lRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DIV1_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void div0lRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DIV0_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void notlReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(NOT_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void orlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(OR_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void orlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 255) && (imm8 >= 0));
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup5(ORIMM_OPCODE, imm8);
+        oneShortOp(opc);
+    }
+
+    void sublRegReg(RegisterID src, RegisterID dst)
+    {
+         uint16_t opc = getOpcodeGroup1(SUB_OPCODE, dst, src);
+         oneShortOp(opc);
+    }
+
+    void subvlRegReg(RegisterID src, RegisterID dst)
+    {
+         uint16_t opc = getOpcodeGroup1(SUBV_OPCODE, dst, src);
+         oneShortOp(opc);
+    }
+
+    void xorlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(XOR_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void xorlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 255) && (imm8 >= 0));
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup5(XORIMM_OPCODE, imm8);
+        oneShortOp(opc);
+    }
+
+    void shllImm8r(int imm, RegisterID dst)
+    {
+        switch (imm) {
+        case 1:
+            oneShortOp(getOpcodeGroup2(SHLL_OPCODE, dst));
+            break;
+        case 2:
+            oneShortOp(getOpcodeGroup2(SHLL2_OPCODE, dst));
+            break;
+        case 8:
+            oneShortOp(getOpcodeGroup2(SHLL8_OPCODE, dst));
+            break;
+        case 16:
+            oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void neg(RegisterID dst, RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup1(NEG_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void shllRegReg(RegisterID dst, RegisterID rShift)
+    {
+        uint16_t opc = getOpcodeGroup1(SHLD_OPCODE, dst, rShift);
+        oneShortOp(opc);
+    }
+
+    void shlrRegReg(RegisterID dst, RegisterID rShift)
+    {
+        neg(rShift, rShift);
+        shllRegReg(dst, rShift);
+    }
+
+    void sharRegReg(RegisterID dst, RegisterID rShift)
+    {
+        neg(rShift, rShift);
+        shaRegReg(dst, rShift);
+    }
+
+    void shaRegReg(RegisterID dst, RegisterID rShift)
+    {
+        uint16_t opc = getOpcodeGroup1(SHAD_OPCODE, dst, rShift);
+        oneShortOp(opc);
+    }
+
+    void shlrImm8r(int imm, RegisterID dst)
+    {
+        switch (imm) {
+        case 1:
+            oneShortOp(getOpcodeGroup2(SHLR_OPCODE, dst));
+            break;
+        case 2:
+            oneShortOp(getOpcodeGroup2(SHLR2_OPCODE, dst));
+            break;
+        case 8:
+            oneShortOp(getOpcodeGroup2(SHLR8_OPCODE, dst));
+            break;
+        case 16:
+            oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void imullRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MULL_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void dmullRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DMULL_L_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void dmulslRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(DMULSL_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void stsmacl(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSMACL_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void stsmach(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSMACH_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    // Comparisons
+
+    void cmplRegReg(RegisterID left, RegisterID right, Condition cond)
+    {
+        switch (cond) {
+        case NE:
+            oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
+            break;
+        case GT:
+            oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, right, left));
+            break;
+        case EQ:
+            oneShortOp(getOpcodeGroup1(CMPEQ_OPCODE, right, left));
+            break;
+        case GE:
+            oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, right, left));
+            break;
+        case HS:
+            oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, right, left));
+            break;
+        case HI:
+            oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, right, left));
+            break;
+        case LI:
+            oneShortOp(getOpcodeGroup1(CMPHI_OPCODE, left, right));
+            break;
+        case LS:
+            oneShortOp(getOpcodeGroup1(CMPHS_OPCODE, left, right));
+            break;
+        case LE:
+            oneShortOp(getOpcodeGroup1(CMPGE_OPCODE, left, right));
+            break;
+        case LT:
+            oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void cmppl(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(CMPPL_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void cmppz(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(CMPPZ_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void cmpEqImmR0(int imm, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup5(CMPEQIMM_OPCODE, imm);
+        oneShortOp(opc);
+    }
+
+    void testlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(TST_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void testlImm8r(int imm, RegisterID dst)
+    {
+        ASSERT((dst == SH4Registers::r0) && (imm <= 255) && (imm >= 0));
+
+        uint16_t opc = getOpcodeGroup5(TSTIMM_OPCODE, imm);
+        oneShortOp(opc);
+    }
+
+    void nop()
+    {
+        oneShortOp(NOP_OPCODE, false);
+    }
+
+    void sett()
+    {
+        oneShortOp(SETT_OPCODE);
+    }
+
+    void clrt()
+    {
+        oneShortOp(CLRT_OPCODE);
+    }
+
+    void fschg()
+    {
+        oneShortOp(FSCHG_OPCODE);
+    }
+
+    void bkpt()
+    {
+        oneShortOp(BRK_OPCODE, false);
+    }
+
+    void branch(uint16_t opc, int label)
+    {
+        switch (opc) {
+        case BT_OPCODE:
+            ASSERT((label <= 127) && (label >= -128));
+            oneShortOp(getOpcodeGroup5(BT_OPCODE, label));
+            break;
+        case BRA_OPCODE:
+            ASSERT((label <= 2047) && (label >= -2048));
+            oneShortOp(getOpcodeGroup6(BRA_OPCODE, label));
+            break;
+        case BF_OPCODE:
+            ASSERT((label <= 127) && (label >= -128));
+            oneShortOp(getOpcodeGroup5(BF_OPCODE, label));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void branch(uint16_t opc, RegisterID reg)
+    {
+        switch (opc) {
+        case BRAF_OPCODE:
+            oneShortOp(getOpcodeGroup2(BRAF_OPCODE, reg));
+            break;
+        case JMP_OPCODE:
+            oneShortOp(getOpcodeGroup2(JMP_OPCODE, reg));
+            break;
+        case JSR_OPCODE:
+            oneShortOp(getOpcodeGroup2(JSR_OPCODE, reg));
+            break;
+        case BSRF_OPCODE:
+            oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg));
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void ldspr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(LDSPR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void stspr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSPR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void extuw(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(EXTUW_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    // float operations
+
+    void ldsrmfpul(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(LDS_RM_FPUL_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void fneg(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup2(FNEG_OPCODE, dst);
+        oneShortOp(opc, true, false);
+    }
+
+    void fsqrt(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup2(FSQRT_OPCODE, dst);
+        oneShortOp(opc, true, false);
+    }
+
+    void stsfpulReg(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(STS_FPUL_RN_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void floatfpulfrn(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FLOAT_OPCODE, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmull(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMUL_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsReadrm(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsWriterm(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsWriter0r(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_R0RN_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsReadr0r(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsReadrminc(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_INC_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fmovsWriterndec(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(FMOVS_WRITE_RN_DEC_OPCODE, dst, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void ftrcRegfpul(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FTRC_OPCODE, src);
+        oneShortOp(opc, true, false);
+    }
+
+    void fldsfpul(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FLDS_FRM_FPUL_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void fstsfpul(RegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup2(FSTS_FPUL_FRN_OPCODE, src);
+        oneShortOp(opc);
+    }
+
+    void ldsfpscr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(LDSFPSCR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    void stsfpscr(RegisterID reg)
+    {
+        uint16_t opc = getOpcodeGroup2(STSFPSCR_OPCODE, reg);
+        oneShortOp(opc);
+    }
+
+    // double operations
+
+    void dcnvds(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup7(FCNVDS_DRM_FPUL_OPCODE, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dcmppeq(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FCMPEQ_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dcmppgt(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FCMPGT_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dmulRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FMUL_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dsubRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FSUB_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void daddRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FADD_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dmovRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FMOV_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void ddivRegReg(FPRegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup8(FDIV_OPCODE, dst >> 1, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void dsqrt(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1);
+        oneShortOp(opc);
+    }
+
+    void dneg(FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup7(FNEG_OPCODE, dst >> 1);
+        oneShortOp(opc);
+    }
+
+    void fmovReadrm(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_OPCODE, dst >> 1, src);
+        oneShortOp(opc);
+    }
+
+    void fmovWriterm(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_OPCODE, dst, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void fmovWriter0r(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_R0RN_OPCODE, dst, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void fmovReadr0r(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup10(FMOVS_READ_R0RM_OPCODE, dst >> 1, src);
+        oneShortOp(opc);
+    }
+
+    void fmovReadrminc(RegisterID src, FPRegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup10(FMOVS_READ_RM_INC_OPCODE, dst >> 1, src);
+        oneShortOp(opc);
+    }
+
+    void fmovWriterndec(FPRegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup9(FMOVS_WRITE_RN_DEC_OPCODE, dst, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void floatfpulDreg(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup7(FLOAT_OPCODE, src >> 1);
+        oneShortOp(opc);
+    }
+
+    void ftrcdrmfpul(FPRegisterID src)
+    {
+        uint16_t opc = getOpcodeGroup7(FTRC_OPCODE, src >> 1);
+        oneShortOp(opc);
+    }
+
+    // Various move ops
+
+    void movImm8(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 127) && (imm8 >= -128));
+
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
+        oneShortOp(opc);
+    }
+
+    void movlRegReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOV_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movwRegMem(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVW_WRITE_RN_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movwMemReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVW_READ_RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movwPCReg(int offset, RegisterID base, RegisterID dst)
+    {
+        ASSERT(base == SH4Registers::pc);
+        ASSERT((offset <= 255) && (offset >= 0));
+
+        uint16_t opc = getOpcodeGroup3(MOVW_READ_OFFPC_OPCODE, dst, offset);
+        oneShortOp(opc);
+    }
+
+    void movwMemReg(int offset, RegisterID base, RegisterID dst)
+    {
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup11(MOVW_READ_OFFRM_OPCODE, base, offset);
+        oneShortOp(opc);
+    }
+
+    void movwR0mr(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVW_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlRegMem(RegisterID src, int offset, RegisterID base)
+    {
+        ASSERT((offset <= 15) && (offset >= 0));
+
+        if (!offset) {
+            oneShortOp(getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup4(MOVL_WRITE_OFFRN_OPCODE, base, src, offset));
+    }
+
+    void movlRegMem(RegisterID src, RegisterID base)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_WRITE_RN_OPCODE, base, src);
+        oneShortOp(opc);
+    }
+
+    void movlMemReg(int offset, RegisterID base, RegisterID dst)
+    {
+        if (base == SH4Registers::pc) {
+            ASSERT((offset <= 255) && (offset >= 0));
+            oneShortOp(getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, dst, offset));
+            return;
+        }
+
+        ASSERT((offset <= 15) && (offset >= 0));
+        if (!offset) {
+            oneShortOp(getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base));
+            return;
+        }
+
+        oneShortOp(getOpcodeGroup4(MOVL_READ_OFFRM_OPCODE, dst, base, offset));
+    }
+
+    void movbMemReg(int offset, RegisterID base, RegisterID dst)
+    {
+        ASSERT(dst == SH4Registers::r0);
+
+        uint16_t opc = getOpcodeGroup11(MOVB_READ_OFFRM_OPCODE, base, offset);
+        oneShortOp(opc);
+    }
+
+    void movbR0mr(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVB_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movbMemReg(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVB_READ_RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlMemReg(RegisterID base, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base);
+        oneShortOp(opc);
+    }
+
+    void movlMemRegIn(RegisterID base, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_READ_RMINC_OPCODE, dst, base);
+        oneShortOp(opc);
+    }
+
+    void movlR0mr(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_READ_R0RM_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlRegMemr0(RegisterID src, RegisterID dst)
+    {
+        uint16_t opc = getOpcodeGroup1(MOVL_WRITE_R0RN_OPCODE, dst, src);
+        oneShortOp(opc);
+    }
+
+    void movlImm8r(int imm8, RegisterID dst)
+    {
+        ASSERT((imm8 <= 127) && (imm8 >= -128));
+
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8);
+        oneShortOp(opc);
+    }
+
+    void loadConstant(uint32_t constant, RegisterID dst)
+    {
+        if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) {
+            movImm8(constant, dst);
+            return;
+        }
+
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
+
+        m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
+        printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
+        m_buffer.putShortWithConstantInt(opc, constant, true);
+    }
+
+    void loadConstantUnReusable(uint32_t constant, RegisterID dst, bool ensureSpace = false)
+    {
+        uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, 0);
+
+        if (ensureSpace)
+            m_buffer.ensureSpace(maxInstructionSize, sizeof(uint32_t));
+
+        printInstr(getOpcodeGroup3(MOVIMM_OPCODE, dst, constant), m_buffer.codeSize());
+        m_buffer.putShortWithConstantInt(opc, constant);
+    }
+
+    // Flow control
+
+    AssemblerLabel call()
+    {
+        RegisterID scr = claimScratch();
+        m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
+        loadConstantUnReusable(0x0, scr);
+        branch(JSR_OPCODE, scr);
+        nop();
+        releaseScratch(scr);
+        return m_buffer.label();
+    }
+
+    AssemblerLabel call(RegisterID dst)
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        branch(JSR_OPCODE, dst);
+        nop();
+        return m_buffer.label();
+    }
+
+    AssemblerLabel jmp()
+    {
+        RegisterID scr = claimScratch();
+        m_buffer.ensureSpace(maxInstructionSize + 4, sizeof(uint32_t));
+        AssemblerLabel label = m_buffer.label();
+        loadConstantUnReusable(0x0, scr);
+        branch(BRAF_OPCODE, scr);
+        nop();
+        releaseScratch(scr);
+        return label;
+    }
+
+    AssemblerLabel jmp(RegisterID dst)
+    {
+        jmpReg(dst);
+        return m_buffer.label();
+    }
+
+    void jmpReg(RegisterID dst)
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        branch(JMP_OPCODE, dst);
+        nop();
+    }
+
+    AssemblerLabel jne()
+    {
+        AssemblerLabel label = m_buffer.label();
+        branch(BF_OPCODE, 0);
+        return label;
+    }
+
+    AssemblerLabel je()
+    {
+        AssemblerLabel label = m_buffer.label();
+        branch(BT_OPCODE, 0);
+        return label;
+    }
+
+    void ret()
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        oneShortOp(RTS_OPCODE, false);
+    }
+
+    AssemblerLabel label()
+    {
+        m_buffer.ensureSpaceForAnyOneInstruction();
+        return m_buffer.label();
+    }
+
+    int sizeOfConstantPool()
+    {
+         return m_buffer.sizeOfConstantPool();
+    }
+
+    AssemblerLabel align(int alignment)
+    {
+        m_buffer.ensureSpace(maxInstructionSize + 2);
+        while (!m_buffer.isAligned(alignment)) {
+            nop();
+            m_buffer.ensureSpace(maxInstructionSize + 2);
+        }
+        return label();
+    }
+
+    static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress)
+    {
+        uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
+        *reinterpret_cast<uint32_t*>(address) = newAddress;
+    }
+    
+    static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr)
+    {
+        uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3));
+        return *reinterpret_cast<uint32_t*>(address);
+    }
+
+    static uint16_t* getInstructionPtr(void* code, int offset)
+    {
+        return reinterpret_cast<uint16_t*> (reinterpret_cast<uint32_t>(code) + offset);
+    }
+
+    static void linkJump(void* code, AssemblerLabel from, void* to)
+    {
+        ASSERT(from.isSet());
+
+        uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
+        uint16_t instruction = *instructionPtr;
+        int offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(code)) - from.m_offset;
+
+        if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
+            /* BT label ==> BF 2
+               nop          LDR reg
+               nop          braf @reg
+               nop          nop
+            */
+            offsetBits -= 8;
+            instruction ^= 0x0202;
+            *instructionPtr++ = instruction;
+            changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
+            instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
+            *instructionPtr = instruction;
+            printBlockInstr(instructionPtr - 2, from.m_offset, 3);
+            return;
+         }
+
+         /* MOV #imm, reg => LDR reg
+            braf @reg        braf @reg
+            nop              nop
+         */
+        ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
+
+        offsetBits -= 4;
+        if (offsetBits >= -4096 && offsetBits <= 4094) {
+            *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
+            *(++instructionPtr) = NOP_OPCODE;
+            printBlockInstr(instructionPtr - 1, from.m_offset, 2);
+            return;
+        }
+
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+        printInstr(*instructionPtr, from.m_offset + 2);
+    }
+
+    static void linkCall(void* code, AssemblerLabel from, void* to)
+    {
+        uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset);
+        instructionPtr -= 3;
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
+    }
+
+    static void linkPointer(void* code, AssemblerLabel where, void* value)
+    {
+        uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset);
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value));
+    }
+
+    static unsigned getCallReturnOffset(AssemblerLabel call)
+    {
+        ASSERT(call.isSet());
+        return call.m_offset;
+    }
+
+    static uint32_t* getLdrImmAddressOnPool(SH4Word* insn, uint32_t* constPool)
+    {
+        return (constPool + (*insn & 0xff));
+    }
+
+    static SH4Word patchConstantPoolLoad(SH4Word load, int value)
+    {
+        return ((load & ~0xff) | value);
+    }
+
+    static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset)
+    {
+        ASSERT(((offset >> 1) <=2047) && ((offset >> 1) >= -2048));
+
+        SH4Buffer::TwoShorts m_barrier;
+        m_barrier.high = (BRA_OPCODE | (offset >> 1));
+        m_barrier.low = NOP_OPCODE;
+        printInstr(((BRA_OPCODE | (offset >> 1))), 0);
+        printInstr(NOP_OPCODE, 0);
+        return m_barrier;
+    }
+
+    static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
+    {
+        SH4Word* instructionPtr = reinterpret_cast<SH4Word*>(loadAddr);
+        SH4Word instruction = *instructionPtr;
+        SH4Word index = instruction & 0xff;
+
+        if ((instruction & 0xf000) != MOVIMM_OPCODE)
+            return;
+
+        ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024);
+
+        int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4);
+        instruction &=0xf00;
+        instruction |= 0xd000;
+        offset &= 0x03ff;
+        instruction |= (offset >> 2);
+        *instructionPtr = instruction;
+        printInstr(instruction, reinterpret_cast<uint32_t>(loadAddr));
+    }
+
+    static void repatchPointer(void* where, void* value)
+    {
+        patchPointer(where, value);
+    }
+
+    static void* readPointer(void* code)
+    {
+        return static_cast<void*>(readInt32(code));
+    }
+
+    static void repatchInt32(void* where, int32_t value)
+    {
+        uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where);
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value);
+    }
+
+    static void repatchCompact(void* where, int32_t value)
+    {
+        repatchInt32(where, value);
+    }
+
+    static void relinkCall(void* from, void* to)
+    {
+        uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from);
+        instructionPtr -= 3;
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to));
+    }
+
+    static void relinkJump(void* from, void* to)
+    {
+        uint16_t* instructionPtr = reinterpret_cast<uint16_t*> (from);
+        uint16_t instruction = *instructionPtr;
+        int32_t offsetBits = (reinterpret_cast<uint32_t>(to) - reinterpret_cast<uint32_t>(from));
+
+        if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) {
+            offsetBits -= 8;
+            instructionPtr++;
+            changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
+            instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
+            *instructionPtr = instruction;
+            printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3);
+            return;
+        }
+
+        ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
+        offsetBits -= 4;
+        if (offsetBits >= -4096 && offsetBits <= 4094) {
+            *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
+            *(++instructionPtr) = NOP_OPCODE;
+            printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2);
+            return;
+        }
+
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+        printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from));
+    }
+
+    // Linking & patching
+
+    void linkJump(AssemblerLabel from, AssemblerLabel to)
+    {
+        ASSERT(to.isSet());
+        ASSERT(from.isSet());
+
+        uint16_t* instructionPtr = getInstructionPtr(data(), from.m_offset);
+        uint16_t instruction = *instructionPtr;
+        int offsetBits;
+
+        if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) {
+            /* BT label => BF 2
+               nop        LDR reg
+               nop        braf @reg
+               nop        nop
+            */
+            offsetBits = (to.m_offset - from.m_offset) - 8;
+            instruction ^= 0x0202;
+            *instructionPtr++ = instruction;
+            if ((*instructionPtr & 0xf000) == 0xe000) {
+                uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
+                *addr = offsetBits;
+            } else
+                changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits);
+            instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00));
+            *instructionPtr = instruction;
+            printBlockInstr(instructionPtr - 2, from.m_offset, 3);
+            return;
+        }
+
+        /* MOV # imm, reg => LDR reg
+           braf @reg         braf @reg
+           nop               nop
+        */
+        ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE);
+        offsetBits = (to.m_offset - from.m_offset) - 4;
+        if (offsetBits >= -4096 && offsetBits <= 4094) {
+            *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1);
+            *(++instructionPtr) = NOP_OPCODE;
+            printBlockInstr(instructionPtr - 1, from.m_offset, 2);
+            return;
+        }
+
+        instruction = *instructionPtr;
+        if ((instruction  & 0xf000) == 0xe000) {
+            uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress());
+            *addr = offsetBits - 2;
+            printInstr(*instructionPtr, from.m_offset + 2);
+            return;
+        }
+
+        changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2);
+        printInstr(*instructionPtr, from.m_offset + 2);
+    }
+
+    static void* getRelocatedAddress(void* code, AssemblerLabel label)
+    {
+        return reinterpret_cast<void*>(reinterpret_cast<char*>(code) + label.m_offset);
+    }
+
+    static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
+    {
+        return b.m_offset - a.m_offset;
+    }
+
+    static void patchPointer(void* code, AssemblerLabel where, void* value)
+    {
+        patchPointer(reinterpret_cast<uint32_t*>(code) + where.m_offset, value);
+    }
+
+    static void patchPointer(void* code, void* value)
+    {
+        patchInt32(code, reinterpret_cast<uint32_t>(value));
+    }
+
+    static void patchInt32(void* code, uint32_t value)
+    {
+        changePCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code), value);
+    }
+
+    static uint32_t readInt32(void* code)
+    {
+        return readPCrelativeAddress((*(reinterpret_cast<uint16_t*>(code)) & 0xff), reinterpret_cast<uint16_t*>(code));
+    }
+
+    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+    {
+        return m_buffer.executableCopy(globalData, allocator);
+    }
+
+    void prefix(uint16_t pre)
+    {
+        m_buffer.putByte(pre);
+    }
+
+    void oneShortOp(uint16_t opcode, bool checksize = true, bool isDouble = true)
+    {
+        printInstr(opcode, m_buffer.codeSize(), isDouble);
+        if (checksize)
+            m_buffer.ensureSpace(maxInstructionSize);
+        m_buffer.putShortUnchecked(opcode);
+    }
+
+    void ensureSpace(int space)
+    {
+        m_buffer.ensureSpace(space);
+    }
+
+    void ensureSpace(int insnSpace, int constSpace)
+    {
+        m_buffer.ensureSpace(insnSpace, constSpace);
+    }
+
+    // Administrative methods
+
+    void* data() const { return m_buffer.data(); }
+    size_t codeSize() const { return m_buffer.codeSize(); }
+
+#ifdef SH4_ASSEMBLER_TRACING
+    static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true)
+    {
+        if (!getenv("JavaScriptCoreDumpJIT"))
+            return;
+
+        const char *format = 0;
+        printfStdoutInstr("offset: 0x%8.8x\t", size);
+        switch (opc) {
+        case BRK_OPCODE:
+            format = "    BRK\n";
+            break;
+        case NOP_OPCODE:
+            format = "    NOP\n";
+            break;
+        case RTS_OPCODE:
+            format ="    *RTS\n";
+            break;
+        case SETS_OPCODE:
+            format = "    SETS\n";
+            break;
+        case SETT_OPCODE:
+            format = "    SETT\n";
+            break;
+        case CLRT_OPCODE:
+            format = "    CLRT\n";
+            break;
+        case FSCHG_OPCODE:
+            format = "    FSCHG\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format);
+            return;
+        }
+        switch (opc & 0xf0ff) {
+        case BRAF_OPCODE:
+            format = "    *BRAF R%d\n";
+            break;
+        case DT_OPCODE:
+            format = "    DT R%d\n";
+            break;
+        case CMPPL_OPCODE:
+            format = "    CMP/PL R%d\n";
+            break;
+        case CMPPZ_OPCODE:
+            format = "    CMP/PZ R%d\n";
+            break;
+        case JMP_OPCODE:
+            format = "    *JMP @R%d\n";
+            break;
+        case JSR_OPCODE:
+            format = "    *JSR @R%d\n";
+            break;
+        case LDSPR_OPCODE:
+            format = "    LDS R%d, PR\n";
+            break;
+        case LDSLPR_OPCODE:
+            format = "    LDS.L @R%d+, PR\n";
+            break;
+        case MOVT_OPCODE:
+            format = "    MOVT R%d\n";
+            break;
+        case SHAL_OPCODE:
+            format = "    SHAL R%d\n";
+            break;
+        case SHAR_OPCODE:
+            format = "    SHAR R%d\n";
+            break;
+        case SHLL_OPCODE:
+            format = "    SHLL R%d\n";
+            break;
+        case SHLL2_OPCODE:
+            format = "    SHLL2 R%d\n";
+            break;
+        case SHLL8_OPCODE:
+            format = "    SHLL8 R%d\n";
+            break;
+        case SHLL16_OPCODE:
+            format = "    SHLL16 R%d\n";
+            break;
+        case SHLR_OPCODE:
+            format = "    SHLR R%d\n";
+            break;
+        case SHLR2_OPCODE:
+            format = "    SHLR2 R%d\n";
+            break;
+        case SHLR8_OPCODE:
+            format = "    SHLR8 R%d\n";
+            break;
+        case SHLR16_OPCODE:
+            format = "    SHLR16 R%d\n";
+            break;
+        case STSPR_OPCODE:
+            format = "    STS PR, R%d\n";
+            break;
+        case STSLPR_OPCODE:
+            format = "    STS.L PR, @-R%d\n";
+            break;
+        case LDS_RM_FPUL_OPCODE:
+            format = "    LDS R%d, FPUL\n";
+            break;
+        case STS_FPUL_RN_OPCODE:
+            format = "    STS FPUL, R%d \n";
+            break;
+        case FLDS_FRM_FPUL_OPCODE:
+            format = "    FLDS FR%d, FPUL\n";
+            break;
+        case FSTS_FPUL_FRN_OPCODE:
+            format = "    FSTS FPUL, R%d \n";
+            break;
+        case LDSFPSCR_OPCODE:
+            format = "    LDS R%d, FPSCR \n";
+            break;
+        case STSFPSCR_OPCODE:
+            format = "    STS FPSCR, R%d \n";
+            break;
+        case STSMACL_OPCODE:
+            format = "    STS MACL, R%d \n";
+            break;
+        case STSMACH_OPCODE:
+            format = "    STS MACH, R%d \n";
+            break;
+        case BSRF_OPCODE:
+            format = "    *BSRF R%d";
+            break;
+        case FTRC_OPCODE:
+            format = "    FTRC FR%d, FPUL\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getRn(opc));
+            return;
+        }
+        switch (opc & 0xf0ff) {
+        case FNEG_OPCODE:
+            format = "    FNEG DR%d\n";
+            break;
+        case FLOAT_OPCODE:
+            format = "    FLOAT DR%d\n";
+            break;
+        case FTRC_OPCODE:
+            format = "    FTRC FR%d, FPUL\n";
+            break;
+        case FSQRT_OPCODE:
+            format = "    FSQRT FR%d\n";
+            break;
+        case FCNVDS_DRM_FPUL_OPCODE:
+            format = "    FCNVDS FR%d, FPUL\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, getDRn(opc) << 1);
+            else
+                printfStdoutInstr(format, getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case ADD_OPCODE:
+            format = "    ADD R%d, R%d\n";
+            break;
+        case ADDC_OPCODE:
+            format = "    ADDC R%d, R%d\n";
+            break;
+        case ADDV_OPCODE:
+            format = "    ADDV R%d, R%d\n";
+            break;
+        case AND_OPCODE:
+            format = "    AND R%d, R%d\n";
+            break;
+        case DIV1_OPCODE:
+            format = "    DIV1 R%d, R%d\n";
+            break;
+        case CMPEQ_OPCODE:
+            format = "    CMP/EQ R%d, R%d\n";
+            break;
+        case CMPGE_OPCODE:
+            format = "    CMP/GE R%d, R%d\n";
+            break;
+        case CMPGT_OPCODE:
+            format = "    CMP/GT R%d, R%d\n";
+            break;
+        case CMPHI_OPCODE:
+            format = "    CMP/HI R%d, R%d\n";
+            break;
+        case CMPHS_OPCODE:
+            format = "    CMP/HS R%d, R%d\n";
+            break;
+        case MOV_OPCODE:
+            format = "    MOV R%d, R%d\n";
+            break;
+        case MOVB_WRITE_RN_OPCODE:
+            format = "    MOV.B R%d, @R%d\n";
+            break;
+        case MOVB_WRITE_RNDEC_OPCODE:
+            format = "    MOV.B R%d, @-R%d\n";
+            break;
+        case MOVB_WRITE_R0RN_OPCODE:
+            format = "    MOV.B R%d, @(R0, R%d)\n";
+            break;
+        case MOVB_READ_RM_OPCODE:
+            format = "    MOV.B @R%d, R%d\n";
+            break;
+        case MOVB_READ_RMINC_OPCODE:
+            format = "    MOV.B @R%d+, R%d\n";
+            break;
+        case MOVB_READ_R0RM_OPCODE:
+            format = "    MOV.B @(R0, R%d), R%d\n";
+            break;
+        case MOVL_WRITE_RN_OPCODE:
+            format = "    MOV.L R%d, @R%d\n";
+            break;
+        case MOVL_WRITE_RNDEC_OPCODE:
+            format = "    MOV.L R%d, @-R%d\n";
+            break;
+        case MOVL_WRITE_R0RN_OPCODE:
+            format = "    MOV.L R%d, @(R0, R%d)\n";
+            break;
+        case MOVL_READ_RM_OPCODE:
+            format = "    MOV.L @R%d, R%d\n";
+            break;
+        case MOVL_READ_RMINC_OPCODE:
+            format = "    MOV.L @R%d+, R%d\n";
+            break;
+        case MOVL_READ_R0RM_OPCODE:
+            format = "    MOV.L @(R0, R%d), R%d\n";
+            break;
+        case MULL_OPCODE:
+            format = "    MUL.L R%d, R%d\n";
+            break;
+        case DMULL_L_OPCODE:
+            format = "    DMULU.L R%d, R%d\n";
+            break;
+        case DMULSL_OPCODE:
+            format = "    DMULS.L R%d, R%d\n";
+            break;
+        case NEG_OPCODE:
+            format = "    NEG R%d, R%d\n";
+            break;
+        case NEGC_OPCODE:
+            format = "    NEGC R%d, R%d\n";
+            break;
+        case NOT_OPCODE:
+            format = "    NOT R%d, R%d\n";
+            break;
+        case OR_OPCODE:
+            format = "    OR R%d, R%d\n";
+            break;
+        case SHAD_OPCODE:
+            format = "    SHAD R%d, R%d\n";
+            break;
+        case SHLD_OPCODE:
+            format = "    SHLD R%d, R%d\n";
+            break;
+        case SUB_OPCODE:
+            format = "    SUB R%d, R%d\n";
+            break;
+        case SUBC_OPCODE:
+            format = "    SUBC R%d, R%d\n";
+            break;
+        case SUBV_OPCODE:
+            format = "    SUBV R%d, R%d\n";
+            break;
+        case TST_OPCODE:
+            format = "    TST R%d, R%d\n";
+            break;
+        case XOR_OPCODE:
+            format = "    XOR R%d, R%d\n";break;
+        case MOVW_WRITE_RN_OPCODE:
+            format = "    MOV.W R%d, @R%d\n";
+            break;
+        case MOVW_READ_RM_OPCODE:
+            format = "    MOV.W @R%d, R%d\n";
+            break;
+        case MOVW_READ_R0RM_OPCODE:
+            format = "    MOV.W @(R0, R%d), R%d\n";
+            break;
+        case EXTUW_OPCODE:
+            format = "    EXTU.W R%d, R%d\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case FSUB_OPCODE:
+            format = "    FSUB FR%d, FR%d\n";
+            break;
+        case FADD_OPCODE:
+            format = "    FADD FR%d, FR%d\n";
+            break;
+        case FDIV_OPCODE:
+            format = "    FDIV FR%d, FR%d\n";
+            break;
+        case FMUL_OPCODE:
+            format = "    DMULL FR%d, FR%d\n";
+            break;
+        case FMOV_OPCODE:
+            format = "    FMOV FR%d, FR%d\n";
+            break;
+        case FCMPEQ_OPCODE:
+            format = "    FCMP/EQ FR%d, FR%d\n";
+            break;
+        case FCMPGT_OPCODE:
+            format = "    FCMP/GT FR%d, FR%d\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, getDRm(opc) << 1, getDRn(opc) << 1);
+            else
+                printfStdoutInstr(format, getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case FMOVS_WRITE_RN_DEC_OPCODE:
+            format = "    %s FR%d, @-R%d\n";
+            break;
+        case FMOVS_WRITE_RN_OPCODE:
+            format = "    %s FR%d, @R%d\n";
+            break;
+        case FMOVS_WRITE_R0RN_OPCODE:
+            format = "    %s FR%d, @(R0, R%d)\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, "FMOV", getDRm(opc) << 1, getDRn(opc));
+            else
+                printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf00f) {
+        case FMOVS_READ_RM_OPCODE:
+            format = "    %s @R%d, FR%d\n";
+            break;
+        case FMOVS_READ_RM_INC_OPCODE:
+            format = "    %s @R%d+, FR%d\n";
+            break;
+        case FMOVS_READ_R0RM_OPCODE:
+            format = "    %s @(R0, R%d), FR%d\n";
+            break;
+        }
+        if (format) {
+            if (isdoubleInst)
+                printfStdoutInstr(format, "FMOV", getDRm(opc), getDRn(opc) << 1);
+            else
+                printfStdoutInstr(format, "FMOV.S", getRm(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xff00) {
+        case BF_OPCODE:
+            format = "    BF %d\n";
+            break;
+        case BFS_OPCODE:
+            format = "    *BF/S %d\n";
+            break;
+        case ANDIMM_OPCODE:
+            format = "    AND #%d, R0\n";
+            break;
+        case BT_OPCODE:
+            format = "    BT %d\n";
+            break;
+        case BTS_OPCODE:
+            format = "    *BT/S %d\n";
+            break;
+        case CMPEQIMM_OPCODE:
+            format = "    CMP/EQ #%d, R0\n";
+            break;
+        case MOVB_WRITE_OFFGBR_OPCODE:
+            format = "    MOV.B R0, @(%d, GBR)\n";
+            break;
+        case MOVB_READ_OFFGBR_OPCODE:
+            format = "    MOV.B @(%d, GBR), R0\n";
+            break;
+        case MOVL_WRITE_OFFGBR_OPCODE:
+            format = "    MOV.L R0, @(%d, GBR)\n";
+            break;
+        case MOVL_READ_OFFGBR_OPCODE:
+            format = "    MOV.L @(%d, GBR), R0\n";
+            break;
+        case MOVA_READ_OFFPC_OPCODE:
+            format = "    MOVA @(%d, PC), R0\n";
+            break;
+        case ORIMM_OPCODE:
+            format = "    OR #%d, R0\n";
+            break;
+        case ORBIMM_OPCODE:
+            format = "    OR.B #%d, @(R0, GBR)\n";
+            break;
+        case TSTIMM_OPCODE:
+            format = "    TST #%d, R0\n";
+            break;
+        case TSTB_OPCODE:
+            format = "    TST.B %d, @(R0, GBR)\n";
+            break;
+        case XORIMM_OPCODE:
+            format = "    XOR #%d, R0\n";
+            break;
+        case XORB_OPCODE:
+            format = "    XOR.B %d, @(R0, GBR)\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getImm8(opc));
+            return;
+        }
+        switch (opc & 0xff00) {
+        case MOVB_WRITE_OFFRN_OPCODE:
+            format = "    MOV.B R0, @(%d, R%d)\n";
+            break;
+        case MOVB_READ_OFFRM_OPCODE:
+            format = "    MOV.B @(%d, R%d), R0\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getDisp(opc), getRm(opc));
+            return;
+        }
+        switch (opc & 0xf000) {
+        case BRA_OPCODE:
+            format = "    *BRA %d\n";
+            break;
+        case BSR_OPCODE:
+            format = "    *BSR %d\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getImm12(opc));
+            return;
+        }
+        switch (opc & 0xf000) {
+        case MOVL_READ_OFFPC_OPCODE:
+            format = "    MOV.L @(%d, PC), R%d\n";
+            break;
+        case ADDIMM_OPCODE:
+            format = "    ADD #%d, R%d\n";
+            break;
+        case MOVIMM_OPCODE:
+            format = "    MOV #%d, R%d\n";
+            break;
+        case MOVW_READ_OFFPC_OPCODE:
+            format = "    MOV.W @(%d, PC), R%d\n";
+            break;
+        }
+        if (format) {
+            printfStdoutInstr(format, getImm8(opc), getRn(opc));
+            return;
+        }
+        switch (opc & 0xf000) {
+        case MOVL_WRITE_OFFRN_OPCODE:
+            format = "    MOV.L R%d, @(%d, R%d)\n";
+            printfStdoutInstr(format, getRm(opc), getDisp(opc), getRn(opc));
+            break;
+        case MOVL_READ_OFFRM_OPCODE:
+            format = "    MOV.L @(%d, R%d), R%d\n";
+            printfStdoutInstr(format, getDisp(opc), getRm(opc), getRn(opc));
+            break;
+        }
+    }
+
+    static void printfStdoutInstr(const char* format, ...)
+    {
+        if (getenv("JavaScriptCoreDumpJIT")) {
+            va_list args;
+            va_start(args, format);
+            vprintfStdoutInstr(format, args);
+            va_end(args);
+        }
+    }
+
+    static void vprintfStdoutInstr(const char* format, va_list args)
+    {
+        if (getenv("JavaScriptCoreDumpJIT"))
+            vfprintf(stdout, format, args);
+    }
+
+    static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr)
+    {
+        printfStdoutInstr(">> repatch instructions after link\n");
+        for (int i = 0; i <= nbInstr; i++)
+           printInstr(*(first + i), offset + i);
+        printfStdoutInstr(">> end repatch\n");
+    }
+#else
+    static void printInstr(uint16_t opc, unsigned int size, bool isdoubleInst = true) {};
+    static void printBlockInstr(uint16_t* first, unsigned int offset, int nbInstr) {};
+#endif
+
+private:
+    SH4Buffer m_buffer;
+    int m_claimscratchReg;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && CPU(SH4)
+
+#endif // SH4Assembler_h
index 20d72f5a55873df164e4fb1a2906cfd695086e35..41dd50ffcc7cf7cabf700076f45c92e9df446826 100644 (file)
@@ -131,12 +131,14 @@ private:
         OP_GROUP1_EbIb                  = 0x80,
         OP_GROUP1_EvIz                  = 0x81,
         OP_GROUP1_EvIb                  = 0x83,
+        OP_TEST_EbGb                    = 0x84,
         OP_TEST_EvGv                    = 0x85,
         OP_XCHG_EvGv                    = 0x87,
         OP_MOV_EvGv                     = 0x89,
         OP_MOV_GvEv                     = 0x8B,
         OP_LEA                          = 0x8D,
         OP_GROUP1A_Ev                   = 0x8F,
+        OP_NOP                          = 0x90,
         OP_CDQ                          = 0x99,
         OP_MOV_EAXOv                    = 0xA1,
         OP_MOV_OvEAX                    = 0xA3,
@@ -219,54 +221,10 @@ private:
     class X86InstructionFormatter;
 public:
 
-    class JmpSrc {
-        friend class X86Assembler;
-        friend class X86InstructionFormatter;
-    public:
-        JmpSrc()
-            : m_offset(-1)
-        {
-        }
-
-    private:
-        JmpSrc(int offset)
-            : m_offset(offset)
-        {
-        }
-
-        int m_offset;
-    };
-    
-    class JmpDst {
-        friend class X86Assembler;
-        friend class X86InstructionFormatter;
-    public:
-        JmpDst()
-            : m_offset(-1)
-            , m_used(false)
-        {
-        }
-
-        bool isUsed() const { return m_used; }
-        void used() { m_used = true; }
-    private:
-        JmpDst(int offset)
-            : m_offset(offset)
-            , m_used(false)
-        {
-            ASSERT(m_offset == offset);
-        }
-
-        int m_offset : 31;
-        bool m_used : 1;
-    };
-
     X86Assembler()
     {
     }
 
-    size_t size() const { return m_formatter.size(); }
-
     // Stack operations:
 
     void push_r(RegisterID reg)
@@ -298,7 +256,7 @@ public:
     // Arithmetic operations:
 
 #if !CPU(X86_64)
-    void adcl_im(int imm, void* addr)
+    void adcl_im(int imm, const void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
@@ -375,7 +333,7 @@ public:
         }
     }
 #else
-    void addl_im(int imm, void* addr)
+    void addl_im(int imm, const void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
@@ -441,7 +399,7 @@ public:
         }
     }
 #else
-    void andl_im(int imm, void* addr)
+    void andl_im(int imm, const void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
@@ -527,7 +485,7 @@ public:
         }
     }
 #else
-    void orl_im(int imm, void* addr)
+    void orl_im(int imm, const void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
@@ -593,7 +551,7 @@ public:
         }
     }
 #else
-    void subl_im(int imm, void* addr)
+    void subl_im(int imm, const void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
@@ -866,12 +824,12 @@ public:
         }
     }
 #else
-    void cmpl_rm(RegisterID reg, void* addr)
+    void cmpl_rm(RegisterID reg, const void* addr)
     {
         m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
     }
 
-    void cmpl_im(int imm, void* addr)
+    void cmpl_im(int imm, const void* addr)
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
@@ -918,7 +876,12 @@ public:
         m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
         m_formatter.immediate32(imm);
     }
-    
+
+    void testb_rr(RegisterID src, RegisterID dst)
+    {
+        m_formatter.oneByteOp(OP_TEST_EbGb, src, dst);
+    }
+
     void testb_im(int imm, int offset, RegisterID base)
     {
         m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset);
@@ -1038,7 +1001,7 @@ public:
         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
     }
     
-    void movl_mEAX(void* addr)
+    void movl_mEAX(const void* addr)
     {
         m_formatter.oneByteOp(OP_MOV_EAXOv);
 #if CPU(X86_64)
@@ -1057,6 +1020,11 @@ public:
     {
         m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
     }
+    
+    void movl_mr_disp8(int offset, RegisterID base, RegisterID dst)
+    {
+        m_formatter.oneByteOp_disp8(OP_MOV_GvEv, dst, base, offset);
+    }
 
     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
     {
@@ -1075,7 +1043,7 @@ public:
         m_formatter.immediate32(imm);
     }
 
-    void movl_EAXm(void* addr)
+    void movl_EAXm(const void* addr)
     {
         m_formatter.oneByteOp(OP_MOV_OvEAX);
 #if CPU(X86_64)
@@ -1106,13 +1074,13 @@ public:
         m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
     }
 
-    void movq_mEAX(void* addr)
+    void movq_mEAX(const void* addr)
     {
         m_formatter.oneByteOp64(OP_MOV_EAXOv);
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
     }
 
-    void movq_EAXm(void* addr)
+    void movq_EAXm(const void* addr)
     {
         m_formatter.oneByteOp64(OP_MOV_OvEAX);
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
@@ -1128,6 +1096,11 @@ public:
         m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset);
     }
 
+    void movq_mr_disp8(int offset, RegisterID base, RegisterID dst)
+    {
+        m_formatter.oneByteOp64_disp8(OP_MOV_GvEv, dst, base, offset);
+    }
+
     void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
@@ -1152,7 +1125,7 @@ public:
     
     
 #else
-    void movl_rm(RegisterID src, void* addr)
+    void movl_rm(RegisterID src, const void* addr)
     {
         if (src == X86Registers::eax)
             movl_EAXm(addr);
@@ -1160,7 +1133,7 @@ public:
             m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
     }
     
-    void movl_mr(void* addr, RegisterID dst)
+    void movl_mr(const void* addr, RegisterID dst)
     {
         if (dst == X86Registers::eax)
             movl_mEAX(addr);
@@ -1168,7 +1141,7 @@ public:
             m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
     }
 
-    void movl_i32m(int imm, void* addr)
+    void movl_i32m(int imm, const void* addr)
     {
         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
         m_formatter.immediate32(imm);
@@ -1206,16 +1179,16 @@ public:
 
     // Flow control:
 
-    JmpSrc call()
+    AssemblerLabel call()
     {
         m_formatter.oneByteOp(OP_CALL_rel32);
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc call(RegisterID dst)
+    AssemblerLabel call(RegisterID dst)
     {
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
-        return JmpSrc(m_formatter.size());
+        return m_formatter.label();
     }
     
     void call_m(int offset, RegisterID base)
@@ -1223,19 +1196,19 @@ public:
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, base, offset);
     }
 
-    JmpSrc jmp()
+    AssemblerLabel jmp()
     {
         m_formatter.oneByteOp(OP_JMP_rel32);
         return m_formatter.immediateRel32();
     }
     
-    // Return a JmpSrc so we have a label to the jump, so we can use this
+    // Return a AssemblerLabel so we have a label to the jump, so we can use this
     // To make a tail recursive call on x86-64.  The MacroAssembler
     // really shouldn't wrap this as a Jump, since it can't be linked. :-/
-    JmpSrc jmp_r(RegisterID dst)
+    AssemblerLabel jmp_r(RegisterID dst)
     {
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
-        return JmpSrc(m_formatter.size());
+        return m_formatter.label();
     }
     
     void jmp_m(int offset, RegisterID base)
@@ -1243,95 +1216,95 @@ public:
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
     }
 
-    JmpSrc jne()
+    AssemblerLabel jne()
     {
         m_formatter.twoByteOp(jccRel32(ConditionNE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jnz()
+    AssemblerLabel jnz()
     {
         return jne();
     }
 
-    JmpSrc je()
+    AssemblerLabel je()
     {
         m_formatter.twoByteOp(jccRel32(ConditionE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jz()
+    AssemblerLabel jz()
     {
         return je();
     }
 
-    JmpSrc jl()
+    AssemblerLabel jl()
     {
         m_formatter.twoByteOp(jccRel32(ConditionL));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jb()
+    AssemblerLabel jb()
     {
         m_formatter.twoByteOp(jccRel32(ConditionB));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jle()
+    AssemblerLabel jle()
     {
         m_formatter.twoByteOp(jccRel32(ConditionLE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jbe()
+    AssemblerLabel jbe()
     {
         m_formatter.twoByteOp(jccRel32(ConditionBE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jge()
+    AssemblerLabel jge()
     {
         m_formatter.twoByteOp(jccRel32(ConditionGE));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc jg()
+    AssemblerLabel jg()
     {
         m_formatter.twoByteOp(jccRel32(ConditionG));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc ja()
+    AssemblerLabel ja()
     {
         m_formatter.twoByteOp(jccRel32(ConditionA));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jae()
+    AssemblerLabel jae()
     {
         m_formatter.twoByteOp(jccRel32(ConditionAE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jo()
+    AssemblerLabel jo()
     {
         m_formatter.twoByteOp(jccRel32(ConditionO));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc jp()
+    AssemblerLabel jp()
     {
         m_formatter.twoByteOp(jccRel32(ConditionP));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc js()
+    AssemblerLabel js()
     {
         m_formatter.twoByteOp(jccRel32(ConditionS));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc jCC(Condition cond)
+    AssemblerLabel jCC(Condition cond)
     {
         m_formatter.twoByteOp(jccRel32(cond));
         return m_formatter.immediateRel32();
@@ -1364,7 +1337,7 @@ public:
     }
 
 #if !CPU(X86_64)
-    void cvtsi2sd_mr(void* address, XMMRegisterID dst)
+    void cvtsi2sd_mr(const void* address, XMMRegisterID dst)
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
@@ -1397,6 +1370,12 @@ public:
     }
 #endif
 
+    void movsd_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
+    }
+
     void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1503,17 +1482,17 @@ public:
 
     // Assembler admin methods:
 
-    JmpDst label()
+    size_t codeSize() const
     {
-        return JmpDst(m_formatter.size());
+        return m_formatter.codeSize();
     }
-    
-    static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0)
+
+    AssemblerLabel label()
     {
-        return JmpDst(jump.m_offset + offset);
+        return m_formatter.label();
     }
-    
-    JmpDst align(int alignment)
+
+    AssemblerLabel align(int alignment)
     {
         while (!m_formatter.isAligned(alignment))
             m_formatter.oneByteOp(OP_HLT);
@@ -1529,32 +1508,33 @@ public:
     // writable region of memory; to modify the code in an execute-only execuable
     // pool the 'repatch' and 'relink' methods should be used.
 
-    void linkJump(JmpSrc from, JmpDst to)
+    void linkJump(AssemblerLabel from, AssemblerLabel to)
     {
-        ASSERT(from.m_offset != -1);
-        ASSERT(to.m_offset != -1);
+        ASSERT(from.isSet());
+        ASSERT(to.isSet());
 
         char* code = reinterpret_cast<char*>(m_formatter.data());
+        ASSERT(!reinterpret_cast<int32_t*>(code + from.m_offset)[-1]);
         setRel32(code + from.m_offset, code + to.m_offset);
     }
     
-    static void linkJump(void* code, JmpSrc from, void* to)
+    static void linkJump(void* code, AssemblerLabel from, void* to)
     {
-        ASSERT(from.m_offset != -1);
+        ASSERT(from.isSet());
 
         setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
     }
 
-    static void linkCall(void* code, JmpSrc from, void* to)
+    static void linkCall(void* code, AssemblerLabel from, void* to)
     {
-        ASSERT(from.m_offset != -1);
+        ASSERT(from.isSet());
 
         setRel32(reinterpret_cast<char*>(code) + from.m_offset, to);
     }
 
-    static void linkPointer(void* code, JmpDst where, void* value)
+    static void linkPointer(void* code, AssemblerLabel where, void* value)
     {
-        ASSERT(where.m_offset != -1);
+        ASSERT(where.isSet());
 
         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
     }
@@ -1568,6 +1548,13 @@ public:
     {
         setRel32(from, to);
     }
+    
+    static void repatchCompact(void* where, int32_t value)
+    {
+        ASSERT(value >= 0);
+        ASSERT(value <= std::numeric_limits<int8_t>::max());
+        setInt8(where, value);
+    }
 
     static void repatchInt32(void* where, int32_t value)
     {
@@ -1578,57 +1565,43 @@ public:
     {
         setPointer(where, value);
     }
-
-    static void repatchLoadPtrToLEA(void* where)
-    {
-#if CPU(X86_64)
-        // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix.
-        // Skip over the prefix byte.
-        where = reinterpret_cast<char*>(where) + 1;
-#endif
-        *reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_LEA);
-    }
     
-    static unsigned getCallReturnOffset(JmpSrc call)
+    static void* readPointer(void* where)
     {
-        ASSERT(call.m_offset >= 0);
-        return call.m_offset;
+        return reinterpret_cast<void**>(where)[-1];
     }
 
-    static void* getRelocatedAddress(void* code, JmpSrc jump)
+    static unsigned getCallReturnOffset(AssemblerLabel call)
     {
-        ASSERT(jump.m_offset != -1);
-
-        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
+        ASSERT(call.isSet());
+        return call.m_offset;
     }
-    
-    static void* getRelocatedAddress(void* code, JmpDst destination)
-    {
-        ASSERT(destination.m_offset != -1);
 
-        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
-    }
-    
-    static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
+    static void* getRelocatedAddress(void* code, AssemblerLabel label)
     {
-        return dst.m_offset - src.m_offset;
+        ASSERT(label.isSet());
+        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.m_offset);
     }
     
-    static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
+    static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
     {
-        return dst.m_offset - src.m_offset;
+        return b.m_offset - a.m_offset;
     }
     
-    static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
+    void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
     {
-        return dst.m_offset - src.m_offset;
+        return m_formatter.executableCopy(globalData, allocator);
     }
-    
-    void* executableCopy(ExecutablePool* allocator)
+
+    void rewindToLabel(AssemblerLabel rewindTo) { m_formatter.rewindToLabel(rewindTo); }
+
+#ifndef NDEBUG
+    unsigned debugOffset() { return m_formatter.debugOffset(); }
+#endif
+
+    void nop()
     {
-        void* copy = m_formatter.executableCopy(allocator);
-        ASSERT(copy);
-        return copy;
+        m_formatter.oneByteOp(OP_NOP);
     }
 
 private:
@@ -1642,6 +1615,11 @@ private:
     {
         reinterpret_cast<int32_t*>(where)[-1] = value;
     }
+    
+    static void setInt8(void* where, int8_t value)
+    {
+        reinterpret_cast<int8_t*>(where)[-1] = value;
+    }
 
     static void setRel32(void* from, void* to)
     {
@@ -1716,6 +1694,14 @@ private:
             m_buffer.putByteUnchecked(opcode);
             memoryModRM_disp32(reg, base, offset);
         }
+        
+        void oneByteOp_disp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM_disp8(reg, base, offset);
+        }
 
         void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
         {
@@ -1726,7 +1712,7 @@ private:
         }
 
 #if !CPU(X86_64)
-        void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
+        void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address)
         {
             m_buffer.ensureSpace(maxInstructionSize);
             m_buffer.putByteUnchecked(opcode);
@@ -1822,6 +1808,14 @@ private:
             m_buffer.putByteUnchecked(opcode);
             memoryModRM_disp32(reg, base, offset);
         }
+        
+        void oneByteOp64_disp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexW(reg, 0, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM_disp8(reg, base, offset);
+        }
 
         void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
         {
@@ -1917,18 +1911,29 @@ private:
             m_buffer.putInt64Unchecked(imm);
         }
 
-        JmpSrc immediateRel32()
+        AssemblerLabel immediateRel32()
         {
             m_buffer.putIntUnchecked(0);
-            return JmpSrc(m_buffer.size());
+            return label();
         }
 
         // Administrative methods:
 
-        size_t size() const { return m_buffer.size(); }
+        size_t codeSize() const { return m_buffer.codeSize(); }
+        AssemblerLabel label() const { return m_buffer.label(); }
         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
         void* data() const { return m_buffer.data(); }
-        void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
+
+        void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+        {
+            return m_buffer.executableCopy(globalData, allocator);
+        }
+
+        void rewindToLabel(AssemblerLabel rewindTo) { m_buffer.rewindToLabel(rewindTo); }
+
+#ifndef NDEBUG
+        unsigned debugOffset() { return m_buffer.debugOffset(); }
+#endif
 
     private:
 
@@ -2043,7 +2048,24 @@ private:
                 }
             }
         }
-    
+
+        void memoryModRM_disp8(int reg, RegisterID base, int offset)
+        {
+            // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
+            ASSERT(CAN_SIGN_EXTEND_8_32(offset));
+#if CPU(X86_64)
+            if ((base == hasSib) || (base == hasSib2)) {
+#else
+            if (base == hasSib) {
+#endif
+                putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);
+                m_buffer.putByteUnchecked(offset);
+            } else {
+                putModRm(ModRmMemoryDisp8, reg, base);
+                m_buffer.putByteUnchecked(offset);
+            }
+        }
+
         void memoryModRM_disp32(int reg, RegisterID base, int offset)
         {
             // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
index 8cefb1ba9adfe2d3ee9a032acdf9b6f0619ae747..fc99e90158dcf6c8345d15e0813fa1bf2a679341 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  *
  * Redistribution and use in source and binary forms, with or without
 #include "config.h"
 #include "CodeBlock.h"
 
-#include "JIT.h"
-#include "JSValue.h"
+#include "BytecodeGenerator.h"
+#include "Debugger.h"
 #include "Interpreter.h"
+#include "JIT.h"
+#include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSStaticScopeObject.h"
-#include "Debugger.h"
-#include "BytecodeGenerator.h"
+#include "JSValue.h"
+#include "RepatchBuffer.h"
+#include "UStringConcatenate.h"
 #include <stdio.h>
 #include <wtf/StringExtras.h>
 
@@ -49,9 +52,9 @@ namespace JSC {
 static UString escapeQuotes(const UString& str)
 {
     UString result = str;
-    unsigned pos = 0;
-    while ((pos = result.find('\"', pos)) != UString::NotFound) {
-        result = makeString(result.substr(0, pos), "\"\\\"\"", result.substr(pos + 1));
+    size_t pos = 0;
+    while ((pos = result.find('\"', pos)) != notFound) {
+        result = makeUString(result.substringSharingImpl(0, pos), "\"\\\"\"", result.substringSharingImpl(pos + 1));
         pos += 4;
     }
     return result;
@@ -63,19 +66,19 @@ static UString valueToSourceString(ExecState* exec, JSValue val)
         return "0";
 
     if (val.isString())
-        return makeString("\"", escapeQuotes(val.toString(exec)), "\"");
+        return makeUString("\"", escapeQuotes(val.toString(exec)), "\"");
 
     return val.toString(exec);
 }
 
 static CString constantName(ExecState* exec, int k, JSValue value)
 {
-    return makeString(valueToSourceString(exec, value), "(@k", UString::from(k - FirstConstantRegisterIndex), ")").UTF8String();
+    return makeUString(valueToSourceString(exec, value), "(@k", UString::number(k - FirstConstantRegisterIndex), ")").utf8();
 }
 
 static CString idName(int id0, const Identifier& ident)
 {
-    return makeString(ident.ustring(), "(@id", UString::from(id0), ")").UTF8String();
+    return makeUString(ident.ustring(), "(@id", UString::number(id0), ")").utf8();
 }
 
 CString CodeBlock::registerName(ExecState* exec, int r) const
@@ -86,7 +89,7 @@ CString CodeBlock::registerName(ExecState* exec, int r) const
     if (isConstantRegisterIndex(r))
         return constantName(exec, r, getConstant(r));
 
-    return makeString("r", UString::from(r)).UTF8String();
+    return makeUString("r", UString::number(r)).utf8();
 }
 
 static UString regexpToSourceString(RegExp* regExp)
@@ -100,12 +103,12 @@ static UString regexpToSourceString(RegExp* regExp)
     if (regExp->multiline())
         postfix[index] = 'm';
 
-    return makeString("/", regExp->pattern(), postfix);
+    return makeUString("/", regExp->pattern(), postfix);
 }
 
 static CString regexpName(int re, RegExp* regexp)
 {
-    return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String();
+    return makeUString(regexpToSourceString(regexp), "(@re", UString::number(re), ")").utf8();
 }
 
 static UString pointerToSourceString(void* p)
@@ -174,7 +177,7 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction
     int id0 = (++it)->u.operand;
     int r1 = (++it)->u.operand;
     printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data());
-    it += 4;
+    it += 5;
 }
 
 #if ENABLE(JIT)
@@ -223,32 +226,32 @@ static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instructio
 
 static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
 {
-    printf("  [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().data());
+    printf("  [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).utf8().data());
 }
 
 static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
 {
     switch (stubInfo.accessType) {
     case access_get_by_id_self:
-        printf("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().data());
+        printf("  [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).utf8().data());
         return;
     case access_get_by_id_proto:
-        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().data());
+        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).utf8().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).utf8().data());
         return;
     case access_get_by_id_chain:
-        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().data());
+        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).utf8().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).utf8().data());
         return;
     case access_get_by_id_self_list:
-        printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().data(), stubInfo.u.getByIdSelfList.listSize);
+        printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).utf8().data(), stubInfo.u.getByIdSelfList.listSize);
         return;
     case access_get_by_id_proto_list:
-        printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().data(), stubInfo.u.getByIdProtoList.listSize);
+        printf("  [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).utf8().data(), stubInfo.u.getByIdProtoList.listSize);
         return;
     case access_put_by_id_transition:
-        printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().data(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().data());
+        printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).utf8().data(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).utf8().data(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).utf8().data());
         return;
     case access_put_by_id_replace:
-        printf("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().data());
+        printf("  [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).utf8().data());
         return;
     case access_get_by_id:
         printf("  [%4d] %s\n", instructionOffset, "get_by_id");
@@ -277,7 +280,7 @@ static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned i
 void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
 {
     unsigned instructionOffset = vPC - m_instructions.begin();
-    printf("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().data());
+    printf("  [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data());
 }
 
 void CodeBlock::printStructures(const Instruction* vPC) const
@@ -294,15 +297,15 @@ void CodeBlock::printStructures(const Instruction* vPC) const
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
-        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data());
+        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data());
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
-        printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().data());
+        printf("  [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structure).utf8().data(), pointerToSourceString(vPC[6].u.structureChain).utf8().data());
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
-        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().data());
+        printf("  [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).utf8().data(), pointerToSourceString(vPC[5].u.structureChain).utf8().data());
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
@@ -352,7 +355,7 @@ void CodeBlock::dump(ExecState* exec) const
         printf("\nIdentifiers:\n");
         size_t i = 0;
         do {
-            printf("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());
+            printf("  id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ustring().utf8().data());
             ++i;
         } while (i != m_identifiers.size());
     }
@@ -362,7 +365,7 @@ void CodeBlock::dump(ExecState* exec) const
         unsigned registerIndex = m_numVars;
         size_t i = 0;
         do {
-            printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii());
+            printf("   k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].get()).utf8().data());
             ++i;
             ++registerIndex;
         } while (i < m_constantRegisters.size());
@@ -372,7 +375,7 @@ void CodeBlock::dump(ExecState* exec) const
         printf("\nm_regexps:\n");
         size_t i = 0;
         do {
-            printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());
+            printf("  re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).utf8().data());
             ++i;
         } while (i < m_rareData->m_regexps.size());
     }
@@ -395,7 +398,8 @@ void CodeBlock::dump(ExecState* exec) const
              ++i;
         } while (i < m_structureStubInfos.size());
     }
-#else
+#endif
+#if ENABLE(INTERPRETER)
     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
         printf("\nStructures:\n");
 
@@ -453,7 +457,7 @@ void CodeBlock::dump(ExecState* exec) const
                     continue;
                 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
                 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
-                printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
+                printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).utf8().data(), *iter);
         }
             printf("      }\n");
             ++i;
@@ -467,7 +471,7 @@ void CodeBlock::dump(ExecState* exec) const
             printf("  %1d = {\n", i);
             StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
             for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
-                printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
+                printf("\t\t\"%s\" => %04d\n", UString(iter->first).utf8().data(), iter->second.branchOffset);
             printf("      }\n");
             ++i;
         } while (i < m_rareData->m_stringSwitchJumpTables.size());
@@ -484,17 +488,30 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] enter\n", location);
             break;
         }
-        case op_enter_with_activation: {
+        case op_create_activation: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data());
+            printf("[%4d] create_activation %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_create_arguments: {
-            printf("[%4d] create_arguments\n", location);
+            int r0 = (++it)->u.operand;
+            printf("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data());
             break;
         }
-        case op_init_arguments: {
-            printf("[%4d] init_arguments\n", location);
+        case op_init_lazy_reg: {
+            int r0 = (++it)->u.operand;
+            printf("[%4d] init_lazy_reg\t %s\n", location, registerName(exec, r0).data());
+            break;
+        }
+        case op_get_callee: {
+            int r0 = (++it)->u.operand;
+            printf("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
+            break;
+        }
+        case op_create_this: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            printf("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_convert_this: {
@@ -502,6 +519,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data());
             break;
         }
+        case op_convert_this_strict: {
+            int r0 = (++it)->u.operand;
+            printf("[%4d] convert_this_strict %s\n", location, registerName(exec, r0).data());
+            break;
+        }
         case op_new_object: {
             int r0 = (++it)->u.operand;
             printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).data());
@@ -514,6 +536,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
             break;
         }
+        case op_new_array_buffer: {
+            int dst = (++it)->u.operand;
+            int argv = (++it)->u.operand;
+            int argc = (++it)->u.operand;
+            printf("[%4d] new_array_buffer %s, %d, %d\n", location, registerName(exec, dst).data(), argv, argc);
+            break;
+        }
         case op_new_regexp: {
             int r0 = (++it)->u.operand;
             int re0 = (++it)->u.operand;
@@ -643,6 +672,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printUnaryOp(exec, location, it, "bitnot");
             break;
         }
+        case op_check_has_instance: {
+            int base = (++it)->u.operand;
+            printf("[%4d] check_has_instance\t\t %s\n", location, registerName(exec, base).data());
+            break;
+        }
         case op_instanceof: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
@@ -698,19 +732,18 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_resolve_global: {
             int r0 = (++it)->u.operand;
-            JSValue scope = JSValue((++it)->u.jsCell);
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data());
+            printf("[%4d] resolve_global\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
             it += 2;
             break;
         }
         case op_resolve_global_dynamic: {
             int r0 = (++it)->u.operand;
-            JSValue scope = JSValue((++it)->u.jsCell);
             int id0 = (++it)->u.operand;
-            int depth = it[2].u.operand;
-            printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data(), depth);
-            it += 3;
+            JSValue scope = JSValue((++it)->u.jsCell.get());
+            ++it;
+            int depth = (++it)->u.operand;
+            printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth);
             break;
         }
         case op_get_scoped_var: {
@@ -729,22 +762,27 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_get_global_var: {
             int r0 = (++it)->u.operand;
-            JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
-            printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), index);
+            printf("[%4d] get_global_var\t %s, %d\n", location, registerName(exec, r0).data(), index);
             break;
         }
         case op_put_global_var: {
-            JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
             int r0 = (++it)->u.operand;
-            printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(exec, r0).data());
+            printf("[%4d] put_global_var\t %d, %s\n", location, index, registerName(exec, r0).data());
             break;
         }
         case op_resolve_base: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
-            printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+            int isStrict = (++it)->u.operand;
+            printf("[%4d] resolve_base%s\t %s, %s\n", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
+            break;
+        }
+        case op_ensure_property_exists: {
+            int r0 = (++it)->u.operand;
+            int id0 = (++it)->u.operand;
+            printf("[%4d] ensure_property_exists\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data());
             break;
         }
         case op_resolve_with_base: {
@@ -830,6 +868,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printGetByIdOp(exec, location, it, "get_string_length");
             break;
         }
+        case op_get_arguments_length: {
+            printUnaryOp(exec, location, it, "get_arguments_length");
+            it++;
+            break;
+        }
         case op_put_by_id: {
             printPutByIdOp(exec, location, it, "put_by_id");
             break;
@@ -878,6 +921,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
             break;
         }
+        case op_get_argument_by_val: {
+            int r0 = (++it)->u.operand;
+            int r1 = (++it)->u.operand;
+            int r2 = (++it)->u.operand;
+            printf("[%4d] get_argument_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
+            break;
+        }
         case op_get_by_pname: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
@@ -1016,7 +1066,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         case op_new_func: {
             int r0 = (++it)->u.operand;
             int f0 = (++it)->u.operand;
-            printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(exec, r0).data(), f0);
+            int shouldCheck = (++it)->u.operand;
+            printf("[%4d] new_func\t\t %s, f%d, %s\n", location, registerName(exec, r0).data(), f0, shouldCheck ? "<Checked>" : "<Unchecked>");
             break;
         }
         case op_new_func_exp: {
@@ -1026,27 +1077,24 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             break;
         }
         case op_call: {
-            int dst = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
-            printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset);
+            printf("[%4d] call\t\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
             break;
         }
         case op_call_eval: {
-            int dst = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
-            printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset);
+            printf("[%4d] call_eval\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
             break;
         }
         case op_call_varargs: {
-            int dst = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++it)->u.operand;
-            printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset);
+            printf("[%4d] call_varargs\t %s, %s, %d\n", location, registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset);
             break;
         }
         case op_load_varargs: {
@@ -1055,11 +1103,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_tear_off_activation: {
             int r0 = (++it)->u.operand;
-            printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).data());
+            int r1 = (++it)->u.operand;
+            printf("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
             break;
         }
         case op_tear_off_arguments: {
-            printf("[%4d] tear_off_arguments\n", location);
+            int r0 = (++it)->u.operand;
+            printf("[%4d] tear_off_arguments\t %s\n", location, registerName(exec, r0).data());
             break;
         }
         case op_ret: {
@@ -1067,20 +1117,22 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
-        case op_construct: {
-            int dst = (++it)->u.operand;
-            int func = (++it)->u.operand;
-            int argCount = (++it)->u.operand;
-            int registerOffset = (++it)->u.operand;
-            int proto = (++it)->u.operand;
-            int thisRegister = (++it)->u.operand;
-            printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset, registerName(exec, proto).data(), registerName(exec, thisRegister).data());
+        case op_call_put_result: {
+            int r0 = (++it)->u.operand;
+            printf("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
-        case op_construct_verify: {
+        case op_ret_object_or_this: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
-            printf("[%4d] construct_verify\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+            printf("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+            break;
+        }
+        case op_construct: {
+            int func = (++it)->u.operand;
+            int argCount = (++it)->u.operand;
+            int registerOffset = (++it)->u.operand;
+            printf("[%4d] construct\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
             break;
         }
         case op_strcat: {
@@ -1108,9 +1160,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
         }
         case op_next_pname: {
             int dest = it[1].u.operand;
-            int iter = it[4].u.operand;
-            int offset = it[5].u.operand;
-            printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, iter).data(), offset, location + offset);
+            int base = it[2].u.operand;
+            int i = it[3].u.operand;
+            int size = it[4].u.operand;
+            int iter = it[5].u.operand;
+            int offset = it[6].u.operand;
+            printf("[%4d] next_pname\t %s, %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, base).data(), registerName(exec, i).data(), registerName(exec, size).data(), registerName(exec, iter).data(), offset, location + offset);
             it += OPCODE_LENGTH(op_next_pname) - 1;
             break;
         }
@@ -1146,11 +1201,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data());
             break;
         }
-        case op_new_error: {
-            int r0 = (++it)->u.operand;
-            int errorType = (++it)->u.operand;
+        case op_throw_reference_error: {
             int k0 = (++it)->u.operand;
-            printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(exec, r0).data(), errorType, constantName(exec, k0, getConstant(k0)).data());
+            printf("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
             break;
         }
         case op_jsr: {
@@ -1212,13 +1265,10 @@ static HashSet<CodeBlock*> liveCodeBlockSet;
     macro(immediateSwitchJumpTables) \
     macro(characterSwitchJumpTables) \
     macro(stringSwitchJumpTables) \
-    macro(functionRegisterInfos)
-
-#define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \
+    macro(evalCodeCache) \
     macro(expressionInfo) \
     macro(lineInfo) \
-    macro(getByIdExceptionInfo) \
-    macro(pcVector)
+    macro(callReturnIndexVector)
 
 template<typename T>
 static size_t sizeInBytes(const Vector<T>& vector)
@@ -1232,7 +1282,6 @@ void CodeBlock::dumpStatistics()
     #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
         FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
         FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
-        FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS)
     #undef DEFINE_VARS
 
     // Non-vector data members
@@ -1241,7 +1290,6 @@ void CodeBlock::dumpStatistics()
     size_t symbolTableIsNotEmpty = 0;
     size_t symbolTableTotalSize = 0;
 
-    size_t hasExceptionInfo = 0;
     size_t hasRareData = 0;
 
     size_t isFunctionCode = 0;
@@ -1261,13 +1309,6 @@ void CodeBlock::dumpStatistics()
             symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
         }
 
-        if (codeBlock->m_exceptionInfo) {
-            hasExceptionInfo++;
-            #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); }
-                FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS)
-            #undef GET_STATS
-        }
-
         if (codeBlock->m_rareData) {
             hasRareData++;
             #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
@@ -1296,7 +1337,6 @@ void CodeBlock::dumpStatistics()
     #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
         FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
         FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
-        FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE)
     #undef GET_TOTAL_SIZE
 
     totalSize += symbolTableTotalSize;
@@ -1311,13 +1351,11 @@ void CodeBlock::dumpStatistics()
     printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
     printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
 
-    printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size());
     printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
 
     #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize); 
         FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
         FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
-        FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS)
     #undef PRINT_STATS
 
     printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
@@ -1330,24 +1368,27 @@ void CodeBlock::dumpStatistics()
 #endif
 }
 
-CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab)
-    : m_numCalleeRegisters(0)
+CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject *globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor)
+    : m_globalObject(globalObject->globalData(), ownerExecutable, globalObject)
+    , m_heap(&m_globalObject->globalData().heap)
+    , m_numCalleeRegisters(0)
     , m_numVars(0)
     , m_numParameters(0)
-    , m_ownerExecutable(ownerExecutable)
+    , m_isConstructor(isConstructor)
+    , m_ownerExecutable(globalObject->globalData(), ownerExecutable, ownerExecutable)
     , m_globalData(0)
 #ifndef NDEBUG
     , m_instructionCount(0)
 #endif
+    , m_argumentsRegister(-1)
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
-    , m_usesArguments(false)
     , m_isNumericCompareFunction(false)
+    , m_isStrictMode(ownerExecutable->isStrictMode())
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
     , m_symbolTable(symTab)
-    , m_exceptionInfo(new ExceptionInfo)
 {
     ASSERT(m_source);
 
@@ -1358,41 +1399,9 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassR
 
 CodeBlock::~CodeBlock()
 {
-#if ENABLE(INTERPRETER)
-    for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
-        derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
-
-    for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
-        derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
-#endif
 #if ENABLE(JIT)
-    for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
-        if (m_globalResolveInfos[i].structure)
-            m_globalResolveInfos[i].structure->deref();
-    }
-
     for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
         m_structureStubInfos[i].deref();
-
-    for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
-        CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
-        if (callLinkInfo->isLinked())
-            callLinkInfo->callee->removeCaller(callLinkInfo);
-    }
-
-    for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
-        if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) {
-            structure->deref();
-            // Both members must be filled at the same time
-            ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
-            m_methodCallLinkInfos[i].cachedPrototypeStructure->deref();
-        }
-    }
-
-#if ENABLE(JIT_OPTIMIZE_CALL)
-    unlinkCallers();
-#endif
-
 #endif // ENABLE(JIT)
 
 #if DUMP_CODE_BLOCK_STATISTICS
@@ -1400,50 +1409,46 @@ CodeBlock::~CodeBlock()
 #endif
 }
 
-#if ENABLE(JIT_OPTIMIZE_CALL)
-void CodeBlock::unlinkCallers()
-{
-    size_t size = m_linkedCallerList.size();
-    for (size_t i = 0; i < size; ++i) {
-        CallLinkInfo* currentCaller = m_linkedCallerList[i];
-        JIT::unlinkCall(currentCaller);
-        currentCaller->setUnlinked();
-    }
-    m_linkedCallerList.clear();
-}
-#endif
-
-void CodeBlock::derefStructures(Instruction* vPC) const
+void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
 {
     Interpreter* interpreter = m_globalData->interpreter;
 
+    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) && vPC[4].u.structure) {
+        visitor.append(&vPC[4].u.structure);
+        return;
+    }
+
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
-        vPC[4].u.structure->deref();
+        visitor.append(&vPC[4].u.structure);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
-        vPC[4].u.structure->deref();
-        vPC[5].u.structure->deref();
+        visitor.append(&vPC[4].u.structure);
+        visitor.append(&vPC[5].u.structure);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
-        vPC[4].u.structure->deref();
-        vPC[5].u.structureChain->deref();
+        visitor.append(&vPC[4].u.structure);
+        visitor.append(&vPC[5].u.structureChain);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
-        vPC[4].u.structure->deref();
-        vPC[5].u.structure->deref();
-        vPC[6].u.structureChain->deref();
+        visitor.append(&vPC[4].u.structure);
+        visitor.append(&vPC[5].u.structure);
+        visitor.append(&vPC[6].u.structureChain);
+        return;
+    }
+    if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) && vPC[4].u.structure) {
+        visitor.append(&vPC[4].u.structure);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
-        vPC[4].u.structure->deref();
+        visitor.append(&vPC[4].u.structure);
         return;
     }
     if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global) || vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) {
-        if(vPC[4].u.structure)
-            vPC[4].u.structure->deref();
+        if (vPC[3].u.structure)
+            visitor.append(&vPC[3].u.structure);
         return;
     }
     if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
@@ -1453,7 +1458,7 @@ void CodeBlock::derefStructures(Instruction* vPC) const
         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto_list))
         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self_list))) {
         PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
-        polymorphicStructures->derefStructures(vPC[5].u.operand);
+        polymorphicStructures->visitAggregate(visitor, vPC[5].u.operand);
         delete polymorphicStructures;
         return;
     }
@@ -1462,68 +1467,62 @@ void CodeBlock::derefStructures(Instruction* vPC) const
     ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
 }
 
-void CodeBlock::refStructures(Instruction* vPC) const
+void EvalCodeCache::visitAggregate(SlotVisitor& visitor)
 {
-    Interpreter* interpreter = m_globalData->interpreter;
-
-    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
-        vPC[4].u.structure->ref();
-        return;
-    }
-    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
-        vPC[4].u.structure->ref();
-        vPC[5].u.structure->ref();
-        return;
-    }
-    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
-        vPC[4].u.structure->ref();
-        vPC[5].u.structureChain->ref();
-        return;
-    }
-    if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
-        vPC[4].u.structure->ref();
-        vPC[5].u.structure->ref();
-        vPC[6].u.structureChain->ref();
-        return;
-    }
-    if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
-        vPC[4].u.structure->ref();
-        return;
-    }
-    
-    // These instructions don't ref their Structures.
-    ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
+    EvalCacheMap::iterator end = m_cacheMap.end();
+    for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr)
+        visitor.append(&ptr->second);
 }
 
-void CodeBlock::markAggregate(MarkStack& markStack)
+void CodeBlock::visitAggregate(SlotVisitor& visitor)
 {
-    for (size_t i = 0; i < m_constantRegisters.size(); ++i)
-        markStack.append(m_constantRegisters[i].jsValue());
+    visitor.append(&m_globalObject);
+    visitor.append(&m_ownerExecutable);
+    if (m_rareData) {
+        m_rareData->m_evalCodeCache.visitAggregate(visitor);
+        size_t regExpCount = m_rareData->m_regexps.size();
+        WriteBarrier<RegExp>* regexps = m_rareData->m_regexps.data();
+        for (size_t i = 0; i < regExpCount; i++)
+            visitor.append(regexps + i);
+    }
+    visitor.appendValues(m_constantRegisters.data(), m_constantRegisters.size());
     for (size_t i = 0; i < m_functionExprs.size(); ++i)
-        m_functionExprs[i]->markAggregate(markStack);
+        visitor.append(&m_functionExprs[i]);
     for (size_t i = 0; i < m_functionDecls.size(); ++i)
-        m_functionDecls[i]->markAggregate(markStack);
-}
+        visitor.append(&m_functionDecls[i]);
+#if ENABLE(JIT_OPTIMIZE_CALL)
+    if (visitor.shouldUnlinkCalls())
+        unlinkCalls();
+    for (unsigned i = 0; i < numberOfCallLinkInfos(); ++i)
+        if (callLinkInfo(i).isLinked())
+            visitor.append(&callLinkInfo(i).callee);
+#endif
+#if ENABLE(INTERPRETER)
+    for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
+        visitStructures(visitor, &m_instructions[m_propertyAccessInstructions[i]]);
+    for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
+        visitStructures(visitor, &m_instructions[m_globalResolveInstructions[i]]);
+#endif
+#if ENABLE(JIT)
+    for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
+        if (m_globalResolveInfos[i].structure)
+            visitor.append(&m_globalResolveInfos[i].structure);
+    }
 
-void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
-{
-    if (m_exceptionInfo)
-        return;
+    for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
+        m_structureStubInfos[i].visitAggregate(visitor);
 
-    ScopeChainNode* scopeChain = callFrame->scopeChain();
-    if (m_needsFullScopeChain) {
-        ScopeChain sc(scopeChain);
-        int scopeDelta = sc.localDepth();
-        if (m_codeType == EvalCode)
-            scopeDelta -= static_cast<EvalCodeBlock*>(this)->baseScopeDepth();
-        else if (m_codeType == FunctionCode)
-            scopeDelta++; // Compilation of function code assumes activation is not on the scope chain yet.
-        ASSERT(scopeDelta >= 0);
-        while (scopeDelta--)
-            scopeChain = scopeChain->next;
+    for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) {
+        if (m_methodCallLinkInfos[i].cachedStructure) {
+            // Both members must be filled at the same time
+            visitor.append(&m_methodCallLinkInfos[i].cachedStructure);
+            ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure);
+            visitor.append(&m_methodCallLinkInfos[i].cachedPrototypeStructure);
+            visitor.append(&m_methodCallLinkInfos[i].cachedFunction);
+            visitor.append(&m_methodCallLinkInfos[i].cachedPrototype);
+        }
     }
-
-    m_exceptionInfo.set(m_ownerExecutable->reparseExceptionInfo(m_globalData, scopeChain, this));
+#endif
 }
 
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
@@ -1544,122 +1543,66 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
     return 0;
 }
 
-int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
+int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 {
     ASSERT(bytecodeOffset < m_instructionCount);
 
-    reparseForExceptionInfoIfNecessary(callFrame);
-    ASSERT(m_exceptionInfo);
+    if (!m_rareData)
+        return m_ownerExecutable->source().firstLine();
 
-    if (!m_exceptionInfo->m_lineInfo.size())
-        return m_ownerExecutable->source().firstLine(); // Empty function
+    Vector<LineInfo>& lineInfo = m_rareData->m_lineInfo;
 
     int low = 0;
-    int high = m_exceptionInfo->m_lineInfo.size();
+    int high = lineInfo.size();
     while (low < high) {
         int mid = low + (high - low) / 2;
-        if (m_exceptionInfo->m_lineInfo[mid].instructionOffset <= bytecodeOffset)
+        if (lineInfo[mid].instructionOffset <= bytecodeOffset)
             low = mid + 1;
         else
             high = mid;
     }
-    
+
     if (!low)
         return m_ownerExecutable->source().firstLine();
-    return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
+    return lineInfo[low - 1].lineNumber;
 }
 
-int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
+void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
 {
     ASSERT(bytecodeOffset < m_instructionCount);
 
-    reparseForExceptionInfoIfNecessary(callFrame);
-    ASSERT(m_exceptionInfo);
-
-    if (!m_exceptionInfo->m_expressionInfo.size()) {
-        // We didn't think anything could throw.  Apparently we were wrong.
+    if (!m_rareData) {
         startOffset = 0;
         endOffset = 0;
         divot = 0;
-        return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+        return;
     }
 
+    Vector<ExpressionRangeInfo>& expressionInfo = m_rareData->m_expressionInfo;
+
     int low = 0;
-    int high = m_exceptionInfo->m_expressionInfo.size();
+    int high = expressionInfo.size();
     while (low < high) {
         int mid = low + (high - low) / 2;
-        if (m_exceptionInfo->m_expressionInfo[mid].instructionOffset <= bytecodeOffset)
+        if (expressionInfo[mid].instructionOffset <= bytecodeOffset)
             low = mid + 1;
         else
             high = mid;
     }
-    
+
     ASSERT(low);
     if (!low) {
         startOffset = 0;
         endOffset = 0;
         divot = 0;
-        return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
-    }
-
-    startOffset = m_exceptionInfo->m_expressionInfo[low - 1].startOffset;
-    endOffset = m_exceptionInfo->m_expressionInfo[low - 1].endOffset;
-    divot = m_exceptionInfo->m_expressionInfo[low - 1].divotPoint + m_sourceOffset;
-    return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
-}
-
-bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
-{
-    ASSERT(bytecodeOffset < m_instructionCount);
-
-    reparseForExceptionInfoIfNecessary(callFrame);
-    ASSERT(m_exceptionInfo);        
-
-    if (!m_exceptionInfo->m_getByIdExceptionInfo.size())
-        return false;
-
-    int low = 0;
-    int high = m_exceptionInfo->m_getByIdExceptionInfo.size();
-    while (low < high) {
-        int mid = low + (high - low) / 2;
-        if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
-            low = mid + 1;
-        else
-            high = mid;
-    }
-
-    if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
-        return false;
-
-    opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof;
-    return true;
-}
-
-#if ENABLE(JIT)
-bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
-{
-    ASSERT(bytecodeOffset < m_instructionCount);
-
-    if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
-        return false;
-
-    int low = 0;
-    int high = m_rareData->m_functionRegisterInfos.size();
-    while (low < high) {
-        int mid = low + (high - low) / 2;
-        if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset)
-            low = mid + 1;
-        else
-            high = mid;
+        return;
     }
 
-    if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset)
-        return false;
-
-    functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex;
-    return true;
+    startOffset = expressionInfo[low - 1].startOffset;
+    endOffset = expressionInfo[low - 1].endOffset;
+    divot = expressionInfo[low - 1].divotPoint + m_sourceOffset;
+    return;
 }
-#endif
 
 #if ENABLE(INTERPRETER)
 bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
@@ -1716,7 +1659,6 @@ void CodeBlock::shrinkToFit()
     m_structureStubInfos.shrinkToFit();
     m_globalResolveInfos.shrinkToFit();
     m_callLinkInfos.shrinkToFit();
-    m_linkedCallerList.shrinkToFit();
 #endif
 
     m_identifiers.shrinkToFit();
@@ -1724,22 +1666,49 @@ void CodeBlock::shrinkToFit()
     m_functionExprs.shrinkToFit();
     m_constantRegisters.shrinkToFit();
 
-    if (m_exceptionInfo) {
-        m_exceptionInfo->m_expressionInfo.shrinkToFit();
-        m_exceptionInfo->m_lineInfo.shrinkToFit();
-        m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit();
-    }
-
     if (m_rareData) {
         m_rareData->m_exceptionHandlers.shrinkToFit();
         m_rareData->m_regexps.shrinkToFit();
         m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
         m_rareData->m_characterSwitchJumpTables.shrinkToFit();
         m_rareData->m_stringSwitchJumpTables.shrinkToFit();
+        m_rareData->m_expressionInfo.shrinkToFit();
+        m_rareData->m_lineInfo.shrinkToFit();
+    }
+}
+
+void CodeBlock::createActivation(CallFrame* callFrame)
+{
+    ASSERT(codeType() == FunctionCode);
+    ASSERT(needsFullScopeChain());
+    ASSERT(!callFrame->uncheckedR(activationRegister()).jsValue());
+    JSActivation* activation = new (callFrame) JSActivation(callFrame, static_cast<FunctionExecutable*>(ownerExecutable()));
+    callFrame->uncheckedR(activationRegister()) = JSValue(activation);
+    callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
+}
+    
 #if ENABLE(JIT)
-        m_rareData->m_functionRegisterInfos.shrinkToFit();
-#endif
+void CodeBlock::unlinkCalls()
+{
+    if (!(m_callLinkInfos.size() || m_methodCallLinkInfos.size()))
+        return;
+    if (!m_globalData->canUseJIT())
+        return;
+    RepatchBuffer repatchBuffer(this);
+    for (size_t i = 0; i < m_callLinkInfos.size(); i++) {
+        if (!m_callLinkInfos[i].isLinked())
+            continue;
+        repatchBuffer.relink(m_callLinkInfos[i].callReturnLocation, m_callLinkInfos[i].isCall ? m_globalData->jitStubs->ctiVirtualCallLink() : m_globalData->jitStubs->ctiVirtualConstructLink());
+        m_callLinkInfos[i].unlink();
     }
 }
+#endif
+
+void CodeBlock::clearEvalCache()
+{
+    if (!m_rareData)
+        return;
+    m_rareData->m_evalCodeCache.clear();
+}
 
 } // namespace JSC
index 63d9b8a16dafb7ab0e4e371df521a2d8ae375f56..7aa356ecf159a38e240dbd63b1a2b9b3daa0623e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
  *
  * Redistribution and use in source and binary forms, with or without
 #include "EvalCodeCache.h"
 #include "Instruction.h"
 #include "JITCode.h"
+#include "JITWriteBarrier.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Nodes.h"
-#include "RegExp.h"
+#include "RegExpObject.h"
 #include "UString.h"
 #include <wtf/FastAllocBase.h>
+#include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
@@ -46,8 +48,8 @@
 #include "StructureStubInfo.h"
 #endif
 
-// Register numbers used in bytecode operations have different meaning accoring to their ranges:
-//      0x80000000-0xFFFFFFFF  Negative indicies from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
+// Register numbers used in bytecode operations have different meaning according to their ranges:
+//      0x80000000-0xFFFFFFFF  Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
 //      0x00000000-0x3FFFFFFF  Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
 //      0x40000000-0x7FFFFFFF  Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
 static const int FirstConstantRegisterIndex = 0x40000000;
@@ -62,6 +64,8 @@ namespace JSC {
 
     enum CodeType { GlobalCode, EvalCode, FunctionCode };
 
+    inline int unmodifiedArgumentsRegister(int argumentsRegister) { return argumentsRegister - 1; }
+
     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
     struct HandlerInfo {
@@ -90,34 +94,27 @@ namespace JSC {
         int32_t lineNumber;
     };
 
-    // Both op_construct and op_instanceof require a use of op_get_by_id to get
-    // the prototype property from an object. The exception messages for exceptions
-    // thrown by these instances op_get_by_id need to reflect this.
-    struct GetByIdExceptionInfo {
-        unsigned bytecodeOffset : 31;
-        bool isOpConstruct : 1;
-    };
-
 #if ENABLE(JIT)
     struct CallLinkInfo {
         CallLinkInfo()
-            : callee(0)
-            , position(0)
-            , hasSeenShouldRepatch(0)
+            : hasSeenShouldRepatch(false)
+            , isCall(false)
         {
         }
 
-        unsigned bytecodeIndex;
         CodeLocationNearCall callReturnLocation;
         CodeLocationDataLabelPtr hotPathBegin;
         CodeLocationNearCall hotPathOther;
-        CodeBlock* ownerCodeBlock;
-        CodeBlock* callee;
-        unsigned position : 31;
-        unsigned hasSeenShouldRepatch : 1;
-        
-        void setUnlinked() { callee = 0; }
+        JITWriteBarrier<JSFunction> callee;
+        bool hasSeenShouldRepatch : 1;
+        bool isCall : 1;
+
         bool isLinked() { return callee; }
+        void unlink()
+        {
+            hasSeenShouldRepatch = false;
+            callee.clear();
+        }
 
         bool seenOnce()
         {
@@ -132,15 +129,13 @@ namespace JSC {
 
     struct MethodCallLinkInfo {
         MethodCallLinkInfo()
-            : cachedStructure(0)
-            , cachedPrototypeStructure(0)
         {
         }
 
         bool seenOnce()
         {
             ASSERT(!cachedStructure);
-            return cachedPrototypeStructure;
+            return cachedPrototypeStructure.isFlagged();
         }
 
         void setSeen()
@@ -152,35 +147,26 @@ namespace JSC {
             //     - Once this transition has been taken once, cachedStructure is
             //       null and cachedPrototypeStructure is set to a nun-null value.
             //     - Once the call is linked both structures are set to non-null values.
-            cachedPrototypeStructure = (Structure*)1;
+            cachedPrototypeStructure.setFlagOnBarrier();
         }
 
         CodeLocationCall callReturnLocation;
-        CodeLocationDataLabelPtr structureLabel;
-        Structure* cachedStructure;
-        Structure* cachedPrototypeStructure;
-    };
-
-    struct FunctionRegisterInfo {
-        FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex)
-            : bytecodeOffset(bytecodeOffset)
-            , functionRegisterIndex(functionRegisterIndex)
-        {
-        }
-
-        unsigned bytecodeOffset;
-        int functionRegisterIndex;
+        JITWriteBarrier<Structure> cachedStructure;
+        JITWriteBarrier<Structure> cachedPrototypeStructure;
+        // We'd like this to actually be JSFunction, but InternalFunction and JSFunction
+        // don't have a common parent class and we allow specialisation on both
+        JITWriteBarrier<JSObjectWithGlobalObject> cachedFunction;
+        JITWriteBarrier<JSObject> cachedPrototype;
     };
 
     struct GlobalResolveInfo {
         GlobalResolveInfo(unsigned bytecodeOffset)
-            : structure(0)
-            , offset(0)
+            : offset(0)
             , bytecodeOffset(bytecodeOffset)
         {
         }
 
-        Structure* structure;
+        WriteBarrier<Structure> structure;
         unsigned offset;
         unsigned bytecodeOffset;
     };
@@ -189,18 +175,18 @@ namespace JSC {
     // (given as an offset in bytes into the JIT code) back to
     // the bytecode index of the corresponding bytecode operation.
     // This is then used to look up the corresponding handler.
-    struct CallReturnOffsetToBytecodeIndex {
-        CallReturnOffsetToBytecodeIndex(unsigned callReturnOffset, unsigned bytecodeIndex)
+    struct CallReturnOffsetToBytecodeOffset {
+        CallReturnOffsetToBytecodeOffset(unsigned callReturnOffset, unsigned bytecodeOffset)
             : callReturnOffset(callReturnOffset)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
         {
         }
 
         unsigned callReturnOffset;
-        unsigned bytecodeIndex;
+        unsigned bytecodeOffset;
     };
 
-    // valueAtPosition helpers for the binaryChop algorithm below.
+    // valueAtPosition helpers for the binarySearch algorithm.
 
     inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
     {
@@ -217,71 +203,25 @@ namespace JSC {
         return methodCallLinkInfo->callReturnLocation.executableAddress();
     }
 
-    inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex* pc)
+    inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeOffset* pc)
     {
         return pc->callReturnOffset;
     }
-
-    // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
-    // compares result with key (KeyTypes should be comparable with '--', '<', '>').
-    // Optimized for cases where the array contains the key, checked by assertions.
-    template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
-    inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
-    {
-        // The array must contain at least one element (pre-condition, array does conatin key).
-        // If the array only contains one element, no need to do the comparison.
-        while (size > 1) {
-            // Pick an element to check, half way through the array, and read the value.
-            int pos = (size - 1) >> 1;
-            KeyType val = valueAtPosition(&array[pos]);
-            
-            // If the key matches, success!
-            if (val == key)
-                return &array[pos];
-            // The item we are looking for is smaller than the item being check; reduce the value of 'size',
-            // chopping off the right hand half of the array.
-            else if (key < val)
-                size = pos;
-            // Discard all values in the left hand half of the array, up to and including the item at pos.
-            else {
-                size -= (pos + 1);
-                array += (pos + 1);
-            }
-
-            // 'size' should never reach zero.
-            ASSERT(size);
-        }
-        
-        // If we reach this point we've chopped down to one element, no need to check it matches
-        ASSERT(size == 1);
-        ASSERT(key == valueAtPosition(&array[0]));
-        return &array[0];
-    }
-#endif
-
-    struct ExceptionInfo : FastAllocBase {
-        Vector<ExpressionRangeInfo> m_expressionInfo;
-        Vector<LineInfo> m_lineInfo;
-        Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
-
-#if ENABLE(JIT)
-        Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector;
 #endif
-    };
 
-    class CodeBlock : public FastAllocBase {
+    class CodeBlock {
+        WTF_MAKE_FAST_ALLOCATED;
         friend class JIT;
     protected:
-        CodeBlock(ScriptExecutable* ownerExecutable, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable);
+        CodeBlock(ScriptExecutable* ownerExecutable, CodeType, JSGlobalObject*, PassRefPtr<SourceProvider>, unsigned sourceOffset, SymbolTable* symbolTable, bool isConstructor);
+
+        WriteBarrier<JSGlobalObject> m_globalObject;
+        Heap* m_heap;
+
     public:
         virtual ~CodeBlock();
 
-        void markAggregate(MarkStack&);
-        void refStructures(Instruction* vPC) const;
-        void derefStructures(Instruction* vPC) const;
-#if ENABLE(JIT_OPTIMIZE_CALL)
-        void unlinkCallers();
-#endif
+        void visitAggregate(SlotVisitor&);
 
         static void dumpStatistics();
 
@@ -291,9 +231,11 @@ namespace JSC {
         void printStructure(const char* name, const Instruction*, int operand) const;
 #endif
 
+        bool isStrictMode() const { return m_isStrictMode; }
+
         inline bool isKnownNotImmediate(int index)
         {
-            if (index == m_thisRegister)
+            if (index == m_thisRegister && !m_isStrictMode)
                 return true;
 
             if (isConstantRegisterIndex(index))
@@ -308,55 +250,41 @@ namespace JSC {
         }
 
         HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
-        int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset);
-        int expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
-        bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&);
+        int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
+        void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
 
 #if ENABLE(JIT)
-        void addCaller(CallLinkInfo* caller)
-        {
-            caller->callee = this;
-            caller->position = m_linkedCallerList.size();
-            m_linkedCallerList.append(caller);
-        }
-
-        void removeCaller(CallLinkInfo* caller)
-        {
-            unsigned pos = caller->position;
-            unsigned lastPos = m_linkedCallerList.size() - 1;
-
-            if (pos != lastPos) {
-                m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
-                m_linkedCallerList[pos]->position = pos;
-            }
-            m_linkedCallerList.shrink(lastPos);
-        }
 
         StructureStubInfo& getStubInfo(ReturnAddressPtr returnAddress)
         {
-            return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value()));
+            return *(binarySearch<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value()));
         }
 
         CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
         {
-            return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value()));
+            return *(binarySearch<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value()));
         }
 
         MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress)
         {
-            return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value()));
+            return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value()));
         }
 
-        unsigned getBytecodeIndex(CallFrame* callFrame, ReturnAddressPtr returnAddress)
+        unsigned bytecodeOffset(ReturnAddressPtr returnAddress)
         {
-            reparseForExceptionInfoIfNecessary(callFrame);
-            return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), ownerExecutable()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex;
+            if (!m_rareData)
+                return 1;
+            Vector<CallReturnOffsetToBytecodeOffset>& callIndices = m_rareData->m_callReturnIndexVector;
+            if (!callIndices.size())
+                return 1;
+            return binarySearch<CallReturnOffsetToBytecodeOffset, unsigned, getCallReturnOffset>(callIndices.begin(), callIndices.size(), getJITCode().offsetOf(returnAddress.value()))->bytecodeOffset;
         }
-        
-        bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
+
+        void unlinkCalls();
 #endif
+
 #if ENABLE(INTERPRETER)
-        unsigned bytecodeOffset(CallFrame*, Instruction* returnAddress)
+        unsigned bytecodeOffset(Instruction* returnAddress)
         {
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
@@ -374,11 +302,11 @@ namespace JSC {
 #endif
 
 #if ENABLE(JIT)
-        JITCode& getJITCode() { return ownerExecutable()->generatedJITCode(); }
-        ExecutablePool* executablePool() { return ownerExecutable()->getExecutablePool(); }
+        JITCode& getJITCode() { return m_isConstructor ? ownerExecutable()->generatedJITCodeForConstruct() : ownerExecutable()->generatedJITCodeForCall(); }
+        ExecutablePool* executablePool() { return getJITCode().getExecutablePool(); }
 #endif
 
-        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable; }
+        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
 
@@ -389,8 +317,28 @@ namespace JSC {
         bool needsFullScopeChain() const { return m_needsFullScopeChain; }
         void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
         bool usesEval() const { return m_usesEval; }
-        void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }
-        bool usesArguments() const { return m_usesArguments; }
+        
+        void setArgumentsRegister(int argumentsRegister)
+        {
+            ASSERT(argumentsRegister != -1);
+            m_argumentsRegister = argumentsRegister;
+            ASSERT(usesArguments());
+        }
+        int argumentsRegister()
+        {
+            ASSERT(usesArguments());
+            return m_argumentsRegister;
+        }
+        void setActivationRegister(int activationRegister)
+        {
+            m_activationRegister = activationRegister;
+        }
+        int activationRegister()
+        {
+            ASSERT(needsFullScopeChain());
+            return m_activationRegister;
+        }
+        bool usesArguments() const { return m_argumentsRegister != -1; }
 
         CodeType codeType() const { return m_codeType; }
 
@@ -402,17 +350,37 @@ namespace JSC {
         unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
         unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
 
+        void createActivation(CallFrame*);
+
+        void clearEvalCache();
+
 #if ENABLE(INTERPRETER)
-        void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
-        void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
+        void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
+        {
+            if (!m_globalData->canUseJIT())
+                m_propertyAccessInstructions.append(propertyAccessInstruction);
+        }
+        void addGlobalResolveInstruction(unsigned globalResolveInstruction)
+        {
+            if (!m_globalData->canUseJIT())
+                m_globalResolveInstructions.append(globalResolveInstruction);
+        }
         bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
 #endif
 #if ENABLE(JIT)
         size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
-        void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
+        void addStructureStubInfo(const StructureStubInfo& stubInfo)
+        {
+            if (m_globalData->canUseJIT())
+                m_structureStubInfos.append(stubInfo);
+        }
         StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
 
-        void addGlobalResolveInfo(unsigned globalResolveInstruction) { m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); }
+        void addGlobalResolveInfo(unsigned globalResolveInstruction)
+        {
+            if (m_globalData->canUseJIT())
+                m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction));
+        }
         GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
         bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
 
@@ -420,11 +388,17 @@ namespace JSC {
         void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
         CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
 
-        void addMethodCallLinkInfos(unsigned n) { m_methodCallLinkInfos.grow(n); }
+        void addMethodCallLinkInfos(unsigned n) { ASSERT(m_globalData->canUseJIT()); m_methodCallLinkInfos.grow(n); }
         MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
-
-        void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
 #endif
+        unsigned globalResolveInfoCount() const
+        {
+#if ENABLE(JIT)    
+            if (m_globalData->canUseJIT())
+                return m_globalResolveInfos.size();
+#endif
+            return 0;
+        }
 
         // Exception handling support
 
@@ -432,19 +406,38 @@ namespace JSC {
         void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
         HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
 
-        bool hasExceptionInfo() const { return m_exceptionInfo; }
-        void clearExceptionInfo() { m_exceptionInfo.clear(); }
-        ExceptionInfo* extractExceptionInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo.release(); }
+        void addExpressionInfo(const ExpressionRangeInfo& expressionInfo)
+        {
+            createRareDataIfNecessary();
+            m_rareData->m_expressionInfo.append(expressionInfo);
+        }
 
-        void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
-        void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
+        void addLineInfo(unsigned bytecodeOffset, int lineNo)
+        {
+            createRareDataIfNecessary();
+            Vector<LineInfo>& lineInfo = m_rareData->m_lineInfo;
+            if (!lineInfo.size() || lineInfo.last().lineNumber != lineNo) {
+                LineInfo info = { bytecodeOffset, lineNo };
+                lineInfo.append(info);
+            }
+        }
 
-        size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); }
-        void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); }
-        LineInfo& lastLineInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.last(); }
+        bool hasExpressionInfo() { return m_rareData && m_rareData->m_expressionInfo.size(); }
+        bool hasLineInfo() { return m_rareData && m_rareData->m_lineInfo.size(); }
+        //  We only generate exception handling info if the user is debugging
+        // (and may want line number info), or if the function contains exception handler.
+        bool needsCallReturnIndices()
+        {
+            return m_rareData &&
+                (m_rareData->m_expressionInfo.size() || m_rareData->m_lineInfo.size() || m_rareData->m_exceptionHandlers.size());
+        }
 
 #if ENABLE(JIT)
-        Vector<CallReturnOffsetToBytecodeIndex>& callReturnIndexVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_callReturnIndexVector; }
+        Vector<CallReturnOffsetToBytecodeOffset>& callReturnIndexVector()
+        {
+            createRareDataIfNecessary();
+            return m_rareData->m_callReturnIndexVector;
+        }
 #endif
 
         // Constant Pool
@@ -454,20 +447,57 @@ namespace JSC {
         Identifier& identifier(int index) { return m_identifiers[index]; }
 
         size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
-        void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
-        Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
+        void addConstant(JSValue v)
+        {
+            m_constantRegisters.append(WriteBarrier<Unknown>());
+            m_constantRegisters.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), v);
+        }
+        WriteBarrier<Unknown>& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
         ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
-        ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); }
+        ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
 
-        unsigned addFunctionDecl(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; }
+        unsigned addFunctionDecl(FunctionExecutable* n)
+        {
+            unsigned size = m_functionDecls.size();
+            m_functionDecls.append(WriteBarrier<FunctionExecutable>());
+            m_functionDecls.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n);
+            return size;
+        }
         FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
         int numberOfFunctionDecls() { return m_functionDecls.size(); }
-        unsigned addFunctionExpr(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; }
+        unsigned addFunctionExpr(FunctionExecutable* n)
+        {
+            unsigned size = m_functionExprs.size();
+            m_functionExprs.append(WriteBarrier<FunctionExecutable>());
+            m_functionExprs.last().set(m_globalObject->globalData(), m_ownerExecutable.get(), n);
+            return size;
+        }
         FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
 
-        unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
+        unsigned addRegExp(RegExp* r)
+        {
+            createRareDataIfNecessary();
+            unsigned size = m_rareData->m_regexps.size();
+            m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_globalData, ownerExecutable(), r));
+            return size;
+        }
         RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
 
+        unsigned addConstantBuffer(unsigned length)
+        {
+            createRareDataIfNecessary();
+            unsigned size = m_rareData->m_constantBuffers.size();
+            m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
+            return size;
+        }
+
+        JSValue* constantBuffer(unsigned index)
+        {
+            ASSERT(m_rareData);
+            return m_rareData->m_constantBuffers[index].data();
+        }
+
+        JSGlobalObject* globalObject() { return m_globalObject.get(); }
 
         // Jump Tables
 
@@ -495,7 +525,9 @@ namespace JSC {
 
         int m_numCalleeRegisters;
         int m_numVars;
+        int m_numCapturedVars;
         int m_numParameters;
+        bool m_isConstructor;
 
     private:
 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
@@ -508,16 +540,15 @@ namespace JSC {
         void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
         void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
 #endif
-
-        void reparseForExceptionInfoIfNecessary(CallFrame*);
+        void visitStructures(SlotVisitor&, Instruction* vPC) const;
 
         void createRareDataIfNecessary()
         {
             if (!m_rareData)
-                m_rareData.set(new RareData);
+                m_rareData = adoptPtr(new RareData);
         }
 
-        ScriptExecutable* m_ownerExecutable;
+        WriteBarrier<ScriptExecutable> m_ownerExecutable;
         JSGlobalData* m_globalData;
 
         Vector<Instruction> m_instructions;
@@ -526,11 +557,13 @@ namespace JSC {
 #endif
 
         int m_thisRegister;
+        int m_argumentsRegister;
+        int m_activationRegister;
 
         bool m_needsFullScopeChain;
         bool m_usesEval;
-        bool m_usesArguments;
         bool m_isNumericCompareFunction;
+        bool m_isStrictMode;
 
         CodeType m_codeType;
 
@@ -546,27 +579,30 @@ namespace JSC {
         Vector<GlobalResolveInfo> m_globalResolveInfos;
         Vector<CallLinkInfo> m_callLinkInfos;
         Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
-        Vector<CallLinkInfo*> m_linkedCallerList;
 #endif
 
         Vector<unsigned> m_jumpTargets;
 
         // Constant Pool
         Vector<Identifier> m_identifiers;
-        Vector<Register> m_constantRegisters;
-        Vector<RefPtr<FunctionExecutable> > m_functionDecls;
-        Vector<RefPtr<FunctionExecutable> > m_functionExprs;
+        COMPILE_ASSERT(sizeof(Register) == sizeof(WriteBarrier<Unknown>), Register_must_be_same_size_as_WriteBarrier_Unknown);
+        Vector<WriteBarrier<Unknown> > m_constantRegisters;
+        Vector<WriteBarrier<FunctionExecutable> > m_functionDecls;
+        Vector<WriteBarrier<FunctionExecutable> > m_functionExprs;
 
         SymbolTable* m_symbolTable;
 
-        OwnPtr<ExceptionInfo> m_exceptionInfo;
-
-        struct RareData : FastAllocBase {
+        struct RareData {
+           WTF_MAKE_FAST_ALLOCATED;
+        public:
             Vector<HandlerInfo> m_exceptionHandlers;
 
             // Rare Constants
-            Vector<RefPtr<RegExp> > m_regexps;
+            Vector<WriteBarrier<RegExp> > m_regexps;
 
+            // Buffers used for large array literals
+            Vector<Vector<JSValue> > m_constantBuffers;
+            
             // Jump Tables
             Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
             Vector<SimpleJumpTable> m_characterSwitchJumpTables;
@@ -574,10 +610,17 @@ namespace JSC {
 
             EvalCodeCache m_evalCodeCache;
 
+            // Expression info - present if debugging.
+            Vector<ExpressionRangeInfo> m_expressionInfo;
+            // Line info - present if profiling or debugging.
+            Vector<LineInfo> m_lineInfo;
 #if ENABLE(JIT)
-            Vector<FunctionRegisterInfo> m_functionRegisterInfos;
+            Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
 #endif
         };
+#if COMPILER(MSVC)
+        friend void WTF::deleteOwnedPtr<RareData>(RareData*);
+#endif
         OwnPtr<RareData> m_rareData;
     };
 
@@ -586,30 +629,19 @@ namespace JSC {
 
     class GlobalCodeBlock : public CodeBlock {
     public:
-        GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, JSGlobalObject* globalObject)
-            : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset, &m_unsharedSymbolTable)
-            , m_globalObject(globalObject)
-        {
-            m_globalObject->codeBlocks().add(this);
-        }
-
-        ~GlobalCodeBlock()
+        GlobalCodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
+            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, &m_unsharedSymbolTable, false)
         {
-            if (m_globalObject)
-                m_globalObject->codeBlocks().remove(this);
         }
 
-        void clearGlobalObject() { m_globalObject = 0; }
-
     private:
-        JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
         SymbolTable m_unsharedSymbolTable;
     };
 
     class ProgramCodeBlock : public GlobalCodeBlock {
     public:
         ProgramCodeBlock(ProgramExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
-            : GlobalCodeBlock(ownerExecutable, codeType, sourceProvider, 0, globalObject)
+            : GlobalCodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, 0)
         {
         }
     };
@@ -617,7 +649,7 @@ namespace JSC {
     class EvalCodeBlock : public GlobalCodeBlock {
     public:
         EvalCodeBlock(EvalExecutable* ownerExecutable, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
-            : GlobalCodeBlock(ownerExecutable, EvalCode, sourceProvider, 0, globalObject)
+            : GlobalCodeBlock(ownerExecutable, EvalCode, globalObject, sourceProvider, 0)
             , m_baseScopeDepth(baseScopeDepth)
         {
         }
@@ -643,8 +675,8 @@ namespace JSC {
         // as we need to initialise the CodeBlock before we could initialise any RefPtr to hold the shared
         // symbol table, so we just pass as a raw pointer with a ref count of 1.  We then manually deref
         // in the destructor.
-        FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
-            : CodeBlock(ownerExecutable, codeType, sourceProvider, sourceOffset, new SharedSymbolTable)
+        FunctionCodeBlock(FunctionExecutable* ownerExecutable, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, bool isConstructor)
+            : CodeBlock(ownerExecutable, codeType, globalObject, sourceProvider, sourceOffset, SharedSymbolTable::create().leakRef(), isConstructor)
         {
         }
         ~FunctionCodeBlock()
@@ -657,10 +689,16 @@ namespace JSC {
     {
         CodeBlock* codeBlock = this->codeBlock();
         if (codeBlock->isConstantRegisterIndex(index))
-            return codeBlock->constantRegister(index);
+            return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index));
         return this[index];
     }
 
+    inline Register& ExecState::uncheckedR(int index)
+    {
+        ASSERT(index < FirstConstantRegisterIndex);
+        return this[index];
+    }
+    
 } // namespace JSC
 
 #endif // CodeBlock_h
index 27c479d4e51c12fb3df93d671f5690a00bfaae39..1e181b9d7c359e9ef21d014c61fbea00670d1700 100644 (file)
 
 namespace JSC {
 
+    class MarkStack;
+    typedef MarkStack SlotVisitor;
+
     class EvalCodeCache {
     public:
-        PassRefPtr<EvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
+        EvalExecutable* get(ExecState* exec, ScriptExecutable* owner, bool inStrictContext, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
         {
-            RefPtr<EvalExecutable> evalExecutable;
+            EvalExecutable* evalExecutable = 0;
 
-            if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
-                evalExecutable = m_cacheMap.get(evalSource.rep());
+            if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
+                evalExecutable = m_cacheMap.get(evalSource.impl()).get();
 
             if (!evalExecutable) {
-                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource));
+                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
                 exceptionValue = evalExecutable->compile(exec, scopeChain);
                 if (exceptionValue)
                     return 0;
 
-                if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
-                    m_cacheMap.set(evalSource.rep(), evalExecutable);
+                if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
+                    m_cacheMap.set(evalSource.impl(), WriteBarrier<EvalExecutable>(exec->globalData(), owner, evalExecutable));
             }
 
-            return evalExecutable.release();
+            return evalExecutable;
         }
 
         bool isEmpty() const { return m_cacheMap.isEmpty(); }
 
+        void visitAggregate(SlotVisitor&);
+
+        void clear()
+        {
+            m_cacheMap.clear();
+        }
+
     private:
         static const unsigned maxCacheableSourceLength = 256;
         static const int maxCacheEntries = 64;
 
-        typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalExecutable> > EvalCacheMap;
+        typedef HashMap<RefPtr<StringImpl>, WriteBarrier<EvalExecutable> > EvalCacheMap;
         EvalCacheMap m_cacheMap;
     };
 
index c6468a5580423b7267466abe46f1be4d6407d328..b3bb5b711fe6a8a51ee9a4bbff2c46385964c170 100644 (file)
@@ -33,6 +33,7 @@
 #include "Opcode.h"
 #include "PropertySlot.h"
 #include "Structure.h"
+#include "StructureChain.h"
 #include <wtf/VectorTraits.h>
 
 #define POLYMORPHIC_LIST_CACHE_SIZE 8
@@ -54,70 +55,78 @@ namespace JSC {
     class StructureChain;
 
     // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream.
-    struct PolymorphicAccessStructureList : FastAllocBase {
+    struct PolymorphicAccessStructureList {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         struct PolymorphicStubInfo {
             bool isChain;
             PolymorphicAccessStructureListStubRoutineType stubRoutine;
-            Structure* base;
+            WriteBarrier<Structure> base;
             union {
-                Structure* proto;
-                StructureChain* chain;
+                WriteBarrierBase<Structure> proto;
+                WriteBarrierBase<StructureChain> chain;
             } u;
 
-            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
+            PolymorphicStubInfo()
+            {
+                u.proto.clear();
+            }
+
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
             {
                 stubRoutine = _stubRoutine;
-                base = _base;
-                u.proto = 0;
+                base.set(globalData, owner, _base);
+                u.proto.clear();
                 isChain = false;
             }
             
-            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
             {
                 stubRoutine = _stubRoutine;
-                base = _base;
-                u.proto = _proto;
+                base.set(globalData, owner, _base);
+                u.proto.set(globalData, owner, _proto);
                 isChain = false;
             }
             
-            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
             {
                 stubRoutine = _stubRoutine;
-                base = _base;
-                u.chain = _chain;
+                base.set(globalData, owner, _base);
+                u.chain.set(globalData, owner, _chain);
                 isChain = true;
             }
         } list[POLYMORPHIC_LIST_CACHE_SIZE];
         
-        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase)
         {
-            list[0].set(stubRoutine, firstBase);
+            list[0].set(globalData, owner, stubRoutine, firstBase);
         }
 
-        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
         {
-            list[0].set(stubRoutine, firstBase, firstProto);
+            list[0].set(globalData, owner, stubRoutine, firstBase, firstProto);
         }
 
-        PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
+        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
         {
-            list[0].set(stubRoutine, firstBase, firstChain);
+            list[0].set(globalData, owner, stubRoutine, firstBase, firstChain);
         }
 
-        void derefStructures(int count)
+        void visitAggregate(SlotVisitor& visitor, int count)
         {
             for (int i = 0; i < count; ++i) {
                 PolymorphicStubInfo& info = list[i];
-
-                ASSERT(info.base);
-                info.base->deref();
-
-                if (info.u.proto) {
-                    if (info.isChain)
-                        info.u.chain->deref();
-                    else
-                        info.u.proto->deref();
+                if (!info.base) {
+                    // We're being marked during initialisation of an entry
+                    ASSERT(!info.u.proto);
+                    continue;
                 }
+                
+                visitor.append(&info.base);
+                if (info.u.proto && !info.isChain)
+                    visitor.append(&info.u.proto);
+                if (info.u.chain && info.isChain)
+                    visitor.append(&info.u.chain);
             }
         }
     };
@@ -128,7 +137,7 @@ namespace JSC {
 #if !ENABLE(COMPUTED_GOTO_INTERPRETER)
             // We have to initialize one of the pointer members to ensure that
             // the entire struct is initialized, when opcode is not a pointer.
-            u.jsCell = 0;
+            u.jsCell.clear();
 #endif
             u.opcode = opcode;
         }
@@ -137,25 +146,41 @@ namespace JSC {
         {
             // We have to initialize one of the pointer members to ensure that
             // the entire struct is initialized in 64-bit.
-            u.jsCell = 0;
+            u.jsCell.clear();
             u.operand = operand;
         }
 
-        Instruction(Structure* structure) { u.structure = structure; }
-        Instruction(StructureChain* structureChain) { u.structureChain = structureChain; }
-        Instruction(JSCell* jsCell) { u.jsCell = jsCell; }
+        Instruction(JSGlobalData& globalData, JSCell* owner, Structure* structure)
+        {
+            u.structure.clear();
+            u.structure.set(globalData, owner, structure);
+        }
+        Instruction(JSGlobalData& globalData, JSCell* owner, StructureChain* structureChain)
+        {
+            u.structureChain.clear();
+            u.structureChain.set(globalData, owner, structureChain);
+        }
+        Instruction(JSGlobalData& globalData, JSCell* owner, JSCell* jsCell)
+        {
+            u.jsCell.clear();
+            u.jsCell.set(globalData, owner, jsCell);
+        }
         Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; }
         Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
 
         union {
             Opcode opcode;
             int operand;
-            Structure* structure;
-            StructureChain* structureChain;
-            JSCell* jsCell;
+            WriteBarrierBase<Structure> structure;
+            WriteBarrierBase<StructureChain> structureChain;
+            WriteBarrierBase<JSCell> jsCell;
             PolymorphicAccessStructureList* polymorphicStructures;
             PropertySlot::GetValueFunc getterFunc;
         } u;
+        
+    private:
+        Instruction(StructureChain*);
+        Instruction(Structure*);
     };
 
 } // namespace JSC
index b4f8e4401cb14af529e5eedcd87fdd2e060ed69b..5bbe047107f5b01c0289bea33186e1f84a3aafc7 100644 (file)
@@ -45,13 +45,13 @@ namespace JSC {
     };
 
     struct StringJumpTable {
-        typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
+        typedef HashMap<RefPtr<StringImpl>, OffsetLocation> StringOffsetTable;
         StringOffsetTable offsetTable;
 #if ENABLE(JIT)
         CodeLocationLabel ctiDefault; // FIXME: it should not be necessary to store this.
 #endif
 
-        inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
+        inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
         {
             StringOffsetTable::const_iterator end = offsetTable.end();
             StringOffsetTable::const_iterator loc = offsetTable.find(value);
@@ -61,7 +61,7 @@ namespace JSC {
         }
 
 #if ENABLE(JIT)
-        inline CodeLocationLabel ctiForValue(UString::Rep* value)
+        inline CodeLocationLabel ctiForValue(StringImpl* value)
         {
             StringOffsetTable::const_iterator end = offsetTable.end();
             StringOffsetTable::const_iterator loc = offsetTable.find(value);
index bb7696dd8d6df5e84815c41184bddb9d485ff13d..0bb714bca2d14ed884574fb73c9cac8947faca4f 100644 (file)
 #include "config.h"
 #include "Opcode.h"
 
+#if ENABLE(OPCODE_STATS)
+#include <stdio.h>
+#include <wtf/FixedArray.h>
+#endif
+
 using namespace std;
 
 namespace JSC {
@@ -101,10 +106,10 @@ OpcodeStats::~OpcodeStats()
         for (int j = 0; j < numOpcodeIDs; ++j)
             totalInstructionPairs += opcodePairCounts[i][j];
 
-    int sortedIndices[numOpcodeIDs];    
+    FixedArray<int, numOpcodeIDs> sortedIndices;
     for (int i = 0; i < numOpcodeIDs; ++i)
         sortedIndices[i] = i;
-    qsort(sortedIndices, numOpcodeIDs, sizeof(int), compareOpcodeIndices);
+    qsort(sortedIndices.data(), numOpcodeIDs, sizeof(int), compareOpcodeIndices);
     
     pair<int, int> sortedPairIndices[numOpcodeIDs * numOpcodeIDs];
     pair<int, int>* currentPairIndex = sortedPairIndices;
index 67f5e70790bbe1daa02bdd7b84c56a4bc97a8b84..18902eb2690a3ee406d683b68045129d6895a9f6 100644 (file)
@@ -39,13 +39,17 @@ namespace JSC {
 
     #define FOR_EACH_OPCODE_ID(macro) \
         macro(op_enter, 1) \
-        macro(op_enter_with_activation, 2) \
-        macro(op_init_arguments, 1) \
-        macro(op_create_arguments, 1) \
+        macro(op_create_activation, 2) \
+        macro(op_init_lazy_reg, 2) \
+        macro(op_create_arguments, 2) \
+        macro(op_create_this, 3) \
+        macro(op_get_callee, 2) \
         macro(op_convert_this, 2) \
+        macro(op_convert_this_strict, 2) \
         \
         macro(op_new_object, 2) \
         macro(op_new_array, 4) \
+        macro(op_new_array_buffer, 4) \
         macro(op_new_regexp, 3) \
         macro(op_mov, 3) \
         \
@@ -79,6 +83,7 @@ namespace JSC {
         macro(op_bitor, 5) \
         macro(op_bitnot, 3) \
         \
+        macro(op_check_has_instance, 2) \
         macro(op_instanceof, 5) \
         macro(op_typeof, 3) \
         macro(op_is_undefined, 3) \
@@ -91,13 +96,14 @@ namespace JSC {
         \
         macro(op_resolve, 3) \
         macro(op_resolve_skip, 4) \
-        macro(op_resolve_global, 6) \
-        macro(op_resolve_global_dynamic, 7) \
+        macro(op_resolve_global, 5) \
+        macro(op_resolve_global_dynamic, 6) \
         macro(op_get_scoped_var, 4) \
         macro(op_put_scoped_var, 4) \
-        macro(op_get_global_var, 4) \
-        macro(op_put_global_var, 4) \
-        macro(op_resolve_base, 3) \
+        macro(op_get_global_var, 3) \
+        macro(op_put_global_var, 3) \
+        macro(op_resolve_base, 4) \
+        macro(op_ensure_property_exists, 3) \
         macro(op_resolve_with_base, 4) \
         macro(op_get_by_id, 8) \
         macro(op_get_by_id_self, 8) \
@@ -118,12 +124,14 @@ namespace JSC {
         macro(op_get_by_id_generic, 8) \
         macro(op_get_array_length, 8) \
         macro(op_get_string_length, 8) \
+        macro(op_get_arguments_length, 4) \
         macro(op_put_by_id, 9) \
         macro(op_put_by_id_transition, 9) \
         macro(op_put_by_id_replace, 9) \
         macro(op_put_by_id_generic, 9) \
         macro(op_del_by_id, 4) \
         macro(op_get_by_val, 4) \
+        macro(op_get_argument_by_val, 4) \
         macro(op_get_by_pname, 7) \
         macro(op_put_by_val, 4) \
         macro(op_del_by_val, 4) \
@@ -151,19 +159,20 @@ namespace JSC {
         macro(op_switch_char, 4) \
         macro(op_switch_string, 4) \
         \
-        macro(op_new_func, 3) \
+        macro(op_new_func, 4) \
         macro(op_new_func_exp, 3) \
-        macro(op_call, 5) \
-        macro(op_call_eval, 5) \
-        macro(op_call_varargs, 5) \
-        macro(op_load_varargs, 3) \
-        macro(op_tear_off_activation, 2) \
-        macro(op_tear_off_arguments, 1) \
+        macro(op_call, 4) \
+        macro(op_call_eval, 4) \
+        macro(op_call_varargs, 4) \
+        macro(op_load_varargs, 4) \
+        macro(op_tear_off_activation, 3) \
+        macro(op_tear_off_arguments, 2) \
         macro(op_ret, 2) \
+        macro(op_call_put_result, 2) \
+        macro(op_ret_object_or_this, 3) \
         macro(op_method_check, 1) \
         \
-        macro(op_construct, 7) \
-        macro(op_construct_verify, 3) \
+        macro(op_construct, 4) \
         macro(op_strcat, 4) \
         macro(op_to_primitive, 3) \
         \
@@ -176,7 +185,7 @@ namespace JSC {
         \
         macro(op_catch, 2) \
         macro(op_throw, 2) \
-        macro(op_new_error, 4) \
+        macro(op_throw_reference_error, 2) \
         \
         macro(op_jsr, 3) \
         macro(op_sret, 2) \
@@ -208,7 +217,7 @@ namespace JSC {
     #undef VERIFY_OPCODE_ID
 
 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
-#if COMPILER(RVCT)
+#if COMPILER(RVCT) || COMPILER(INTEL)
     typedef void* Opcode;
 #else
     typedef const void* Opcode;
@@ -251,6 +260,17 @@ namespace JSC {
 
 #endif
 
+    inline size_t opcodeLength(OpcodeID opcode)
+    {
+        switch (opcode) {
+#define OPCODE_ID_LENGTHS(id, length) case id: return OPCODE_LENGTH(id);
+             FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS)
+#undef OPCODE_ID_LENGTHS
+        }
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
 } // namespace JSC
 
 #endif // Opcode_h
index 7191e388ee61ee9f427ae8d4ba20e2730ef10f56..f47e6982517c3f7df7f2b3208a9404874cbb4209 100644 (file)
@@ -337,7 +337,7 @@ void SamplingTool::dump(ExecState* exec)
 
         if (blockPercent >= 1) {
             //Instruction* code = codeBlock->instructions().begin();
-            printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_executable->sourceURL().ascii(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent);
+            printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_executable->sourceURL().utf8().data(), codeBlock->lineNumberForBytecodeOffset(0), record->m_sampleCount, m_sampleCount, blockPercent);
             if (i < 10) {
                 HashMap<unsigned,unsigned> lineCounts;
                 codeBlock->dump(exec);
@@ -347,7 +347,7 @@ void SamplingTool::dump(ExecState* exec)
                     int count = record->m_samples[op];
                     if (count) {
                         printf("    [% 4d] has sample count: % 4d\n", op, count);
-                        unsigned line = codeBlock->lineNumberForBytecodeOffset(exec, op);
+                        unsigned line = codeBlock->lineNumberForBytecodeOffset(op);
                         lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count);
                     }
                 }
index 8e3ed9e5e0e762bf4e0d65a6aa92f34ec950f2b5..1d77b31d76e7af32b4a4f102257f66e0b95e1a61 100644 (file)
 #ifndef SamplingTool_h
 #define SamplingTool_h
 
+#include "Strong.h"
+#include "Nodes.h"
+#include "Opcode.h"
 #include <wtf/Assertions.h>
 #include <wtf/HashMap.h>
 #include <wtf/Threading.h>
 
-#include "Nodes.h"
-#include "Opcode.h"
-
 namespace JSC {
 
     class ScriptExecutable;
 
     class SamplingFlags {
-        friend class JIT;
     public:
         static void start();
         static void stop();
@@ -80,6 +79,11 @@ namespace JSC {
             int m_flag;
         };
     
+        static const void* addressOfFlags()
+        {
+            return &s_flags;
+        }
+
 #endif
     private:
         static uint32_t s_flags;
@@ -95,8 +99,8 @@ namespace JSC {
     struct Instruction;
 
     struct ScriptSampleRecord {
-        ScriptSampleRecord(ScriptExecutable* executable)
-            : m_executable(executable)
+        ScriptSampleRecord(JSGlobalData& globalData, ScriptExecutable* executable)
+            : m_executable(globalData, executable)
             , m_codeBlock(0)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
@@ -113,7 +117,7 @@ namespace JSC {
         
         void sample(CodeBlock*, Instruction*);
 
-        RefPtr<ScriptExecutable> m_executable;
+        Strong<ScriptExecutable> m_executable;
         CodeBlock* m_codeBlock;
         int m_sampleCount;
         int m_opcodeSampleCount;
@@ -142,7 +146,8 @@ namespace JSC {
         friend class HostCallRecord;
         
 #if ENABLE(OPCODE_SAMPLING)
-        class CallRecord : public Noncopyable {
+        class CallRecord {
+            WTF_MAKE_NONCOPYABLE(CallRecord);
         public:
             CallRecord(SamplingTool* samplingTool)
                 : m_samplingTool(samplingTool)
@@ -172,7 +177,8 @@ namespace JSC {
             }
         };
 #else
-        class CallRecord : public Noncopyable {
+        class CallRecord {
+            WTF_MAKE_NONCOPYABLE(CallRecord);
         public:
             CallRecord(SamplingTool*)
             {
@@ -278,7 +284,6 @@ namespace JSC {
     // Implements a named set of counters, printed on exit if ENABLE(SAMPLING_COUNTERS).
     // See subclasses below, SamplingCounter, GlobalSamplingCounter and DeletableSamplingCounter.
     class AbstractSamplingCounter {
-        friend class JIT;
         friend class DeletableSamplingCounter;
     public:
         void count(uint32_t count = 1)
@@ -288,6 +293,8 @@ namespace JSC {
 
         static void dump();
 
+        int64_t* addressOfCounter() { return &m_counter; }
+
     protected:
         // Effectively the contructor, however called lazily in the case of GlobalSamplingCounter.
         void init(const char* name)
index 018d83289bf087cff99d08c23f66ff3952842895..9dd41a6e32f7bda7831d47f1170b01cc98225c23 100644 (file)
 #include "config.h"
 #include "StructureStubInfo.h"
 
+#include "JSObject.h"
+#include "ScopeChain.h"
+
 namespace JSC {
 
 #if ENABLE(JIT)
 void StructureStubInfo::deref()
+{
+    switch (accessType) {
+    case access_get_by_id_self_list: {
+        PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
+        delete polymorphicStructures;
+        return;
+    }
+    case access_get_by_id_proto_list: {
+        PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
+        delete polymorphicStructures;
+        return;
+    }
+    case access_get_by_id_self:
+    case access_get_by_id_proto:
+    case access_get_by_id_chain:
+    case access_put_by_id_transition:
+    case access_put_by_id_replace:
+    case access_get_by_id:
+    case access_put_by_id:
+    case access_get_by_id_generic:
+    case access_put_by_id_generic:
+    case access_get_array_length:
+    case access_get_string_length:
+        // These instructions don't have to release any allocated memory
+        return;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+}
+
+void StructureStubInfo::visitAggregate(SlotVisitor& visitor)
 {
     switch (accessType) {
     case access_get_by_id_self:
-        u.getByIdSelf.baseObjectStructure->deref();
+        visitor.append(&u.getByIdSelf.baseObjectStructure);
         return;
     case access_get_by_id_proto:
-        u.getByIdProto.baseObjectStructure->deref();
-        u.getByIdProto.prototypeStructure->deref();
+        visitor.append(&u.getByIdProto.baseObjectStructure);
+        visitor.append(&u.getByIdProto.prototypeStructure);
         return;
     case access_get_by_id_chain:
-        u.getByIdChain.baseObjectStructure->deref();
-        u.getByIdChain.chain->deref();
+        visitor.append(&u.getByIdChain.baseObjectStructure);
+        visitor.append(&u.getByIdChain.chain);
         return;
     case access_get_by_id_self_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
-        polymorphicStructures->derefStructures(u.getByIdSelfList.listSize);
-        delete polymorphicStructures;
+        polymorphicStructures->visitAggregate(visitor, u.getByIdSelfList.listSize);
         return;
     }
     case access_get_by_id_proto_list: {
         PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
-        polymorphicStructures->derefStructures(u.getByIdProtoList.listSize);
-        delete polymorphicStructures;
+        polymorphicStructures->visitAggregate(visitor, u.getByIdProtoList.listSize);
         return;
     }
     case access_put_by_id_transition:
-        u.putByIdTransition.previousStructure->deref();
-        u.putByIdTransition.structure->deref();
-        u.putByIdTransition.chain->deref();
+        visitor.append(&u.putByIdTransition.previousStructure);
+        visitor.append(&u.putByIdTransition.structure);
+        visitor.append(&u.putByIdTransition.chain);
         return;
     case access_put_by_id_replace:
-        u.putByIdReplace.baseObjectStructure->deref();
+        visitor.append(&u.putByIdReplace.baseObjectStructure);
         return;
     case access_get_by_id:
     case access_put_by_id:
@@ -69,7 +101,7 @@ void StructureStubInfo::deref()
     case access_put_by_id_generic:
     case access_get_array_length:
     case access_get_string_length:
-        // These instructions don't ref their Structures.
+        // These instructions don't need to mark anything
         return;
     default:
         ASSERT_NOT_REACHED();
index 8e2c489aa93023139b9af96dae8e565decf224fe..7f11edd769691518876cd10f5f2855e8423f68cd 100644 (file)
@@ -58,34 +58,27 @@ namespace JSC {
         {
         }
 
-        void initGetByIdSelf(Structure* baseObjectStructure)
+        void initGetByIdSelf(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure)
         {
             accessType = access_get_by_id_self;
 
-            u.getByIdSelf.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
+            u.getByIdSelf.baseObjectStructure.set(globalData, owner, baseObjectStructure);
         }
 
-        void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure)
+        void initGetByIdProto(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, Structure* prototypeStructure)
         {
             accessType = access_get_by_id_proto;
 
-            u.getByIdProto.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
-
-            u.getByIdProto.prototypeStructure = prototypeStructure;
-            prototypeStructure->ref();
+            u.getByIdProto.baseObjectStructure.set(globalData, owner, baseObjectStructure);
+            u.getByIdProto.prototypeStructure.set(globalData, owner, prototypeStructure);
         }
 
-        void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain)
+        void initGetByIdChain(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure, StructureChain* chain)
         {
             accessType = access_get_by_id_chain;
 
-            u.getByIdChain.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
-
-            u.getByIdChain.chain = chain;
-            chain->ref();
+            u.getByIdChain.baseObjectStructure.set(globalData, owner, baseObjectStructure);
+            u.getByIdChain.chain.set(globalData, owner, chain);
         }
 
         void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
@@ -106,29 +99,24 @@ namespace JSC {
 
         // PutById*
 
-        void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain)
+        void initPutByIdTransition(JSGlobalData& globalData, JSCell* owner, Structure* previousStructure, Structure* structure, StructureChain* chain)
         {
             accessType = access_put_by_id_transition;
 
-            u.putByIdTransition.previousStructure = previousStructure;
-            previousStructure->ref();
-
-            u.putByIdTransition.structure = structure;
-            structure->ref();
-
-            u.putByIdTransition.chain = chain;
-            chain->ref();
+            u.putByIdTransition.previousStructure.set(globalData, owner, previousStructure);
+            u.putByIdTransition.structure.set(globalData, owner, structure);
+            u.putByIdTransition.chain.set(globalData, owner, chain);
         }
 
-        void initPutByIdReplace(Structure* baseObjectStructure)
+        void initPutByIdReplace(JSGlobalData& globalData, JSCell* owner, Structure* baseObjectStructure)
         {
             accessType = access_put_by_id_replace;
     
-            u.putByIdReplace.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
+            u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure);
         }
 
         void deref();
+        void visitAggregate(SlotVisitor&);
 
         bool seenOnce()
         {
@@ -145,15 +133,15 @@ namespace JSC {
 
         union {
             struct {
-                Structure* baseObjectStructure;
+                WriteBarrierBase<Structure> baseObjectStructure;
             } getByIdSelf;
             struct {
-                Structure* baseObjectStructure;
-                Structure* prototypeStructure;
+                WriteBarrierBase<Structure> baseObjectStructure;
+                WriteBarrierBase<Structure> prototypeStructure;
             } getByIdProto;
             struct {
-                Structure* baseObjectStructure;
-                StructureChain* chain;
+                WriteBarrierBase<Structure> baseObjectStructure;
+                WriteBarrierBase<StructureChain> chain;
             } getByIdChain;
             struct {
                 PolymorphicAccessStructureList* structureList;
@@ -164,12 +152,12 @@ namespace JSC {
                 int listSize;
             } getByIdProtoList;
             struct {
-                Structure* previousStructure;
-                Structure* structure;
-                StructureChain* chain;
+                WriteBarrierBase<Structure> previousStructure;
+                WriteBarrierBase<Structure> structure;
+                WriteBarrierBase<StructureChain> chain;
             } putByIdTransition;
             struct {
-                Structure* baseObjectStructure;
+                WriteBarrierBase<Structure> baseObjectStructure;
             } putByIdReplace;
         } u;
 
index c4b3cab912b1b69897d4c886c45863048c50d999..c09a83766d6a9b406fb8aa6ee3491b9555e5aaaa 100644 (file)
@@ -31,9 +31,9 @@
 #include "BytecodeGenerator.h"
 
 #include "BatchedTransitionOptimizer.h"
-#include "PrototypeFunction.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
+#include "ScopeChain.h"
 #include "UString.h"
 
 using namespace std;
@@ -137,7 +137,7 @@ bool BytecodeGenerator::dumpsGeneratedCode()
 #endif
 }
 
-void BytecodeGenerator::generate()
+JSObject* BytecodeGenerator::generate()
 {
     m_codeBlock->setThisRegister(m_thisRegister.index());
 
@@ -147,35 +147,31 @@ void BytecodeGenerator::generate()
     m_codeBlock->setInstructionCount(m_codeBlock->instructions().size());
 
     if (s_dumpsGeneratedCode)
-        m_codeBlock->dump(m_scopeChain->globalObject()->globalExec());
+        m_codeBlock->dump(m_scopeChain->globalObject->globalExec());
 #endif
 
     if ((m_codeType == FunctionCode && !m_codeBlock->needsFullScopeChain() && !m_codeBlock->usesArguments()) || m_codeType == EvalCode)
         symbolTable().clear();
-        
-    m_codeBlock->setIsNumericCompareFunction(instructions() == m_globalData->numericCompareFunction(m_scopeChain->globalObject()->globalExec()));
-
-#if !ENABLE(OPCODE_SAMPLING)
-    if (!m_regeneratingForExceptionInfo && (m_codeType == FunctionCode || m_codeType == EvalCode))
-        m_codeBlock->clearExceptionInfo();
-#endif
 
     m_codeBlock->shrinkToFit();
+
+    if (m_expressionTooDeep)
+        return createOutOfMemoryError(m_scopeChain->globalObject.get());
+    return 0;
 }
 
 bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, RegisterID*& r0)
 {
     int index = m_calleeRegisters.size();
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
-    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
+    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry);
 
     if (!result.second) {
         r0 = &registerFor(result.first->second.getIndex());
         return false;
     }
 
-    ++m_codeBlock->m_numVars;
-    r0 = newRegister();
+    r0 = addVar();
     return true;
 }
 
@@ -183,7 +179,7 @@ bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, R
 {
     int index = m_nextGlobalIndex;
     SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0);
-    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.ustring().rep(), newEntry);
+    pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry);
 
     if (!result.second)
         index = result.first->second.getIndex();
@@ -202,10 +198,11 @@ void BytecodeGenerator::preserveLastVar()
         m_lastVar = &m_calleeRegisters.last();
 }
 
-BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
-    : m_shouldEmitDebugHooks(!!debugger)
-    , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
-    , m_scopeChain(&scopeChain)
+BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
+    : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
+    , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
+    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
+    , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(programNode)
     , m_codeBlock(codeBlock)
@@ -217,11 +214,17 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
     , m_nextGlobalIndex(-1)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
-    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
+    , m_hasCreatedActivation(true)
+    , m_firstLazyFunction(0)
+    , m_lastLazyFunction(0)
+    , m_globalData(scopeChain->globalData)
     , m_lastOpcodeID(op_end)
-    , m_emitNodeDepth(0)
-    , m_regeneratingForExceptionInfo(false)
-    , m_codeBlockBeingRegeneratedFrom(0)
+#ifndef NDEBUG
+    , m_lastOpcodePosition(0)
+#endif
+    , m_stack(m_globalData->stack())
+    , m_usesExceptions(false)
+    , m_expressionTooDeep(false)
 {
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
@@ -233,7 +236,7 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
     
     m_codeBlock->m_numParameters = 1; // Allocate space for "this"
 
-    JSGlobalObject* globalObject = scopeChain.globalObject();
+    JSGlobalObject* globalObject = scopeChain->globalObject.get();
     ExecState* exec = globalObject->globalExec();
     RegisterFile* registerFile = &exec->globalData().interpreter->registerFile();
     
@@ -245,8 +248,8 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
     SymbolTable::iterator end = symbolTable->end();
     for (SymbolTable::iterator it = symbolTable->begin(); it != end; ++it)
         registerFor(it->second.getIndex()).setIndex(it->second.getIndex() + m_globalVarStorageOffset);
-        
-    BatchedTransitionOptimizer optimizer(globalObject);
+
+    BatchedTransitionOptimizer optimizer(*m_globalData, globalObject);
 
     const VarStack& varStack = programNode->varStack();
     const FunctionStack& functionStack = programNode->functionStack();
@@ -255,28 +258,56 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
         // Shift new symbols so they get stored prior to existing symbols.
         m_nextGlobalIndex -= symbolTable->size();
 
+        HashSet<StringImpl*, IdentifierRepHash> newGlobals;
+        Vector<std::pair<int, bool>, 16> functionInfo(functionStack.size());
+        for (size_t i = 0; i < functionStack.size(); ++i) {
+            FunctionBodyNode* function = functionStack[i];
+            globalObject->removeDirect(*m_globalData, function->ident()); // Make sure our new function is not shadowed by an old property.
+            SymbolTableEntry entry = symbolTable->inlineGet(function->ident().impl());
+            
+            if (entry.isNull())
+                newGlobals.add(function->ident().impl());
+            functionInfo[i] = make_pair(entry.getIndex(), entry.isReadOnly());
+        }
+        
+        Vector<bool, 16> shouldCreateVar(varStack.size());
+        for (size_t i = 0; i < varStack.size(); ++i) {
+            if (newGlobals.contains(varStack[i].first->impl()) || globalObject->hasProperty(exec, *varStack[i].first)) {
+                shouldCreateVar[i] = false;
+                continue;
+            }
+            shouldCreateVar[i] = true;
+            newGlobals.add(varStack[i].first->impl());
+        }
+
+        int expectedSize = symbolTable->size() + newGlobals.size();
+        globalObject->resizeRegisters(symbolTable->size(), expectedSize);
+    
         for (size_t i = 0; i < functionStack.size(); ++i) {
             FunctionBodyNode* function = functionStack[i];
-            globalObject->removeDirect(function->ident()); // Make sure our new function is not shadowed by an old property.
-            emitNewFunction(addGlobalVar(function->ident(), false), function);
+            if (functionInfo[i].second)
+                continue;
+            RegisterID* dst = addGlobalVar(function->ident(), false);
+            JSValue value = new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain);
+            globalObject->registerAt(dst->index() - m_globalVarStorageOffset).set(*m_globalData, globalObject, value);
         }
 
-        Vector<RegisterID*, 32> newVars;
-        for (size_t i = 0; i < varStack.size(); ++i)
-            if (!globalObject->hasProperty(exec, *varStack[i].first))
-                newVars.append(addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
+        for (size_t i = 0; i < varStack.size(); ++i) {
+            if (!shouldCreateVar[i])
+                continue;
+            addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+        }
+        if (symbolTable->size() != expectedSize)
+            CRASH();
 
         preserveLastVar();
-
-        for (size_t i = 0; i < newVars.size(); ++i)
-            emitLoad(newVars[i], jsUndefined());
     } else {
         for (size_t i = 0; i < functionStack.size(); ++i) {
             FunctionBodyNode* function = functionStack[i];
-            globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain.node()), DontDelete);
+            globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain), DontDelete);
         }
         for (size_t i = 0; i < varStack.size(); ++i) {
-            if (globalObject->hasProperty(exec, *varStack[i].first))
+            if (globalObject->symbolTableHasProperty(*varStack[i].first) || globalObject->hasProperty(exec, *varStack[i].first))
                 continue;
             int attributes = DontDelete;
             if (varStack[i].second & DeclarationStacks::IsConstant)
@@ -286,94 +317,178 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
 
         preserveLastVar();
     }
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
 }
 
-BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
-    : m_shouldEmitDebugHooks(!!debugger)
-    , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
-    , m_scopeChain(&scopeChain)
+BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, ScopeChainNode* scopeChain, SymbolTable* symbolTable, CodeBlock* codeBlock)
+    : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
+    , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
+    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
+    , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(functionBody)
     , m_codeBlock(codeBlock)
+    , m_activationRegister(0)
     , m_finallyDepth(0)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(0)
     , m_codeType(FunctionCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
-    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
+    , m_hasCreatedActivation(false)
+    , m_firstLazyFunction(0)
+    , m_lastLazyFunction(0)
+    , m_globalData(scopeChain->globalData)
     , m_lastOpcodeID(op_end)
-    , m_emitNodeDepth(0)
-    , m_regeneratingForExceptionInfo(false)
-    , m_codeBlockBeingRegeneratedFrom(0)
+#ifndef NDEBUG
+    , m_lastOpcodePosition(0)
+#endif
+    , m_stack(m_globalData->stack())
+    , m_usesExceptions(false)
+    , m_expressionTooDeep(false)
 {
     if (m_shouldEmitDebugHooks)
         m_codeBlock->setNeedsFullScopeChain(true);
 
     codeBlock->setGlobalData(m_globalData);
-
-    bool usesArguments = functionBody->usesArguments();
-    codeBlock->setUsesArguments(usesArguments);
-    if (usesArguments) {
-        m_argumentsRegister.setIndex(RegisterFile::OptionalCalleeArguments);
-        addVar(propertyNames().arguments, false);
+    
+    emitOpcode(op_enter);
+    if (m_codeBlock->needsFullScopeChain()) {
+        m_activationRegister = addVar();
+        emitInitLazyRegister(m_activationRegister);
+        m_codeBlock->setActivationRegister(m_activationRegister->index());
     }
 
-    if (m_codeBlock->needsFullScopeChain()) {
-        ++m_codeBlock->m_numVars;
-        m_activationRegisterIndex = newRegister()->index();
-        emitOpcode(op_enter_with_activation);
-        instructions().append(m_activationRegisterIndex);
-    } else
-        emitOpcode(op_enter);
+    // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments'
+    // object, if created.
+    if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) {
+        RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code.
+        RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'.
+
+        // We can save a little space by hard-coding the knowledge that the two
+        // 'arguments' values are stored in consecutive registers, and storing
+        // only the index of the assignable one.
+        codeBlock->setArgumentsRegister(argumentsRegister->index());
+        ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister()));
 
-    if (usesArguments) {
-        emitOpcode(op_init_arguments);
+        emitInitLazyRegister(argumentsRegister);
+        emitInitLazyRegister(unmodifiedArgumentsRegister);
+        
+        if (m_codeBlock->isStrictMode()) {
+            emitOpcode(op_create_arguments);
+            instructions().append(argumentsRegister->index());
+        }
 
         // The debugger currently retrieves the arguments object from an activation rather than pulling
         // it from a call frame.  In the long-term it should stop doing that (<rdar://problem/6911886>),
         // but for now we force eager creation of the arguments object when debugging.
-        if (m_shouldEmitDebugHooks)
+        if (m_shouldEmitDebugHooks) {
             emitOpcode(op_create_arguments);
+            instructions().append(argumentsRegister->index());
+        }
     }
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
+    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
+
+    // Captured variables and functions go first so that activations don't have
+    // to step over the non-captured locals to mark them.
+    m_hasCreatedActivation = false;
+    if (functionBody->hasCapturedVariables()) {
+        for (size_t i = 0; i < functionStack.size(); ++i) {
+            FunctionBodyNode* function = functionStack[i];
+            const Identifier& ident = function->ident();
+            if (functionBody->captures(ident)) {
+                if (!m_hasCreatedActivation) {
+                    m_hasCreatedActivation = true;
+                    emitOpcode(op_create_activation);
+                    instructions().append(m_activationRegister->index());
+                }
+                m_functions.add(ident.impl());
+                emitNewFunction(addVar(ident, false), function);
+            }
+        }
+        for (size_t i = 0; i < varStack.size(); ++i) {
+            const Identifier& ident = *varStack[i].first;
+            if (functionBody->captures(ident))
+                addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
+        }
+    }
+    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
+    if (!canLazilyCreateFunctions && !m_hasCreatedActivation) {
+        m_hasCreatedActivation = true;
+        emitOpcode(op_create_activation);
+        instructions().append(m_activationRegister->index());
+    }
+
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
+    m_firstLazyFunction = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
         FunctionBodyNode* function = functionStack[i];
         const Identifier& ident = function->ident();
-        m_functions.add(ident.ustring().rep());
-        emitNewFunction(addVar(ident, false), function);
+        if (!functionBody->captures(ident)) {
+            m_functions.add(ident.impl());
+            RefPtr<RegisterID> reg = addVar(ident, false);
+            // Don't lazily create functions that override the name 'arguments'
+            // as this would complicate lazy instantiation of actual arguments.
+            if (!canLazilyCreateFunctions || ident == propertyNames().arguments)
+                emitNewFunction(reg.get(), function);
+            else {
+                emitInitLazyRegister(reg.get());
+                m_lazyFunctions.set(reg->index(), function);
+            }
+        }
     }
-
-    const DeclarationStacks::VarStack& varStack = functionBody->varStack();
-    for (size_t i = 0; i < varStack.size(); ++i)
-        addVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+    m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction;
+    for (size_t i = 0; i < varStack.size(); ++i) {
+        const Identifier& ident = *varStack[i].first;
+        if (!functionBody->captures(ident))
+            addVar(ident, varStack[i].second & DeclarationStacks::IsConstant);
+    }
+    
+    if (m_shouldEmitDebugHooks)
+        codeBlock->m_numCapturedVars = codeBlock->m_numVars;
 
     FunctionParameters& parameters = *functionBody->parameters();
     size_t parameterCount = parameters.size();
-    m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
+    int nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
     m_parameters.grow(1 + parameterCount); // reserve space for "this"
 
     // Add "this" as a parameter
-    m_thisRegister.setIndex(m_nextParameterIndex);
-    ++m_nextParameterIndex;
+    m_thisRegister.setIndex(nextParameterIndex);
     ++m_codeBlock->m_numParameters;
-
-    if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
-        emitOpcode(op_convert_this);
-        instructions().append(m_thisRegister.index());
-    }
     
     for (size_t i = 0; i < parameterCount; ++i)
-        addParameter(parameters[i]);
+        addParameter(parameters[i], ++nextParameterIndex);
 
     preserveLastVar();
+
+    if (isConstructor()) {
+        RefPtr<RegisterID> func = newTemporary();
+        RefPtr<RegisterID> funcProto = newTemporary();
+
+        emitOpcode(op_get_callee);
+        instructions().append(func->index());
+        // Load prototype.
+        emitGetById(funcProto.get(), func.get(), globalData()->propertyNames->prototype);
+
+        emitOpcode(op_create_this);
+        instructions().append(m_thisRegister.index());
+        instructions().append(funcProto->index());
+    } else if (functionBody->usesThis() || m_shouldEmitDebugHooks) {
+        if (codeBlock->isStrictMode())
+            emitOpcode(op_convert_this_strict);
+        else
+            emitOpcode(op_convert_this);
+        instructions().append(m_thisRegister.index());
+    }
 }
 
-BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
-    : m_shouldEmitDebugHooks(!!debugger)
-    , m_shouldEmitProfileHooks(scopeChain.globalObject()->supportsProfiling())
-    , m_scopeChain(&scopeChain)
+BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, ScopeChainNode* scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
+    : m_shouldEmitDebugHooks(scopeChain->globalObject->debugger())
+    , m_shouldEmitProfileHooks(scopeChain->globalObject->supportsProfiling())
+    , m_shouldEmitRichSourceInfo(scopeChain->globalObject->supportsRichSourceInfo())
+    , m_scopeChain(*scopeChain->globalData, scopeChain)
     , m_symbolTable(symbolTable)
     , m_scopeNode(evalNode)
     , m_codeBlock(codeBlock)
@@ -384,11 +499,17 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     , m_codeType(EvalCode)
     , m_nextConstantOffset(0)
     , m_globalConstantIndex(0)
-    , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
+    , m_hasCreatedActivation(true)
+    , m_firstLazyFunction(0)
+    , m_lastLazyFunction(0)
+    , m_globalData(scopeChain->globalData)
     , m_lastOpcodeID(op_end)
-    , m_emitNodeDepth(0)
-    , m_regeneratingForExceptionInfo(false)
-    , m_codeBlockBeingRegeneratedFrom(0)
+#ifndef NDEBUG
+    , m_lastOpcodePosition(0)
+#endif
+    , m_stack(m_globalData->stack())
+    , m_usesExceptions(false)
+    , m_expressionTooDeep(false)
 {
     if (m_shouldEmitDebugHooks || m_baseScopeDepth)
         m_codeBlock->setNeedsFullScopeChain(true);
@@ -408,27 +529,30 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     for (size_t i = 0; i < numVariables; ++i)
         variables.append(*varStack[i].first);
     codeBlock->adoptVariables(variables);
-
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     preserveLastVar();
 }
 
-RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
+RegisterID* BytecodeGenerator::emitInitLazyRegister(RegisterID* reg)
+{
+    emitOpcode(op_init_lazy_reg);
+    instructions().append(reg->index());
+    return reg;
+}
+
+void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex)
 {
     // Parameters overwrite var declarations, but not function declarations.
-    RegisterID* result = 0;
-    UString::Rep* rep = ident.ustring().rep();
+    StringImpl* rep = ident.impl();
     if (!m_functions.contains(rep)) {
-        symbolTable().set(rep, m_nextParameterIndex);
-        RegisterID& parameter = registerFor(m_nextParameterIndex);
-        parameter.setIndex(m_nextParameterIndex);
-        result = &parameter;
+        symbolTable().set(rep, parameterIndex);
+        RegisterID& parameter = registerFor(parameterIndex);
+        parameter.setIndex(parameterIndex);
     }
 
     // To maintain the calling convention, we have to allocate unique space for
     // each parameter, even if the parameter doesn't make it into the symbol table.
-    ++m_nextParameterIndex;
     ++m_codeBlock->m_numParameters;
-    return result;
 }
 
 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
@@ -439,14 +563,14 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
     if (!shouldOptimizeLocals())
         return 0;
 
-    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+    SymbolTableEntry entry = symbolTable().get(ident.impl());
     if (entry.isNull())
         return 0;
 
     if (ident == propertyNames().arguments)
         createArgumentsIfNecessary();
 
-    return &registerFor(entry.getIndex());
+    return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
 }
 
 bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
@@ -457,7 +581,7 @@ bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
     if (!shouldOptimizeLocals())
         return false;
     
-    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+    SymbolTableEntry entry = symbolTable().get(ident.impl());
     if (entry.isNull())
         return false;
     
@@ -471,21 +595,29 @@ RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
 {
     ASSERT(willResolveToArguments(propertyNames().arguments));
 
-    SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep());
+    SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.impl());
     ASSERT(!entry.isNull());
     return &registerFor(entry.getIndex());
 }
 
+RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg)
+{
+    if (m_lastLazyFunction <= reg->index() || reg->index() < m_firstLazyFunction)
+        return reg;
+    emitLazyNewFunction(reg, m_lazyFunctions.get(reg->index()));
+    return reg;
+}
+
 RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
 {
     if (m_codeType == EvalCode)
         return 0;
 
-    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+    SymbolTableEntry entry = symbolTable().get(ident.impl());
     if (entry.isNull())
         return 0;
 
-    return &registerFor(entry.getIndex());
+    return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
 }
 
 bool BytecodeGenerator::isLocal(const Identifier& ident)
@@ -493,12 +625,12 @@ bool BytecodeGenerator::isLocal(const Identifier& ident)
     if (ident == propertyNames().thisIdentifier)
         return true;
     
-    return shouldOptimizeLocals() && symbolTable().contains(ident.ustring().rep());
+    return shouldOptimizeLocals() && symbolTable().contains(ident.impl());
 }
 
 bool BytecodeGenerator::isLocalConstant(const Identifier& ident)
 {
-    return symbolTable().get(ident.ustring().rep()).isReadOnly();
+    return symbolTable().get(ident.impl()).isReadOnly();
 }
 
 RegisterID* BytecodeGenerator::newRegister()
@@ -573,6 +705,11 @@ PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
 
 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
 {
+#ifndef NDEBUG
+    size_t opcodePosition = instructions().size();
+    ASSERT(opcodePosition - m_lastOpcodePosition == opcodeLength(m_lastOpcodeID) || m_lastOpcodeID == op_end);
+    m_lastOpcodePosition = opcodePosition;
+#endif
     instructions().append(globalData()->interpreter->getOpcode(opcodeID));
     m_lastOpcodeID = opcodeID;
 }
@@ -598,12 +735,14 @@ void ALWAYS_INLINE BytecodeGenerator::rewindBinaryOp()
 {
     ASSERT(instructions().size() >= 4);
     instructions().shrink(instructions().size() - 4);
+    m_lastOpcodeID = op_end;
 }
 
 void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
 {
     ASSERT(instructions().size() >= 3);
     instructions().shrink(instructions().size() - 3);
+    m_lastOpcodeID = op_end;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
@@ -786,7 +925,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond,
 
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
-    instructions().append(m_scopeChain->globalObject()->d()->callFunction);
+    instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->callFunction()));
     instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
@@ -797,14 +936,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond
 
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
-    instructions().append(m_scopeChain->globalObject()->d()->applyFunction);
+    instructions().append(Instruction(*m_globalData, m_codeBlock->ownerExecutable(), m_scopeChain->globalObject->applyFunction()));
     instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
 {
-    UString::Rep* rep = ident.ustring().rep();
+    StringImpl* rep = ident.impl();
     pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers());
     if (result.second) // new entry
         m_codeBlock->addIdentifier(Identifier(m_globalData, rep));
@@ -820,7 +959,7 @@ RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
     if (result.second) {
         m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
         ++m_nextConstantOffset;
-        m_codeBlock->addConstantRegister(JSValue(v));
+        m_codeBlock->addConstant(JSValue(v));
     } else
         index = result.first->second;
 
@@ -903,8 +1042,8 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
         if (src1->index() == dstIndex
             && src1->isTemporary()
             && m_codeBlock->isConstantRegisterIndex(src2->index())
-            && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
-            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue();
+            && m_codeBlock->constantRegister(src2->index()).get().isString()) {
+            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).get())->tryGetValue();
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
@@ -964,19 +1103,20 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
 
 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
 {
-    // FIXME: Our hash tables won't hold infinity, so we make a new JSNumberCell each time.
-    // Later we can do the extra work to handle that like the other cases.
-    if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
-        return emitLoad(dst, jsNumber(globalData(), number));
+    // FIXME: Our hash tables won't hold infinity, so we make a new JSValue each time.
+    // Later we can do the extra work to handle that like the other cases.  They also don't
+    // work correctly with NaN as a key.
+    if (isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
+        return emitLoad(dst, jsNumber(number));
     JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second;
     if (!valueInMap)
-        valueInMap = jsNumber(globalData(), number);
+        valueInMap = jsNumber(number);
     return emitLoad(dst, valueInMap);
 }
 
 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier)
 {
-    JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
+    JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second;
     if (!stringInMap)
         stringInMap = jsOwnedString(globalData(), identifier.ustring());
     return emitLoad(dst, JSValue(stringInMap));
@@ -999,7 +1139,7 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
 
         if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
             ScopeChainIterator iter = m_scopeChain->begin();
-            globalObject = *iter;
+            globalObject = iter->get();
             ASSERT((++iter) == m_scopeChain->end());
         }
         return false;
@@ -1010,11 +1150,11 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
     ScopeChainIterator iter = m_scopeChain->begin();
     ScopeChainIterator end = m_scopeChain->end();
     for (; iter != end; ++iter, ++depth) {
-        JSObject* currentScope = *iter;
+        JSObject* currentScope = iter->get();
         if (!currentScope->isVariableObject())
             break;
         JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
-        SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.ustring().rep());
+        SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
 
         // Found the property
         if (!entry.isNull()) {
@@ -1025,7 +1165,7 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
                     globalObject = currentVariableObject;
                 return false;
             }
-            stackDepth = depth;
+            stackDepth = depth + m_codeBlock->needsFullScopeChain();
             index = entry.getIndex();
             if (++iter == end)
                 globalObject = currentVariableObject;
@@ -1037,14 +1177,20 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
         requiresDynamicChecks |= scopeRequiresDynamicChecks;
     }
     // Can't locate the property but we're able to avoid a few lookups.
-    stackDepth = depth;
+    stackDepth = depth + m_codeBlock->needsFullScopeChain();
     index = missingSymbolMarker();
-    JSObject* scope = *iter;
+    JSObject* scope = iter->get();
     if (++iter == end)
         globalObject = scope;
     return true;
 }
 
+void BytecodeGenerator::emitCheckHasInstance(RegisterID* base)
+{ 
+    emitOpcode(op_check_has_instance);
+    instructions().append(base->index());
+}
+
 RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype)
 { 
     emitOpcode(op_instanceof);
@@ -1055,6 +1201,13 @@ RegisterID* BytecodeGenerator::emitInstanceOf(RegisterID* dst, RegisterID* value
     return dst;
 }
 
+static const unsigned maxGlobalResolves = 128;
+
+bool BytecodeGenerator::shouldAvoidResolveGlobal()
+{
+    return m_codeBlock->globalResolveInfoCount() > maxGlobalResolves && !m_labelScopes.size();
+}
+
 RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
 {
     size_t depth = 0;
@@ -1068,16 +1221,13 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
         instructions().append(addConstant(property));
         return dst;
     }
-
+    if (shouldAvoidResolveGlobal()) {
+        globalObject = 0;
+        requiresDynamicChecks = true;
+    }
+        
     if (globalObject) {
         bool forceGlobalResolve = false;
-        if (m_regeneratingForExceptionInfo) {
-#if ENABLE(JIT)
-            forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
-#else
-            forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
-#endif
-        }
 
         if (index != missingSymbolMarker() && !forceGlobalResolve && !requiresDynamicChecks) {
             // Directly index the property lookup across multiple scopes.
@@ -1086,12 +1236,12 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
 
 #if ENABLE(JIT)
         m_codeBlock->addGlobalResolveInfo(instructions().size());
-#else
+#endif
+#if ENABLE(INTERPRETER)
         m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
         emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
         instructions().append(dst->index());
-        instructions().append(globalObject);
         instructions().append(addConstant(property));
         instructions().append(0);
         instructions().append(0);
@@ -1127,7 +1277,6 @@ RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, i
     if (globalObject) {
         emitOpcode(op_get_global_var);
         instructions().append(dst->index());
-        instructions().append(asCell(globalObject));
         instructions().append(index);
         return dst;
     }
@@ -1143,7 +1292,6 @@ RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, Registe
 {
     if (globalObject) {
         emitOpcode(op_put_global_var);
-        instructions().append(asCell(globalObject));
         instructions().append(index);
         instructions().append(value->index());
         return value;
@@ -1167,6 +1315,7 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier
         emitOpcode(op_resolve_base);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
+        instructions().append(false);
         return dst;
     }
 
@@ -1174,6 +1323,32 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier
     return emitLoad(dst, JSValue(globalObject));
 }
 
+RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Identifier& property)
+{
+    if (!m_codeBlock->isStrictMode())
+        return emitResolveBase(dst, property);
+    size_t depth = 0;
+    int index = 0;
+    JSObject* globalObject = 0;
+    bool requiresDynamicChecks = false;
+    findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
+    if (!globalObject || requiresDynamicChecks) {
+        // We can't optimise at all :-(
+        emitOpcode(op_resolve_base);
+        instructions().append(dst->index());
+        instructions().append(addConstant(property));
+        instructions().append(true);
+        return dst;
+    }
+    
+    // Global object is the base
+    RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject));
+    emitOpcode(op_ensure_property_exists);
+    instructions().append(dst->index());
+    instructions().append(addConstant(property));
+    return result.get();
+}
+
 RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
 {
     size_t depth = 0;
@@ -1190,13 +1365,6 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
     }
 
     bool forceGlobalResolve = false;
-    if (m_regeneratingForExceptionInfo) {
-#if ENABLE(JIT)
-        forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
-#else
-        forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
-#endif
-    }
 
     // Global object is the base
     emitLoad(baseDst, JSValue(globalObject));
@@ -1206,15 +1374,20 @@ RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, Register
         emitGetScopedVar(propDst, depth, index, globalObject);
         return baseDst;
     }
-
+    if (shouldAvoidResolveGlobal()) {
+        emitOpcode(op_resolve);
+        instructions().append(propDst->index());
+        instructions().append(addConstant(property));
+        return baseDst;
+    }
 #if ENABLE(JIT)
     m_codeBlock->addGlobalResolveInfo(instructions().size());
-#else
+#endif
+#if ENABLE(INTERPRETER)
     m_codeBlock->addGlobalResolveInstruction(instructions().size());
 #endif
     emitOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     instructions().append(propDst->index());
-    instructions().append(globalObject);
     instructions().append(addConstant(property));
     instructions().append(0);
     instructions().append(0);
@@ -1232,7 +1405,9 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
 {
 #if ENABLE(JIT)
     m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
-#else
+#endif
+    
+#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 
@@ -1247,11 +1422,22 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitGetArgumentsLength(RegisterID* dst, RegisterID* base)
+{
+    emitOpcode(op_get_arguments_length);
+    instructions().append(dst->index());
+    ASSERT(base->index() == m_codeBlock->argumentsRegister());
+    instructions().append(base->index());
+    instructions().append(addConstant(propertyNames().length));
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 #if ENABLE(JIT)
     m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
-#else
+#endif
+#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 
@@ -1271,7 +1457,8 @@ RegisterID* BytecodeGenerator::emitDirectPutById(RegisterID* base, const Identif
 {
 #if ENABLE(JIT)
     m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
-#else
+#endif
+#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
     
@@ -1314,6 +1501,16 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
+{
+    emitOpcode(op_get_argument_by_val);
+    instructions().append(dst->index());
+    ASSERT(base->index() == m_codeBlock->argumentsRegister());
+    instructions().append(base->index());
+    instructions().append(property->index());
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
     for (size_t i = m_forInContextStack.size(); i > 0; i--) {
@@ -1370,8 +1567,60 @@ RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements)
+unsigned BytecodeGenerator::addConstantBuffer(unsigned length)
+{
+    return m_codeBlock->addConstantBuffer(length);
+}
+
+JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier)
+{
+    JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second;
+    if (!stringInMap) {
+        stringInMap = jsString(globalData(), identifier.ustring());
+        addConstantValue(stringInMap);
+    }
+    return stringInMap;
+}
+
+RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elements, unsigned length)
 {
+#if !ASSERT_DISABLED
+    unsigned checkLength = 0;
+#endif
+    bool hadVariableExpression = false;
+    if (length) {
+        for (ElementNode* n = elements; n; n = n->next()) {
+            if (!n->value()->isNumber() && !n->value()->isString()) {
+                hadVariableExpression = true;
+                break;
+            }
+            if (n->elision())
+                break;
+#if !ASSERT_DISABLED
+            checkLength++;
+#endif
+        }
+        if (!hadVariableExpression) {
+            ASSERT(length == checkLength);
+            unsigned constantBufferIndex = addConstantBuffer(length);
+            JSValue* constantBuffer = m_codeBlock->constantBuffer(constantBufferIndex);
+            unsigned index = 0;
+            for (ElementNode* n = elements; index < length; n = n->next()) {
+                if (n->value()->isNumber())
+                    constantBuffer[index++] = jsNumber(static_cast<NumberNode*>(n->value())->value());
+                else {
+                    ASSERT(n->value()->isString());
+                    constantBuffer[index++] = addStringConstant(static_cast<StringNode*>(n->value())->value());
+                }
+            }
+            emitOpcode(op_new_array_buffer);
+            instructions().append(dst->index());
+            instructions().append(constantBufferIndex);
+            instructions().append(length);
+            return dst;
+        }
+    }
+
     Vector<RefPtr<RegisterID>, 16> argv;
     for (ElementNode* n = elements; n; n = n->next()) {
         if (n->elision())
@@ -1390,11 +1639,24 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
 
 RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
-    unsigned index = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
+    return emitNewFunctionInternal(dst, m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)), false);
+}
+
+RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function)
+{
+    std::pair<FunctionOffsetMap::iterator, bool> ptr = m_functionOffsets.add(function, 0);
+    if (ptr.second)
+        ptr.first->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
+    return emitNewFunctionInternal(dst, ptr.first->second, true);
+}
 
+RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck)
+{
+    createActivationIfNecessary();
     emitOpcode(op_new_func);
     instructions().append(dst->index());
     instructions().append(index);
+    instructions().append(doNullCheck);
     return dst;
 }
 
@@ -1406,64 +1668,68 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
     return dst;
 }
 
-
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
     FunctionBodyNode* function = n->body();
     unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
-
+    
+    createActivationIfNecessary();
     emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
     instructions().append(index);
     return r0;
 }
 
-RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
-    return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
+    return emitCall(op_call, dst, func, callArguments, divot, startOffset, endOffset);
 }
 
 void BytecodeGenerator::createArgumentsIfNecessary()
 {
-    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
-        emitOpcode(op_create_arguments);
+    if (m_codeType != FunctionCode)
+        return;
+    
+    if (!m_codeBlock->usesArguments())
+        return;
+
+    // If we're in strict mode we tear off the arguments on function
+    // entry, so there's no need to check if we need to create them
+    // now
+    if (m_codeBlock->isStrictMode())
+        return;
+
+    emitOpcode(op_create_arguments);
+    instructions().append(m_codeBlock->argumentsRegister());
 }
 
-RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+void BytecodeGenerator::createActivationIfNecessary()
 {
-    createArgumentsIfNecessary();
-    return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
+    if (m_hasCreatedActivation)
+        return;
+    if (!m_codeBlock->needsFullScopeChain())
+        return;
+    emitOpcode(op_create_activation);
+    instructions().append(m_activationRegister->index());
 }
 
-RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+    return emitCall(op_call_eval, dst, func, callArguments, divot, startOffset, endOffset);
+}
+
+RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
     ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
     ASSERT(func->refCount());
-    ASSERT(thisRegister->refCount());
 
-    RegisterID* originalFunc = func;
-    if (m_shouldEmitProfileHooks) {
-        // If codegen decided to recycle func as this call's destination register,
-        // we need to undo that optimization here so that func will still be around
-        // for the sake of op_profile_did_call.
-        if (dst == func) {
-            RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister);
-            RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func);
-            
-            thisRegister = movedThisRegister.release().releaseRef();
-            func = movedFunc.release().releaseRef();
-        }
-    }
+    if (m_shouldEmitProfileHooks)
+        emitMove(callArguments.profileHookRegister(), func);
 
     // Generate code for arguments.
-    Vector<RefPtr<RegisterID>, 16> argv;
-    argv.append(thisRegister);
-    for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
-        argv.append(newTemporary());
-        // op_call requires the arguments to be a sequential range of registers
-        ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
-        emitNode(argv.last().get(), n);
-    }
+    unsigned argumentIndex = 0;
+    for (ArgumentListNode* n = callArguments.argumentsNode()->m_listNode; n; n = n->m_next)
+        emitNode(callArguments.argumentRegister(argumentIndex++), n);
 
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
@@ -1472,11 +1738,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
 
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_will_call);
-        instructions().append(func->index());
-
-#if ENABLE(JIT)
-        m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
-#endif
+        instructions().append(callArguments.profileHookRegister()->index());
     }
 
     emitExpressionInfo(divot, startOffset, endOffset);
@@ -1487,30 +1749,29 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
 
     // Emit call.
     emitOpcode(opcodeID);
-    instructions().append(dst->index()); // dst
     instructions().append(func->index()); // func
-    instructions().append(argv.size()); // argCount
-    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
+    instructions().append(callArguments.count()); // argCount
+    instructions().append(callArguments.callFrame()); // registerOffset
+    if (dst != ignoredResult()) {
+        emitOpcode(op_call_put_result);
+        instructions().append(dst->index()); // dst
+    }
 
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
-        instructions().append(func->index());
-
-        if (dst == originalFunc) {
-            thisRegister->deref();
-            func->deref();
-        }
+        instructions().append(callArguments.profileHookRegister()->index());
     }
 
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* arguments)
+RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* arguments)
 {
     ASSERT(argCountDst->index() < arguments->index());
     emitOpcode(op_load_varargs);
     instructions().append(argCountDst->index());
     instructions().append(arguments->index());
+    instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
     return argCountDst;
 }
 
@@ -1522,20 +1783,19 @@ RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_will_call);
         instructions().append(func->index());
-        
-#if ENABLE(JIT)
-        m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
-#endif
     }
     
     emitExpressionInfo(divot, startOffset, endOffset);
     
     // Emit call.
     emitOpcode(op_call_varargs);
-    instructions().append(dst->index()); // dst
     instructions().append(func->index()); // func
     instructions().append(argCountRegister->index()); // arg count
     instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
+    if (dst != ignoredResult()) {
+        emitOpcode(op_call_put_result);
+        instructions().append(dst->index()); // dst
+    }
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
         instructions().append(func->index());
@@ -1547,10 +1807,23 @@ RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
 {
     if (m_codeBlock->needsFullScopeChain()) {
         emitOpcode(op_tear_off_activation);
-        instructions().append(m_activationRegisterIndex);
-    } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1)
+        instructions().append(m_activationRegister->index());
+        instructions().append(m_codeBlock->argumentsRegister());
+    } else if (m_codeBlock->usesArguments() && m_codeBlock->m_numParameters > 1
+               && !m_codeBlock->isStrictMode()) { // If there are no named parameters, there's nothing to tear off, since extra / unnamed parameters get copied to the arguments object at construct time.
         emitOpcode(op_tear_off_arguments);
+        instructions().append(m_codeBlock->argumentsRegister());
+    }
 
+    // Constructors use op_ret_object_or_this to check the result is an
+    // object, unless we can trivially determine the check is not
+    // necessary (currently, if the return value is 'this').
+    if (isConstructor() && (src->index() != m_thisRegister.index())) {
+        emitOpcode(op_ret_object_or_this);
+        instructions().append(src->index());
+        instructions().append(m_thisRegister.index());
+        return src;
+    }
     return emitUnaryNoDstOp(op_ret, src);
 }
 
@@ -1561,43 +1834,25 @@ RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* s
     return src;
 }
 
-RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
+RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func, CallArguments& callArguments, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
     ASSERT(func->refCount());
 
-    RegisterID* originalFunc = func;
-    if (m_shouldEmitProfileHooks) {
-        // If codegen decided to recycle func as this call's destination register,
-        // we need to undo that optimization here so that func will still be around
-        // for the sake of op_profile_did_call.
-        if (dst == func) {
-            RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func);
-            func = movedFunc.release().releaseRef();
-        }
-    }
-
-    RefPtr<RegisterID> funcProto = newTemporary();
+    if (m_shouldEmitProfileHooks)
+        emitMove(callArguments.profileHookRegister(), func);
 
     // Generate code for arguments.
-    Vector<RefPtr<RegisterID>, 16> argv;
-    argv.append(newTemporary()); // reserve space for "this"
-    for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode : 0; n; n = n->m_next) {
-        argv.append(newTemporary());
-        // op_construct requires the arguments to be a sequential range of registers
-        ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
-        emitNode(argv.last().get(), n);
+    unsigned argumentIndex = 0;
+    if (ArgumentsNode* argumentsNode = callArguments.argumentsNode()) {
+        for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next)
+            emitNode(callArguments.argumentRegister(argumentIndex++), n);
     }
 
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_will_call);
-        instructions().append(func->index());
+        instructions().append(callArguments.profileHookRegister()->index());
     }
 
-    // Load prototype.
-    emitExpressionInfo(divot, startOffset, endOffset);
-    emitGetByIdExceptionInfo(op_construct);
-    emitGetById(funcProto.get(), func, globalData()->propertyNames->prototype);
-
     // Reserve space for call frame.
     Vector<RefPtr<RegisterID>, RegisterFile::CallFrameHeaderSize> callFrame;
     for (int i = 0; i < RegisterFile::CallFrameHeaderSize; ++i)
@@ -1610,23 +1865,17 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
 #endif
 
     emitOpcode(op_construct);
-    instructions().append(dst->index()); // dst
     instructions().append(func->index()); // func
-    instructions().append(argv.size()); // argCount
-    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
-    instructions().append(funcProto->index()); // proto
-    instructions().append(argv[0]->index()); // thisRegister
-
-    emitOpcode(op_construct_verify);
-    instructions().append(dst->index());
-    instructions().append(argv[0]->index());
+    instructions().append(callArguments.count()); // argCount
+    instructions().append(callArguments.callFrame()); // registerOffset
+    if (dst != ignoredResult()) {
+        emitOpcode(op_call_put_result);
+        instructions().append(dst->index()); // dst
+    }
 
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
-        instructions().append(func->index());
-        
-        if (dst == originalFunc)
-            func->deref();
+        instructions().append(callArguments.profileHookRegister()->index());
     }
 
     return dst;
@@ -1656,7 +1905,6 @@ RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
-    createArgumentsIfNecessary();
 
     return emitUnaryNoDstOp(op_push_scope, scope);
 }
@@ -1876,6 +2124,7 @@ RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID*
 
 RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
 {
+    m_usesExceptions = true;
 #if ENABLE(JIT)
     HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
 #else
@@ -1888,13 +2137,10 @@ RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* star
     return targetRegister;
 }
 
-RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue message)
+void BytecodeGenerator::emitThrowReferenceError(const UString& message)
 {
-    emitOpcode(op_new_error);
-    instructions().append(dst->index());
-    instructions().append(static_cast<int>(type));
-    instructions().append(addConstantValue(message)->index());
-    return dst;
+    emitOpcode(op_throw_reference_error);
+    instructions().append(addConstantValue(jsString(globalData(), message))->index());
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
@@ -1920,8 +2166,6 @@ void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& prop
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
-    
-    createArgumentsIfNecessary();
 
     emitOpcode(op_push_new_scope);
     instructions().append(dst->index());
@@ -1981,7 +2225,7 @@ static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t
 {
     UNUSED_PARAM(max);
     ASSERT(node->isString());
-    UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep();
+    StringImpl* clause = static_cast<StringNode*>(node)->value().impl();
     ASSERT(clause->length() == 1);
     
     int32_t key = clause->characters()[0];
@@ -2011,7 +2255,7 @@ static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t
         ASSERT(!labels[i]->isForward());
         
         ASSERT(nodes[i]->isString());
-        UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
+        StringImpl* clause = static_cast<StringNode*>(nodes[i])->value().impl();
         OffsetLocation location;
         location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3);
         jumpTable.offsetTable.add(clause, location);
@@ -2050,10 +2294,23 @@ RegisterID* BytecodeGenerator::emitThrowExpressionTooDeepException()
     // And we could make the caller pass the node pointer in, if there was some way of getting
     // that from an arbitrary node. However, calling emitExpressionInfo without any useful data
     // is still good enough to get us an accurate line number.
-    emitExpressionInfo(0, 0, 0);
-    RegisterID* exception = emitNewError(newTemporary(), SyntaxError, jsString(globalData(), "Expression too deep"));
-    emitThrow(exception);
-    return exception;
+    m_expressionTooDeep = true;
+    return newTemporary();
+}
+
+void BytecodeGenerator::setIsNumericCompareFunction(bool isNumericCompareFunction)
+{
+    m_codeBlock->setIsNumericCompareFunction(isNumericCompareFunction);
+}
+
+int BytecodeGenerator::argumentNumberFor(const Identifier& ident)
+{
+    int parameterCount = m_parameters.size(); // includes 'this'
+    RegisterID* registerID = registerFor(ident);
+    if (!registerID)
+        return 0;
+    int index = registerID->index() + RegisterFile::CallFrameHeaderSize + parameterCount;
+    return (index > 0 && index < parameterCount) ? index : 0;
 }
 
 } // namespace JSC
index 3667198dad5466e20548747449b5fa7925cc6c8c..bc297ee6d7fda2b78b8a57041e9b50c61703edf1 100644 (file)
@@ -40,7 +40,6 @@
 #include "SymbolTable.h"
 #include "Debugger.h"
 #include "Nodes.h"
-#include <wtf/FastAllocBase.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/SegmentedVector.h>
 #include <wtf/Vector.h>
 namespace JSC {
 
     class Identifier;
-    class ScopeChain;
-    class ScopeNode;
+    class ScopeChainNode;
+
+    class CallArguments {
+    public:
+        CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode);
+
+        RegisterID* thisRegister() { return m_argv[0].get(); }
+        RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
+        unsigned callFrame() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; }
+        unsigned count() { return m_argv.size(); }
+        RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
+        ArgumentsNode* argumentsNode() { return m_argumentsNode; }
+
+    private:
+        RefPtr<RegisterID> m_profileHookRegister;
+        ArgumentsNode* m_argumentsNode;
+        Vector<RefPtr<RegisterID>, 16> m_argv;
+    };
 
     struct FinallyContext {
         Label* finallyAddr;
@@ -68,7 +83,8 @@ namespace JSC {
         RefPtr<RegisterID> propertyRegister;
     };
 
-    class BytecodeGenerator : public FastAllocBase {
+    class BytecodeGenerator {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
@@ -76,20 +92,27 @@ namespace JSC {
         static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
         static bool dumpsGeneratedCode();
 
-        BytecodeGenerator(ProgramNode*, const Debugger*, const ScopeChain&, SymbolTable*, ProgramCodeBlock*);
-        BytecodeGenerator(FunctionBodyNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*);
-        BytecodeGenerator(EvalNode*, const Debugger*, const ScopeChain&, SymbolTable*, EvalCodeBlock*);
+        BytecodeGenerator(ProgramNode*, ScopeChainNode*, SymbolTable*, ProgramCodeBlock*);
+        BytecodeGenerator(FunctionBodyNode*, ScopeChainNode*, SymbolTable*, CodeBlock*);
+        BytecodeGenerator(EvalNode*, ScopeChainNode*, SymbolTable*, EvalCodeBlock*);
 
         JSGlobalData* globalData() const { return m_globalData; }
         const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
 
-        void generate();
+        bool isConstructor() { return m_codeBlock->m_isConstructor; }
+
+        JSObject* generate();
 
         // Returns the register corresponding to a local variable, or 0 if no
         // such register exists. Registers returned by registerFor do not
         // require explicit reference counting.
         RegisterID* registerFor(const Identifier&);
-        
+
+        // Returns the agument number if this is an argument, or 0 if not.
+        int argumentNumberFor(const Identifier&);
+
+        void setIsNumericCompareFunction(bool isNumericCompareFunction);
+
         bool willResolveToArguments(const Identifier&);
         RegisterID* uncheckedRegisterForArguments();
 
@@ -103,9 +126,6 @@ namespace JSC {
         // VariableObject that defines the property.  If the property cannot be found
         // statically, depth will contain the depth of the scope chain where dynamic
         // lookup must begin.
-        //
-        // NB: depth does _not_ include the local scope.  eg. a depth of 0 refers
-        // to the scope containing this codeblock.
         bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
 
         // Returns the register storing "this"
@@ -150,6 +170,17 @@ namespace JSC {
             return newTemporary();
         }
 
+        // Returns the place to write the final output of an operation.
+        RegisterID* finalDestinationOrIgnored(RegisterID* originalDst, RegisterID* tempDst = 0)
+        {
+            if (originalDst)
+                return originalDst;
+            ASSERT(tempDst != ignoredResult());
+            if (tempDst && tempDst->isTemporary())
+                return tempDst;
+            return newTemporary();
+        }
+
         RegisterID* destinationForAssignResult(RegisterID* dst)
         {
             if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
@@ -175,16 +206,10 @@ namespace JSC {
         {
             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
-            if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) {
-                LineInfo info = { instructions().size(), n->lineNo() };
-                m_codeBlock->addLineInfo(info);
-            }
-            if (m_emitNodeDepth >= s_maxEmitNodeDepth)
-                return emitThrowExpressionTooDeepException();
-            ++m_emitNodeDepth;
-            RegisterID* r = n->emitBytecode(*this, dst);
-            --m_emitNodeDepth;
-            return r;
+            addLineInfo(n->lineNo());
+            return m_stack.recursionCheck()
+                ? n->emitBytecode(*this, dst)
+                : emitThrowExpressionTooDeepException();
         }
 
         RegisterID* emitNode(Node* n)
@@ -194,19 +219,18 @@ namespace JSC {
 
         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
         {
-            if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) {
-                LineInfo info = { instructions().size(), n->lineNo() };
-                m_codeBlock->addLineInfo(info);
-            }
-            if (m_emitNodeDepth >= s_maxEmitNodeDepth)
+            addLineInfo(n->lineNo());
+            if (m_stack.recursionCheck())
+                n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
+            else
                 emitThrowExpressionTooDeepException();
-            ++m_emitNodeDepth;
-            n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
-            --m_emitNodeDepth;
         }
 
         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
-        { 
+        {
+            if (!m_shouldEmitRichSourceInfo)
+                return;
+
             divot -= m_codeBlock->sourceOffset();
             if (divot > ExpressionRangeInfo::MaxDivot) {
                 // Overflow has occurred, we can only give line number info for errors for this region
@@ -234,17 +258,6 @@ namespace JSC {
             m_codeBlock->addExpressionInfo(info);
         }
 
-        void emitGetByIdExceptionInfo(OpcodeID opcodeID)
-        {
-            // Only op_construct and op_instanceof need exception info for
-            // a preceding op_get_by_id.
-            ASSERT(opcodeID == op_construct || opcodeID == op_instanceof);
-            GetByIdExceptionInfo info;
-            info.bytecodeOffset = instructions().size();
-            info.isOpConstruct = (opcodeID == op_construct);
-            m_codeBlock->addGetByIdExceptionInfo(info);
-        }
-        
         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
         {
             return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
@@ -272,11 +285,13 @@ namespace JSC {
         RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
 
         RegisterID* emitNewObject(RegisterID* dst);
-        RegisterID* emitNewArray(RegisterID* dst, ElementNode*); // stops at first elision
+        RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
 
         RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode* body);
+        RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body);
+        RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck);
         RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
-        RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp);
+        RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
 
         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
 
@@ -286,6 +301,7 @@ namespace JSC {
         RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
         RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
 
+        void emitCheckHasInstance(RegisterID* base);
         RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype);
         RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
@@ -295,30 +311,33 @@ namespace JSC {
         RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue globalObject);
 
         RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
+        RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
         RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
 
         void emitMethodCheck();
 
         RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
+        RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);
         RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
         RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
+        RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
         RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
         RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
         RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
         RegisterID* emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value);
         RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value);
 
-        RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
-        RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        RegisterID* emitCall(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
+        RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
         RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCount, unsigned divot, unsigned startOffset, unsigned endOffset);
-        RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* args);
+        RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
 
         RegisterID* emitReturn(RegisterID* src);
         RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
 
-        RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
         RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
         void emitToPrimitive(RegisterID* dst, RegisterID* src);
 
@@ -337,8 +356,14 @@ namespace JSC {
         RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
 
         RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
-        void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); }
-        RegisterID* emitNewError(RegisterID* dst, ErrorType type, JSValue message);
+        void emitThrow(RegisterID* exc)
+        { 
+            m_usesExceptions = true;
+            emitUnaryNoDstOp(op_throw, exc);
+        }
+
+        void emitThrowReferenceError(const UString& message);
+
         void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
 
         RegisterID* emitPushScope(RegisterID* scope);
@@ -371,11 +396,9 @@ namespace JSC {
 
         CodeType codeType() const { return m_codeType; }
 
-        void setRegeneratingForExceptionInfo(CodeBlock* originalCodeBlock)
-        {
-            m_regeneratingForExceptionInfo = true;
-            m_codeBlockBeingRegeneratedFrom = originalCodeBlock;
-        }
+        bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
+        
+        bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
 
     private:
         void emitOpcode(OpcodeID);
@@ -397,23 +420,31 @@ namespace JSC {
             static const bool needsRef = false;
         };
 
-        typedef HashMap<RefPtr<UString::Rep>, int, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, IdentifierMapIndexHashTraits> IdentifierMap;
+        typedef HashMap<RefPtr<StringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, IdentifierMapIndexHashTraits> IdentifierMap;
         typedef HashMap<double, JSValue> NumberMap;
-        typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap;
-        
-        RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
+        typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
         
+        RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
+
         RegisterID* newRegister();
 
-        // Returns the RegisterID corresponding to ident.
+        // Adds a var slot and maps it to the name ident in symbolTable().
         RegisterID* addVar(const Identifier& ident, bool isConstant)
         {
             RegisterID* local;
             addVar(ident, isConstant, local);
             return local;
         }
-        // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
+
+        // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
         bool addVar(const Identifier&, bool isConstant, RegisterID*&);
+        
+        // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
+        RegisterID* addVar()
+        {
+            ++m_codeBlock->m_numVars;
+            return newRegister();
+        }
 
         // Returns the RegisterID corresponding to ident.
         RegisterID* addGlobalVar(const Identifier& ident, bool isConstant)
@@ -425,18 +456,16 @@ namespace JSC {
         // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
         bool addGlobalVar(const Identifier&, bool isConstant, RegisterID*&);
 
-        RegisterID* addParameter(const Identifier&);
+        void addParameter(const Identifier&, int parameterIndex);
         
         void preserveLastVar();
+        bool shouldAvoidResolveGlobal();
 
         RegisterID& registerFor(int index)
         {
             if (index >= 0)
                 return m_calleeRegisters[index];
 
-            if (index == RegisterFile::OptionalCalleeArguments)
-                return m_argumentsRegister;
-
             if (m_parameters.size()) {
                 ASSERT(!m_globals.size());
                 return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
@@ -449,16 +478,30 @@ namespace JSC {
         RegisterID* addConstantValue(JSValue);
         unsigned addRegExp(RegExp*);
 
-        PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body)
+        unsigned addConstantBuffer(unsigned length);
+        
+        FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
         {
-            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
-        PassRefPtr<FunctionExecutable> makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
+        FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
         {
-            return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+            return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
         }
 
+        JSString* addStringConstant(const Identifier&);
+
+        void addLineInfo(unsigned lineNo)
+        {
+#if !ENABLE(OPCODE_SAMPLING)
+            if (m_shouldEmitRichSourceInfo)
+#endif
+                m_codeBlock->addLineInfo(instructions().size(), lineNo);
+        }
+
+        RegisterID* emitInitLazyRegister(RegisterID*);
+
         Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
@@ -468,11 +511,14 @@ namespace JSC {
         RegisterID* emitThrowExpressionTooDeepException();
 
         void createArgumentsIfNecessary();
+        void createActivationIfNecessary();
+        RegisterID* createLazyRegisterIfNecessary(RegisterID*);
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
+        bool m_shouldEmitRichSourceInfo;
 
-        const ScopeChain* m_scopeChain;
+        Strong<ScopeChainNode> m_scopeChain;
         SymbolTable* m_symbolTable;
 
         ScopeNode* m_scopeNode;
@@ -480,11 +526,10 @@ namespace JSC {
 
         // Some of these objects keep pointers to one another. They are arranged
         // to ensure a sane destruction order that avoids references to freed memory.
-        HashSet<RefPtr<UString::Rep>, IdentifierRepHash> m_functions;
+        HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
         RegisterID m_ignoredResultRegister;
         RegisterID m_thisRegister;
-        RegisterID m_argumentsRegister;
-        int m_activationRegisterIndex;
+        RegisterID* m_activationRegister;
         SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
         SegmentedVector<RegisterID, 32> m_calleeRegisters;
         SegmentedVector<RegisterID, 32> m_parameters;
@@ -502,13 +547,19 @@ namespace JSC {
         Vector<ForInContext> m_forInContextStack;
 
         int m_nextGlobalIndex;
-        int m_nextParameterIndex;
         int m_firstConstantIndex;
         int m_nextConstantOffset;
         unsigned m_globalConstantIndex;
 
         int m_globalVarStorageOffset;
 
+        bool m_hasCreatedActivation;
+        int m_firstLazyFunction;
+        int m_lastLazyFunction;
+        HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
+        typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
+        FunctionOffsetMap m_functionOffsets;
+        
         // Constant pool
         IdentifierMap m_identifierMap;
         JSValueMap m_jsValueMap;
@@ -518,34 +569,14 @@ namespace JSC {
         JSGlobalData* m_globalData;
 
         OpcodeID m_lastOpcodeID;
+#ifndef NDEBUG
+        size_t m_lastOpcodePosition;
+#endif
 
-        unsigned m_emitNodeDepth;
-
-        bool m_regeneratingForExceptionInfo;
-        CodeBlock* m_codeBlockBeingRegeneratedFrom;
+        StackBounds m_stack;
 
-        static const unsigned s_maxEmitNodeDepth = 3000;
-
-        friend class IncreaseEmitNodeDepth;
-    };
-
-    class IncreaseEmitNodeDepth {
-    public:
-        IncreaseEmitNodeDepth(BytecodeGenerator& generator, unsigned count = 1)
-            : m_generator(generator)
-            , m_count(count)
-        {
-            m_generator.m_emitNodeDepth += count;
-        }
-
-        ~IncreaseEmitNodeDepth()
-        {
-            m_generator.m_emitNodeDepth -= m_count;
-        }
-
-    private:
-        BytecodeGenerator& m_generator;
-        unsigned m_count;
+        bool m_usesExceptions;
+        bool m_expressionTooDeep;
     };
 }
 
index a7455e49ca9d0665aef2c7ad3ea6a2f04257e986..a7abadf40312a26889ec079a9c4ae4ba4d8f5df9 100644 (file)
@@ -42,6 +42,7 @@
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 #include "SamplingTool.h"
+#include "UStringConcatenate.h"
 #include <wtf/Assertions.h>
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/Threading.h>
@@ -75,34 +76,11 @@ namespace JSC {
 
 // ------------------------------ ThrowableExpressionData --------------------------------
 
-static void substitute(UString& string, const UString& substring)
+RegisterID* ThrowableExpressionData::emitThrowReferenceError(BytecodeGenerator& generator, const UString& message)
 {
-    unsigned position = string.find("%s");
-    ASSERT(position != UString::NotFound);
-    string = makeString(string.substr(0, position), substring, string.substr(position + 2));
-}
-
-RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message)
-{
-    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
-    generator.emitThrow(exception);
-    return exception;
-}
-
-RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label)
-{
-    UString message = messageTemplate;
-    substitute(message, label);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message));
-    generator.emitThrow(exception);
-    return exception;
-}
-
-inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label)
-{
-    return emitThrowError(generator, type, messageTemplate, label.ustring());
+    generator.emitThrowReferenceError(message);
+    return generator.newTemporary();
 }
 
 // ------------------------------ NullNode -------------------------------------
@@ -145,12 +123,9 @@ RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
 
 RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    RefPtr<RegExp> regExp = generator.globalData()->regExpCache()->lookupOrCreate(m_pattern.ustring(), m_flags.ustring());
-    if (!regExp->isValid())
-        return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage());
     if (dst == generator.ignoredResult())
         return 0;
-    return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get());
+    return generator.emitNewRegExp(generator.finalDestination(dst), RegExp::create(generator.globalData(), m_pattern.ustring(), regExpFlags(m_flags.ustring())));
 }
 
 // ------------------------------ ThisNode -------------------------------------
@@ -177,7 +152,7 @@ RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
         return generator.moveToDestinationIfNeeded(dst, local);
     }
     
-    generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0);
+    generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0);
     return generator.emitResolve(generator.finalDestination(dst), m_ident);
 }
 
@@ -196,9 +171,9 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
     }
 
     if (!firstPutElement && !m_elision)
-        return generator.emitNewArray(generator.finalDestination(dst), m_element);
+        return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
 
-    RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element);
+    RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
 
     for (ElementNode* n = firstPutElement; n; n = n->next()) {
         RegisterID* value = generator.emitNode(n->value());
@@ -207,7 +182,7 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
     }
 
     if (m_elision) {
-        RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length));
+        RegisterID* value = generator.emitLoad(0, jsNumber(m_elision + length));
         generator.emitPutById(array.get(), generator.propertyNames().length, value);
     }
 
@@ -289,6 +264,12 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe
 
 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) {
+        RegisterID* property = generator.emitNode(m_subscript);
+        generator.emitExpressionInfo(divot(), startOffset(), endOffset());    
+        return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
+    }
+
     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
     RegisterID* property = generator.emitNode(m_subscript);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
@@ -299,6 +280,17 @@ RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, Regi
 
 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (m_ident == generator.propertyNames().length) {
+        if (!m_base->isResolveNode())
+            goto nonArgumentsPath;
+        ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
+        if (!generator.willResolveToArguments(resolveNode->identifier()))
+            goto nonArgumentsPath;
+        generator.emitExpressionInfo(divot(), startOffset(), endOffset());    
+        return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
+    }
+
+nonArgumentsPath:
     RegisterID* base = generator.emitNode(m_base);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
@@ -317,7 +309,23 @@ RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, Registe
 RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> func = generator.emitNode(m_expr);
-    return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset());
+    CallArguments callArguments(generator, m_args);
+    return generator.emitConstruct(generator.finalDestinationOrIgnored(dst), func.get(), callArguments, divot(), startOffset(), endOffset());
+}
+
+CallArguments::CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode)
+    : m_argumentsNode(argumentsNode)
+{
+    if (generator.shouldEmitProfileHooks())
+        m_profileHookRegister = generator.newTemporary();
+    m_argv.append(generator.newTemporary());
+    if (argumentsNode) {
+        for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
+            m_argv.append(generator.newTemporary());
+            // op_call requires the arguments to be a sequential range of registers
+            ASSERT(m_argv[m_argv.size() - 1]->index() == m_argv[m_argv.size() - 2]->index() + 1);
+        }
+    }
 }
 
 // ------------------------------ EvalFunctionCallNode ----------------------------------
@@ -325,10 +333,10 @@ RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> func = generator.tempDestination(dst);
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
+    CallArguments callArguments(generator, m_args);
     generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
-    generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
-    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
+    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
 // ------------------------------ FunctionCallValueNode ----------------------------------
@@ -336,8 +344,9 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg
 RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> func = generator.emitNode(m_expr);
-    RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
-    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    CallArguments callArguments(generator, m_args);
+    generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+    return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
 // ------------------------------ FunctionCallResolveNode ----------------------------------
@@ -345,8 +354,9 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re
 RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
-        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
-        return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+        CallArguments callArguments(generator, m_args);
+        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+        return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset());
     }
 
     int index = 0;
@@ -355,16 +365,17 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator,
     bool requiresDynamicChecks = false;
     if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
         RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
-        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
-        return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+        CallArguments callArguments(generator, m_args);
+        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+        return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
     }
 
     RefPtr<RegisterID> func = generator.newTemporary();
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
+    CallArguments callArguments(generator, m_args);
     int identifierStart = divot() - startOffset();
-    generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
-    generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident);
-    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
+    generator.emitResolveWithBase(callArguments.thisRegister(), func.get(), m_ident);
+    return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
 // ------------------------------ FunctionCallBracketNode ----------------------------------
@@ -375,8 +386,9 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator,
     RegisterID* property = generator.emitNode(m_subscript);
     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
     RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
-    RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
-    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    CallArguments callArguments(generator, m_args);
+    generator.emitMove(callArguments.thisRegister(), base.get());
+    return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
 // ------------------------------ FunctionCallDotNode ----------------------------------
@@ -384,12 +396,12 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator,
 RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> function = generator.tempDestination(dst);
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
-    generator.emitNode(thisRegister.get(), m_base);
+    CallArguments callArguments(generator, m_args);
+    generator.emitNode(callArguments.thisRegister(), m_base);
     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
     generator.emitMethodCheck();
-    generator.emitGetById(function.get(), thisRegister.get(), m_ident);
-    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+    generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
+    return generator.emitCall(generator.finalDestinationOrIgnored(dst, function.get()), function.get(), callArguments, divot(), startOffset(), endOffset());
 }
 
 RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
@@ -399,31 +411,39 @@ RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
     RefPtr<RegisterID> base = generator.emitNode(m_base);
     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
     RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
-    RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+    RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
     generator.emitJumpIfNotFunctionCall(function.get(), realCall.get());
     {
-        RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-        RefPtr<RegisterID> thisRegister = generator.newTemporary();
-        ArgumentListNode* oldList = m_args->m_listNode;
         if (m_args->m_listNode && m_args->m_listNode->m_expr) {
-            generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
+            ArgumentListNode* oldList = m_args->m_listNode;
             m_args->m_listNode = m_args->m_listNode->m_next;
-        } else
-            generator.emitLoad(thisRegister.get(), jsNull());
 
-        generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-        generator.emitJump(end.get());
-        m_args->m_listNode = oldList;
+            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+            CallArguments callArguments(generator, m_args);
+            generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
+            generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+            generator.emitJump(end.get());
+
+            m_args->m_listNode = oldList;
+
+        } else {
+            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+            CallArguments callArguments(generator, m_args);
+            generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+            generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+            generator.emitJump(end.get());
+        }
     }
     generator.emitLabel(realCall.get());
     {
-        RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
-        generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+        CallArguments callArguments(generator, m_args);
+        generator.emitMove(callArguments.thisRegister(), base.get());
+        generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
     }
     generator.emitLabel(end.get());
-    return finalDestination.get();
+    return finalDestinationOrIgnored.get();
 }
-    
+
 static bool areTrivialApplyArguments(ArgumentsNode* args)
 {
     return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next
@@ -442,25 +462,34 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
     RefPtr<RegisterID> base = generator.emitNode(m_base);
     generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
     RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
-    RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get());
+    RefPtr<RegisterID> finalDestinationOrIgnored = generator.finalDestinationOrIgnored(dst, function.get());
     generator.emitJumpIfNotFunctionApply(function.get(), realCall.get());
     {
         if (mayBeCall) {
-            RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
-            RefPtr<RegisterID> thisRegister = generator.newTemporary();
-            ArgumentListNode* oldList = m_args->m_listNode;
             if (m_args->m_listNode && m_args->m_listNode->m_expr) {
-                generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr);
-                m_args->m_listNode = m_args->m_listNode->m_next;
-                if (m_args->m_listNode) {
-                    ASSERT(m_args->m_listNode->m_expr->isSimpleArray());
-                    ASSERT(!m_args->m_listNode->m_next);
-                    m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData());
+                ArgumentListNode* oldList = m_args->m_listNode;
+                if (m_args->m_listNode->m_next) {
+                    ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
+                    ASSERT(!m_args->m_listNode->m_next->m_next);
+                    m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_next->m_expr)->toArgumentList(generator.globalData());
+                    RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+                    CallArguments callArguments(generator, m_args);
+                    generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
+                    generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+                } else {
+                    m_args->m_listNode = m_args->m_listNode->m_next;
+                    RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+                    CallArguments callArguments(generator, m_args);
+                    generator.emitNode(callArguments.thisRegister(), oldList->m_expr);
+                    generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
                 }
-            } else
-                generator.emitLoad(thisRegister.get(), jsNull());
-            generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
-            m_args->m_listNode = oldList;
+                m_args->m_listNode = oldList;
+            } else {
+                RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get());
+                CallArguments callArguments(generator, m_args);
+                generator.emitLoad(callArguments.thisRegister(), jsUndefined());
+                generator.emitCall(finalDestinationOrIgnored.get(), realFunction.get(), callArguments, divot(), startOffset(), endOffset());
+            }
         } else {
             ASSERT(m_args->m_listNode && m_args->m_listNode->m_next);
             RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
@@ -481,18 +510,19 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator,
             while ((args = args->m_next))
                 generator.emitNode(args->m_expr);
 
-            generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get());
-            generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
+            generator.emitLoadVarargs(argsCountRegister.get(), thisRegister.get(), argsRegister.get());
+            generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset());
         }
         generator.emitJump(end.get());
     }
     generator.emitLabel(realCall.get());
     {
-        RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
-        generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset());
+        CallArguments callArguments(generator, m_args);
+        generator.emitMove(callArguments.thisRegister(), base.get());
+        generator.emitCall(finalDestinationOrIgnored.get(), function.get(), callArguments, divot(), startOffset(), endOffset());
     }
     generator.emitLabel(end.get());
-    return finalDestination.get();
+    return finalDestinationOrIgnored.get();
 }
 
 // ------------------------------ PostfixResolveNode ----------------------------------
@@ -605,7 +635,7 @@ RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterI
 
 RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
 {
-    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
+    return emitThrowReferenceError(generator, m_operator == OpPlusPlus
         ? "Postfix ++ operator applied to value that is not a reference."
         : "Postfix -- operator applied to value that is not a reference.");
 }
@@ -770,7 +800,7 @@ RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID
 
 RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
 {
-    return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus
+    return emitThrowReferenceError(generator, m_operator == OpPlusPlus
         ? "Prefix ++ operator applied to value that is not a reference."
         : "Prefix -- operator applied to value that is not a reference.");
 }
@@ -830,8 +860,6 @@ RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* d
     ASSERT(isAdd());
     ASSERT(resultDescriptor().definitelyIsString());
 
-    IncreaseEmitNodeDepth stackGuard(generator, 3);
-
     // Create a list of expressions for all the adds in the tree of nodes we can convert into
     // a string concatenation.  The rightmost node (c) is added first.  The rightmost node is
     // added first, and the leftmost child is never added, so the vector produced for the
@@ -978,7 +1006,9 @@ RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterI
     RefPtr<RegisterID> src2 = generator.emitNode(m_expr2);
 
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
-    generator.emitGetByIdExceptionInfo(op_instanceof);
+    generator.emitCheckHasInstance(src2.get());
+
+    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype);
 
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
@@ -1147,7 +1177,7 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
     }
 
     RefPtr<RegisterID> src1 = generator.tempDestination(dst);
-    generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0);
+    generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0);
     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
     RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
     return generator.emitPutById(base.get(), m_ident, result);
@@ -1177,7 +1207,7 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
         return value;
     }
 
-    RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
+    RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident);
     if (dst == generator.ignoredResult())
         dst = 0;
     RegisterID* value = generator.emitNode(dst, m_right);
@@ -1215,7 +1245,7 @@ RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, Regist
 
 RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
 {
-    return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference.");
+    return emitThrowReferenceError(generator, "Left side of assignment is not a reference.");
 }
 
 // ------------------------------ AssignBracketNode -----------------------------------
@@ -1323,6 +1353,11 @@ inline StatementNode* BlockNode::lastStatement() const
     return m_statements ? m_statements->lastStatement() : 0;
 }
 
+inline StatementNode* BlockNode::singleStatement() const
+{
+    return m_statements ? m_statements->singleStatement() : 0;
+}
+
 RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     if (m_statements)
@@ -1517,12 +1552,10 @@ RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
 RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    IncreaseEmitNodeDepth stackGuard(generator);
-
     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
 
     if (!m_lexpr->isLocation())
-        return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference.");
+        return emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
 
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
 
@@ -1548,7 +1581,7 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
         if (!propertyName) {
             propertyName = generator.newTemporary();
             RefPtr<RegisterID> protect = propertyName;
-            RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident);
+            RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident);
 
             generator.emitExpressionInfo(divot(), startOffset(), endOffset());
             generator.emitPutById(base, ident, propertyName);
@@ -1598,11 +1631,7 @@ RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
     
     LabelScope* scope = generator.continueTarget(m_ident);
-
-    if (!scope)
-        return m_ident.isEmpty()
-            ? emitThrowError(generator, SyntaxError, "Invalid continue statement.")
-            : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+    ASSERT(scope);
 
     generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth());
     return dst;
@@ -1616,11 +1645,7 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
     
     LabelScope* scope = generator.breakTarget(m_ident);
-    
-    if (!scope)
-        return m_ident.isEmpty()
-            ? emitThrowError(generator, SyntaxError, "Invalid break statement.")
-            : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident);
+    ASSERT(scope);
 
     generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth());
     return dst;
@@ -1631,8 +1656,7 @@ RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
-    if (generator.codeType() != FunctionCode)
-        return emitThrowError(generator, SyntaxError, "Invalid return statement.");
+    ASSERT(generator.codeType() == FunctionCode);
 
     if (dst == generator.ignoredResult())
         dst = 0;
@@ -1708,8 +1732,8 @@ static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>&
                 break;
             }
             const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring();
-            if (singleCharacterSwitch &= value.size() == 1) {
-                int32_t intVal = value.rep()->characters()[0];
+            if (singleCharacterSwitch &= value.length() == 1) {
+                int32_t intVal = value.impl()->characters()[0];
                 if (intVal < min_num)
                     min_num = intVal;
                 if (intVal > max_num)
@@ -1837,8 +1861,7 @@ RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
 {
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
 
-    if (generator.breakTarget(m_name))
-        return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name);
+    ASSERT(!generator.breakTarget(m_name));
 
     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name);
     RegisterID* r0 = generator.emitNode(dst, m_statement);
@@ -1868,8 +1891,6 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
     // NOTE: The catch and finally blocks must be labeled explicitly, so the
     // optimizer knows they may be jumped to from anywhere.
 
-    IncreaseEmitNodeDepth stackGuard(generator);
-
     generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
 
     RefPtr<Label> tryStartLabel = generator.newLabel();
@@ -1979,16 +2000,38 @@ RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, Registe
 {
     generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
     emitStatementsBytecode(generator, generator.ignoredResult());
+
     StatementNode* singleStatement = this->singleStatement();
+    ReturnNode* returnNode = 0;
+
+    // Check for a return statement at the end of a function composed of a single block.
     if (singleStatement && singleStatement->isBlock()) {
         StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement();
         if (lastStatementInBlock && lastStatementInBlock->isReturnNode())
-            return 0;
+            returnNode = static_cast<ReturnNode*>(lastStatementInBlock);
+    }
+
+    // If there is no return we must automatically insert one.
+    if (!returnNode) {
+        RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
+        generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
+        generator.emitReturn(r0);
+        return 0;
+    }
+
+    // If there is a return statment, and it is the only statement in the function, check if this is a numeric compare.
+    if (static_cast<BlockNode*>(singleStatement)->singleStatement()) {
+        ExpressionNode* returnValueExpression = returnNode->value();
+        if (returnValueExpression && returnValueExpression->isSubtract()) {
+            ExpressionNode* lhsExpression = static_cast<SubNode*>(returnValueExpression)->lhs();
+            ExpressionNode* rhsExpression = static_cast<SubNode*>(returnValueExpression)->rhs();
+            if (lhsExpression->isResolveNode() && rhsExpression->isResolveNode()) {
+                generator.setIsNumericCompareFunction(generator.argumentNumberFor(static_cast<ResolveNode*>(lhsExpression)->identifier()) == 1
+                    && generator.argumentNumberFor(static_cast<ResolveNode*>(rhsExpression)->identifier()) == 2);
+            }
+        }
     }
 
-    RegisterID* r0 = generator.emitLoad(0, jsUndefined());
-    generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine());
-    generator.emitReturn(r0);
     return 0;
 }
 
index 3532ad802cb220ae76a6230152080b999ceb8487..78d49d29086366fd7f9b7e9ae36cac736892cbce 100644 (file)
 #define RegisterID_h
 
 #include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
 
-    class RegisterID : public Noncopyable {
+    class RegisterID {
+        WTF_MAKE_NONCOPYABLE(RegisterID);
     public:
         RegisterID()
             : m_refCount(0)
index 9810885d73490b8f503221e29af9c776c059e5d7..394bba56a452ba761d05dc50f66ae35c056e5321 100644 (file)
--- a/config.h
+++ b/config.h
  */
 
 #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
+#ifdef BUILDING_WITH_CMAKE
+#include "cmakeconfig.h"
+#else
 #include "autotoolsconfig.h"
 #endif
+#endif
 
 #include <wtf/Platform.h>
 
+/* See note in wtf/Platform.h for more info on EXPORT_MACROS. */
+#if USE(EXPORT_MACROS)
+
+#include <wtf/ExportMacros.h>
+
+#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
+#define WTF_EXPORT_PRIVATE WTF_EXPORT
+#define JS_EXPORT_PRIVATE WTF_EXPORT
+#else
+#define WTF_EXPORT_PRIVATE WTF_IMPORT
+#define JS_EXPORT_PRIVATE WTF_IMPORT
+#endif
+
+#define JS_EXPORTDATA JS_EXPORT_PRIVATE
+#define JS_EXPORTCLASS JS_EXPORT_PRIVATE
+
+#else /* !USE(EXPORT_MACROS) */
+
 #if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC)
 #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF)
 #define JS_EXPORTDATA __declspec(dllexport)
 #define JS_EXPORTCLASS
 #endif
 
+#define WTF_EXPORT_PRIVATE
+#define JS_EXPORT_PRIVATE
+
+#endif /* USE(EXPORT_MACROS) */
+
 #if OS(WINDOWS)
 
 // If we don't define these, they get defined in windef.h. 
 
 #endif
 
+#if OS(UNIX) || OS(WINDOWS)
+#define WTF_USE_OS_RANDOMNESS 1
+#endif
+
 #if OS(FREEBSD) || OS(OPENBSD)
 #define HAVE_PTHREAD_NP_H 1
 #endif
index 6078f974f7b0e8ab9a5e65d0183569cd554c8ab1..59b574aaf561fe8e0f0000fe027fcd0453cc414b 100755 (executable)
@@ -284,6 +284,9 @@ sub output() {
         if ($key eq "pow") {
             $thunkGenerator = "powThunkGenerator";
         }
+        if ($key eq "fromCharCode") {
+            $thunkGenerator = "fromCharCodeThunkGenerator";
+        }
         print "   { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue THUNK_GENERATOR($thunkGenerator) },\n";
         $i++;
     }
index 4d510ea2fd6899b728daa38056632a6516f18212..f0fcb53b03f52e1100bb91c4d8b286f34479b46e 100644 (file)
@@ -22,19 +22,16 @@ use strict;
 use File::Basename;
 use Getopt::Long;
 
-my $usage = basename($0) . " --prefix prefix [--offset offset] file";
+my $usage = basename($0) . " --prefix prefix file";
 
 my $rtype_template = quotemeta("#rtype#");
-my $offset_template = quotemeta("#offset#");
 my $op_template = quotemeta("#op#");
 
 my $prefix;
-my $offset = 32;
 my $file;
 
 my $getOptionsResult = GetOptions(
-    'prefix=s' => \$prefix,
-    'offset=i' => \$offset
+    'prefix=s' => \$prefix
 );
 
 $file = $ARGV[0];
@@ -42,6 +39,7 @@ $file = $ARGV[0];
 die "$usage\n" unless ($prefix and $file);
 
 my $stub_template = "";
+my $output_end = "";
 my $stub = "";
 
 my $rtype = "";
@@ -51,14 +49,20 @@ print STDERR "Creating JIT stubs for $file \n";
 open(IN, $file) or die "No such file $file";
 
 while ( $_ = <IN> ) {
+    if ( /^$prefix\_BEGIN\((.*)\)/ ) {
+        $stub = $1;
+        print $stub . "\n";
+    }
     if ( /^$prefix\((.*)\)/ ) {
         $stub_template .= $1 . "\n";
     }
+    if ( /^$prefix\_END\((.*)\)/ ) {
+        $output_end .= $1 . "\n";
+    }
     if ( /^DEFINE_STUB_FUNCTION\((.*), (.*)\)/ ) {
         $stub = $stub_template;
         $rtype = quotemeta($1);
         $op = quotemeta($2);
-        $stub =~ s/$offset_template/$offset/g;
         $stub =~ s/$rtype_template/$rtype/g;
         $stub =~ s/$op_template/$op/g;
         $stub =~ s/\\\*/\*/g;
@@ -66,4 +70,6 @@ while ( $_ = <IN> ) {
     }
 }
 
+print $output_end;
+
 close(IN);
index b436eee11fc572419defff4b6035a5d0c496f531..bd799ba0441cd49d1e19f30e1c678825966771e9 100644 (file)
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
+import sys
+
 types = {
     "wordchar": { "UseTable" : True, "data": ['_', ('0','9'), ('A', 'Z'), ('a','z')]},
     "nonwordchar": { "UseTable" : True, "Inverse": "wordchar", "data": ['`', (0, ord('0') - 1), (ord('9') + 1, ord('A') - 1), (ord('Z') + 1, ord('_') - 1), (ord('z') + 1, 0xffff)]},
     "newline": { "UseTable" : False, "data": ['\n', '\r', 0x2028, 0x2029]},
-    "spaces": { "UseTable" : True, "data": [' ', ('\t', '\r'), 0xa0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, (0x2000, 0x200a)]},
-    "nonspaces": { "UseTable" : True, "Inverse": "spaces", "data": [(0, ord('\t') - 1), (ord('\r') + 1, ord(' ') - 1), (ord(' ') + 1, 0x009f), (0x00a1, 0x167f), (0x1681, 0x180d), (0x180f, 0x1fff), (0x200b, 0x2027), (0x202a, 0x202e), (0x2030, 0x205e), (0x2060, 0x2fff), (0x3001, 0xffff)]},
+    "spaces": { "UseTable" : True, "data": [' ', ('\t', '\r'), 0xa0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, (0x2000, 0x200a), 0xfeff]},
+    "nonspaces": { "UseTable" : True, "Inverse": "spaces", "data": [(0, ord('\t') - 1), (ord('\r') + 1, ord(' ') - 1), (ord(' ') + 1, 0x009f), (0x00a1, 0x167f), (0x1681, 0x180d), (0x180f, 0x1fff), (0x200b, 0x2027), (0x202a, 0x202e), (0x2030, 0x205e), (0x2060, 0x2fff), (0x3001, 0xfefe), (0xff00, 0xffff)]},
     "digits": { "UseTable" : False, "data": [('0', '9')]},
     "nondigits": { "UseTable" : False, "Inverse": "digits", "data": [(0, ord('0') - 1), (ord('9') + 1, 0xffff)] }
 }
 entriesPerLine = 50
 arrays = "";
 functions = "";
+emitTables = (len(sys.argv) < 2 or sys.argv[1] != "--no-tables")
 
 for name, classes in types.items():
     ranges = [];
@@ -54,7 +57,7 @@ for name, classes in types.items():
             ranges.append((min,max))
     ranges.sort();
     
-    if classes["UseTable"] and (not "Inverse" in classes):
+    if emitTables and classes["UseTable"] and (not "Inverse" in classes):
         array = ("static const char _%sData[65536] = {\n" % name);
         i = 0
         for (min,max) in ranges:
@@ -85,7 +88,7 @@ for name, classes in types.items():
     function = "";
     function += ("CharacterClass* %sCreate()\n" % name)
     function += ("{\n")
-    if classes["UseTable"]:
+    if emitTables and classes["UseTable"]:
         if "Inverse" in classes:
             function += ("    CharacterClass* characterClass = new CharacterClass(CharacterClassTable::create(_%sData, true));\n" % (classes["Inverse"]))
         else:
@@ -107,6 +110,12 @@ for name, classes in types.items():
     function += ("}\n\n")
     functions += function
 
-print(arrays)
-print(functions)
+if (len(sys.argv) > 1):
+    f = open(sys.argv[-1], "w")
+    f.write(arrays)
+    f.write(functions)
+    f.close()
+else:
+    print(arrays)
+    print(functions)
 
index 39489e8e37087a9e2d2cf6f45057abf0a391c7e4..64f60029d9b6d3a55e6f1047a9f1813520042731 100644 (file)
@@ -22,7 +22,6 @@
 #include "config.h"
 #include "Debugger.h"
 
-#include "CollectorHeapIterator.h"
 #include "Error.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "Parser.h"
 #include "Protect.h"
 
+namespace {
+
+using namespace JSC;
+
+class Recompiler {
+public:
+    Recompiler(Debugger*);
+    ~Recompiler();
+    void operator()(JSCell*);
+
+private:
+    typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
+    typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
+    
+    Debugger* m_debugger;
+    FunctionExecutableSet m_functionExecutables;
+    SourceProviderMap m_sourceProviders;
+};
+
+inline Recompiler::Recompiler(Debugger* debugger)
+    : m_debugger(debugger)
+{
+}
+
+inline Recompiler::~Recompiler()
+{
+    // Call sourceParsed() after reparsing all functions because it will execute
+    // JavaScript in the inspector.
+    SourceProviderMap::const_iterator end = m_sourceProviders.end();
+    for (SourceProviderMap::const_iterator iter = m_sourceProviders.begin(); iter != end; ++iter)
+        m_debugger->sourceParsed(iter->second, iter->first, -1, UString());
+}
+
+inline void Recompiler::operator()(JSCell* cell)
+{
+    if (!cell->inherits(&JSFunction::s_info))
+        return;
+
+    JSFunction* function = asFunction(cell);
+    if (function->executable()->isHostFunction())
+        return;
+
+    FunctionExecutable* executable = function->jsExecutable();
+
+    // Check if the function is already in the set - if so,
+    // we've already retranslated it, nothing to do here.
+    if (!m_functionExecutables.add(executable).second)
+        return;
+
+    ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec();
+    executable->discardCode();
+    if (m_debugger == function->scope()->globalObject->debugger())
+        m_sourceProviders.add(executable->source().provider(), exec);
+}
+
+} // namespace
+
 namespace JSC {
 
 Debugger::~Debugger()
@@ -61,52 +117,29 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
     if (globalData->dynamicGlobalObject)
         return;
 
-    typedef HashSet<FunctionExecutable*> FunctionExecutableSet;
-    typedef HashMap<SourceProvider*, ExecState*> SourceProviderMap;
-
-    FunctionExecutableSet functionExecutables;
-    SourceProviderMap sourceProviders;
-
-    LiveObjectIterator it = globalData->heap.primaryHeapBegin();
-    LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd();
-    for ( ; it != heapEnd; ++it) {
-        if (!(*it)->inherits(&JSFunction::info))
-            continue;
-
-        JSFunction* function = asFunction(*it);
-        if (function->executable()->isHostFunction())
-            continue;
-
-        FunctionExecutable* executable = function->jsExecutable();
-
-        // Check if the function is already in the set - if so,
-        // we've already retranslated it, nothing to do here.
-        if (!functionExecutables.add(executable).second)
-            continue;
-
-        ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
-        executable->recompile();
-        if (function->scope().globalObject()->debugger() == this)
-            sourceProviders.add(executable->source().provider(), exec);
-    }
-
-    // Call sourceParsed() after reparsing all functions because it will execute
-    // JavaScript in the inspector.
-    SourceProviderMap::const_iterator end = sourceProviders.end();
-    for (SourceProviderMap::const_iterator iter = sourceProviders.begin(); iter != end; ++iter)
-        sourceParsed(iter->second, SourceCode(iter->first), -1, UString());
+    Recompiler recompiler(this);
+    globalData->heap.forEach(recompiler);
 }
 
 JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSGlobalObject* globalObject)
 {
     CallFrame* globalCallFrame = globalObject->globalExec();
+    JSGlobalData& globalData = globalObject->globalData();
 
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script));
-    JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain());
-    if (error)
-        return error;
+    EvalExecutable* eval = EvalExecutable::create(globalCallFrame, makeSource(script), false);
+    if (!eval) {
+        exception = globalData.exception;
+        globalData.exception = JSValue();
+        return exception;
+    }
 
-    return globalObject->globalData()->interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
+    JSValue result = globalData.interpreter->execute(eval, globalCallFrame, globalObject, globalCallFrame->scopeChain());
+    if (globalData.exception) {
+        exception = globalData.exception;
+        globalData.exception = JSValue();
+    }
+    ASSERT(result);
+    return result;
 }
 
 } // namespace JSC
index 3b9bec4ac924f499155cc87836de142306c9cf0f..ec5cf37374e09b490ff96c10ff5ed4bdcedced79 100644 (file)
@@ -31,7 +31,7 @@ namespace JSC {
     class JSGlobalData;
     class JSGlobalObject;
     class JSValue;
-    class SourceCode;
+    class SourceProvider;
     class UString;
 
     class Debugger {
@@ -41,7 +41,7 @@ namespace JSC {
         void attach(JSGlobalObject*);
         virtual void detach(JSGlobalObject*);
 
-        virtual void sourceParsed(ExecState*, const SourceCode&, int errorLineNumber, const UString& errorMessage) = 0;
+        virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const UString& errorMessage) = 0;
         virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, bool hasHandler) = 0;
         virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
         virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0;
index 0444d23d204f8318a392555c5c57c56906a3b914..8711b5ce93df9204118cd780c59219e1f1c5ce84 100644 (file)
 
 namespace JSC {
 
-DebuggerActivation::DebuggerActivation(JSObject* activation)
-    : JSObject(DebuggerActivation::createStructure(jsNull()))
+DebuggerActivation::DebuggerActivation(JSGlobalData& globalData, JSObject* activation)
+    : JSNonFinalObject(globalData, globalData.debuggerActivationStructure.get())
 {
     ASSERT(activation);
     ASSERT(activation->isActivationObject());
-    m_activation = static_cast<JSActivation*>(activation);
+    m_activation.set(globalData, this, static_cast<JSActivation*>(activation));
 }
 
-void DebuggerActivation::markChildren(MarkStack& markStack)
+void DebuggerActivation::visitChildren(SlotVisitor& visitor)
 {
-    JSObject::markChildren(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSObject::visitChildren(visitor);
 
     if (m_activation)
-        markStack.append(m_activation);
+        visitor.append(&m_activation);
 }
 
 UString DebuggerActivation::className() const
index 392701741ba764b3f44392da99c7006dcc5c4c5d..574986a0fd662f681f3a06eb4be20e7dc0aff3a9 100644 (file)
@@ -32,11 +32,11 @@ namespace JSC {
 
     class JSActivation;
 
-    class DebuggerActivation : public JSObject {
+    class DebuggerActivation : public JSNonFinalObject {
     public:
-        DebuggerActivation(JSObject*);
+        DebuggerActivation(JSGlobalData&, JSObject*);
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
         virtual UString className() const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
@@ -49,16 +49,16 @@ namespace JSC {
         virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
         virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
 
     private:
-        JSActivation* m_activation;
+        WriteBarrier<JSActivation> m_activation;
     };
 
 } // namespace JSC
index a734b1d0e413db8c151ccefc745e920af9c6e630..08fba4a6b4cb8a00991d55749907f5e2f8076155 100644 (file)
@@ -44,10 +44,10 @@ const UString* DebuggerCallFrame::functionName() const
     if (!m_callFrame->callee())
         return 0;
 
-    JSFunction* function = asFunction(m_callFrame->callee());
-    if (!function)
+    JSObject* function = m_callFrame->callee();
+    if (!function || !function->inherits(&JSFunction::s_info))
         return 0;
-    return &function->name(m_callFrame);
+    return &asFunction(function)->name(m_callFrame);
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
@@ -55,13 +55,11 @@ UString DebuggerCallFrame::calculatedFunctionName() const
     if (!m_callFrame->codeBlock())
         return UString();
 
-    if (!m_callFrame->callee())
+    JSObject* function = m_callFrame->callee();
+    if (!function || !function->inherits(&JSFunction::s_info))
         return UString();
 
-    JSFunction* function = asFunction(m_callFrame->callee());
-    if (!function)
-        return UString();
-    return function->calculatedDisplayName(m_callFrame);
+    return asFunction(function)->calculatedDisplayName(m_callFrame);
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
@@ -74,23 +72,36 @@ DebuggerCallFrame::Type DebuggerCallFrame::type() const
 
 JSObject* DebuggerCallFrame::thisObject() const
 {
-    if (!m_callFrame->codeBlock())
+    CodeBlock* codeBlock = m_callFrame->codeBlock();
+    if (!codeBlock)
+        return 0;
+
+    JSValue thisValue = m_callFrame->uncheckedR(codeBlock->thisRegister()).jsValue();
+    if (!thisValue.isObject())
         return 0;
 
-    return asObject(m_callFrame->thisValue());
+    return asObject(thisValue);
 }
 
 JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) const
 {
     if (!m_callFrame->codeBlock())
         return JSValue();
-
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script));
-    JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain());
-    if (error)
-        return error;
-
-    return m_callFrame->scopeChain()->globalData->interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
+    
+    JSGlobalData& globalData = m_callFrame->globalData();
+    EvalExecutable* eval = EvalExecutable::create(m_callFrame, makeSource(script), m_callFrame->codeBlock()->isStrictMode());
+    if (globalData.exception) {
+        exception = globalData.exception;
+        globalData.exception = JSValue();
+    }
+
+    JSValue result = globalData.interpreter->execute(eval, m_callFrame, thisObject(), m_callFrame->scopeChain());
+    if (globalData.exception) {
+        exception = globalData.exception;
+        globalData.exception = JSValue();
+    }
+    ASSERT(result);
+    return result;
 }
 
 } // namespace JSC
index 9d377ef97a0a2db3aaac32285ea6cf011d7e16b8..f6b415cecbd09462d3cd3a49c992dcb766b7ab30 100644 (file)
@@ -49,7 +49,7 @@ namespace JSC {
         }
 
         JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
-        const ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); }
+        ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); }
         const UString* functionName() const;
         UString calculatedFunctionName() const;
         Type type() const;
diff --git a/dfg/DFGAliasTracker.h b/dfg/DFGAliasTracker.h
new file mode 100644 (file)
index 0000000..8710169
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2011 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 DFGAliasTracker_h
+#define DFGAliasTracker_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGGraph.h>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+// === AliasTracker ===
+//
+// This class id used to detect aliasing property accesses, which we may
+// be able to speculatively optimize (for example removing redundant loads
+// where we know a getter will not be called, or optimizing puts to arrays
+// where we know the value being written to in within length and is not a
+// hole value). In time, this should be more than a 1-deep buffer!
+class AliasTracker {
+public:
+    AliasTracker(Graph& graph)
+        : m_graph(graph)
+        , m_candidateAliasGetByVal(NoNode)
+    {
+    }
+
+    NodeIndex lookupGetByVal(NodeIndex base, NodeIndex property)
+    {
+        // Try to detect situations where a GetByVal follows another GetByVal to the same
+        // property; in these cases, we may be able to omit the subsequent get on the
+        // speculative path, where we know conditions hold to make this safe (for example,
+        // on the speculative path we will not have allowed getter access).
+        if (m_candidateAliasGetByVal != NoNode) {
+            Node& possibleAlias = m_graph[m_candidateAliasGetByVal];
+            ASSERT(possibleAlias.op == GetByVal);
+            // This check ensures the accesses alias, provided that the subscript is an
+            // integer index (this is good enough; the speculative path will only generate
+            // optimized accesses to handle integer subscripts).
+            if (possibleAlias.child1 == base && equalIgnoringLaterNumericConversion(possibleAlias.child2, property))
+                return m_candidateAliasGetByVal;
+        }
+        return NoNode;
+    }
+
+    void recordGetByVal(NodeIndex getByVal)
+    {
+        m_candidateAliasGetByVal = getByVal;
+    }
+
+    void recordPutByVal(NodeIndex putByVal)
+    {
+        ASSERT_UNUSED(putByVal, m_graph[putByVal].op == PutByVal || m_graph[putByVal].op == PutByValAlias);
+        m_candidateAliasGetByVal = NoNode;
+    }
+
+    void recordGetById(NodeIndex getById)
+    {
+        ASSERT_UNUSED(getById, m_graph[getById].op == GetById);
+        m_candidateAliasGetByVal = NoNode;
+    }
+
+    void recordPutById(NodeIndex putById)
+    {
+        ASSERT_UNUSED(putById, m_graph[putById].op == PutById);
+        m_candidateAliasGetByVal = NoNode;
+    }
+
+    void recordPutByIdDirect(NodeIndex putByVal)
+    {
+        ASSERT_UNUSED(putByVal, m_graph[putByVal].op == PutByIdDirect);
+        m_candidateAliasGetByVal = NoNode;
+    }
+
+private:
+    // This method returns true for arguments:
+    //   - (X, X)
+    //   - (X, ValueToNumber(X))
+    //   - (X, ValueToInt32(X))
+    //   - (X, NumberToInt32(X))
+    bool equalIgnoringLaterNumericConversion(NodeIndex op1, NodeIndex op2)
+    {
+        if (op1 == op2)
+            return true;
+        Node& node2 = m_graph[op2];
+        return (node2.op == ValueToNumber || node2.op == ValueToInt32 || node2.op == NumberToInt32) && op1 == node2.child1;
+    }
+
+    // The graph, to look up potentially aliasing nodes.
+    Graph& m_graph;
+    // Currently a 1-deep buffer!
+    NodeIndex m_candidateAliasGetByVal;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGByteCodeParser.cpp b/dfg/DFGByteCodeParser.cpp
new file mode 100644 (file)
index 0000000..7c333de
--- /dev/null
@@ -0,0 +1,1198 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGByteCodeParser.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAliasTracker.h"
+#include "DFGScoreBoard.h"
+#include "CodeBlock.h"
+
+namespace JSC { namespace DFG {
+
+#if ENABLE(DFG_JIT_RESTRICTIONS)
+// FIXME: Temporarily disable arithmetic, until we fix associated performance regressions.
+#define ARITHMETIC_OP() m_parseFailed = true
+#else
+#define ARITHMETIC_OP() ((void)0)
+#endif
+
+// === ByteCodeParser ===
+//
+// This class is used to compile the dataflow graph from a CodeBlock.
+class ByteCodeParser {
+public:
+    ByteCodeParser(JSGlobalData* globalData, CodeBlock* codeBlock, Graph& graph)
+        : m_globalData(globalData)
+        , m_codeBlock(codeBlock)
+        , m_graph(graph)
+        , m_currentIndex(0)
+        , m_parseFailed(false)
+        , m_constantUndefined(UINT_MAX)
+        , m_constantNull(UINT_MAX)
+        , m_constant1(UINT_MAX)
+        , m_constants(codeBlock->numberOfConstantRegisters())
+        , m_numArguments(codeBlock->m_numParameters)
+        , m_numLocals(codeBlock->m_numCalleeRegisters)
+        , m_preservedVars(codeBlock->m_numVars)
+    {
+    }
+
+    // Parse a full CodeBlock of bytecode.
+    bool parse();
+
+private:
+    // Parse a single basic block of bytecode instructions.
+    bool parseBlock(unsigned limit);
+    // Setup predecessor links in the graph's BasicBlocks.
+    void setupPredecessors();
+    // Link GetLocal & SetLocal nodes, to ensure live values are generated.
+    enum PhiStackType {
+        LocalPhiStack,
+        ArgumentPhiStack
+    };
+    template<PhiStackType stackType>
+    void processPhiStack();
+    // Add spill locations to nodes.
+    void allocateVirtualRegisters();
+
+    // Get/Set the operands/result of a bytecode instruction.
+    NodeIndex get(int operand)
+    {
+        // Is this a constant?
+        if (operand >= FirstConstantRegisterIndex) {
+            unsigned constant = operand - FirstConstantRegisterIndex;
+            ASSERT(constant < m_constants.size());
+            return getJSConstant(constant);
+        }
+
+        // Is this an argument?
+        if (operandIsArgument(operand))
+            return getArgument(operand);
+
+        // Must be a local.
+        return getLocal((unsigned)operand);
+    }
+    void set(int operand, NodeIndex value, PredictedType prediction = PredictNone)
+    {
+        m_graph.predict(operand, prediction);
+
+        // Is this an argument?
+        if (operandIsArgument(operand)) {
+            setArgument(operand, value);
+            return;
+        }
+
+        // Must be a local.
+        setLocal((unsigned)operand, value);
+    }
+
+    // Used in implementing get/set, above, where the operand is a local variable.
+    NodeIndex getLocal(unsigned operand)
+    {
+        NodeIndex nodeIndex = m_currentBlock->m_locals[operand].value;
+
+        if (nodeIndex != NoNode) {
+            Node& node = m_graph[nodeIndex];
+            if (node.op == GetLocal)
+                return nodeIndex;
+            ASSERT(node.op == SetLocal);
+            return node.child1;
+        }
+
+        // Check for reads of temporaries from prior blocks,
+        // expand m_preservedVars to cover these.
+        m_preservedVars = std::max(m_preservedVars, operand + 1);
+
+        NodeIndex phi = addToGraph(Phi);
+        m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
+        nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
+        m_currentBlock->m_locals[operand].value = nodeIndex;
+        return nodeIndex;
+    }
+    void setLocal(unsigned operand, NodeIndex value)
+    {
+        m_currentBlock->m_locals[operand].value = addToGraph(SetLocal, OpInfo(operand), value);
+    }
+
+    // Used in implementing get/set, above, where the operand is an argument.
+    NodeIndex getArgument(unsigned operand)
+    {
+        unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
+        ASSERT(argument < m_numArguments);
+
+        NodeIndex nodeIndex = m_currentBlock->m_arguments[argument].value;
+
+        if (nodeIndex != NoNode) {
+            Node& node = m_graph[nodeIndex];
+            if (node.op == GetLocal)
+                return nodeIndex;
+            ASSERT(node.op == SetLocal);
+            return node.child1;
+        }
+
+        NodeIndex phi = addToGraph(Phi);
+        m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
+        nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
+        m_currentBlock->m_arguments[argument].value = nodeIndex;
+        return nodeIndex;
+    }
+    void setArgument(int operand, NodeIndex value)
+    {
+        unsigned argument = operand + m_codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize;
+        ASSERT(argument < m_numArguments);
+
+        m_currentBlock->m_arguments[argument].value = addToGraph(SetLocal, OpInfo(operand), value);
+    }
+
+    // Get an operand, and perform a ToInt32/ToNumber conversion on it.
+    NodeIndex getToInt32(int operand)
+    {
+        // Avoid wastefully adding a JSConstant node to the graph, only to
+        // replace it with a Int32Constant (which is what would happen if
+        // we called 'toInt32(get(operand))' in this case).
+        if (operand >= FirstConstantRegisterIndex) {
+            JSValue v = m_codeBlock->getConstant(operand);
+            if (v.isInt32())
+                return getInt32Constant(v.asInt32(), operand - FirstConstantRegisterIndex);
+        }
+        return toInt32(get(operand));
+    }
+    NodeIndex getToNumber(int operand)
+    {
+        // Avoid wastefully adding a JSConstant node to the graph, only to
+        // replace it with a DoubleConstant (which is what would happen if
+        // we called 'toNumber(get(operand))' in this case).
+        if (operand >= FirstConstantRegisterIndex) {
+            JSValue v = m_codeBlock->getConstant(operand);
+            if (v.isNumber())
+                return getDoubleConstant(v.uncheckedGetNumber(), operand - FirstConstantRegisterIndex);
+        }
+        return toNumber(get(operand));
+    }
+
+    // Perform an ES5 ToInt32 operation - returns a node of type NodeResultInt32.
+    NodeIndex toInt32(NodeIndex index)
+    {
+        Node& node = m_graph[index];
+
+        if (node.hasInt32Result())
+            return index;
+
+        if (node.hasDoubleResult()) {
+            if (node.op == DoubleConstant)
+                return getInt32Constant(JSC::toInt32(valueOfDoubleConstant(index)), node.constantNumber());
+            // 'NumberToInt32(Int32ToNumber(X))' == X, and 'NumberToInt32(UInt32ToNumber(X)) == X'
+            if (node.op == Int32ToNumber || node.op == UInt32ToNumber)
+                return node.child1;
+
+            // We unique NumberToInt32 nodes in a map to prevent duplicate conversions.
+            pair<UnaryOpMap::iterator, bool> result = m_numberToInt32Nodes.add(index, NoNode);
+            // Either we added a new value, or the existing value in the map is non-zero.
+            ASSERT(result.second == (result.first->second == NoNode));
+            if (result.second)
+                result.first->second = addToGraph(NumberToInt32, index);
+            return result.first->second;
+        }
+
+        // Check for numeric constants boxed as JSValues.
+        if (node.op == JSConstant) {
+            JSValue v = valueOfJSConstant(index);
+            if (v.isInt32())
+                return getInt32Constant(v.asInt32(), node.constantNumber());
+            if (v.isNumber())
+                return getInt32Constant(JSC::toInt32(v.uncheckedGetNumber()), node.constantNumber());
+        }
+
+        return addToGraph(ValueToInt32, index);
+    }
+
+    // Perform an ES5 ToNumber operation - returns a node of type NodeResultDouble.
+    NodeIndex toNumber(NodeIndex index)
+    {
+        Node& node = m_graph[index];
+
+        if (node.hasDoubleResult())
+            return index;
+
+        if (node.hasInt32Result()) {
+            if (node.op == Int32Constant)
+                return getDoubleConstant(valueOfInt32Constant(index), node.constantNumber());
+
+            // We unique Int32ToNumber nodes in a map to prevent duplicate conversions.
+            pair<UnaryOpMap::iterator, bool> result = m_int32ToNumberNodes.add(index, NoNode);
+            // Either we added a new value, or the existing value in the map is non-zero.
+            ASSERT(result.second == (result.first->second == NoNode));
+            if (result.second)
+                result.first->second = addToGraph(Int32ToNumber, index);
+            return result.first->second;
+        }
+
+        if (node.op == JSConstant) {
+            JSValue v = valueOfJSConstant(index);
+            if (v.isNumber())
+                return getDoubleConstant(v.uncheckedGetNumber(), node.constantNumber());
+        }
+
+        return addToGraph(ValueToNumber, index);
+    }
+
+
+    // Used in implementing get, above, where the operand is a constant.
+    NodeIndex getInt32Constant(int32_t value, unsigned constant)
+    {
+        NodeIndex index = m_constants[constant].asInt32;
+        if (index != NoNode)
+            return index;
+        NodeIndex resultIndex = addToGraph(Int32Constant, OpInfo(constant));
+        m_graph[resultIndex].setInt32Constant(value);
+        m_constants[constant].asInt32 = resultIndex;
+        return resultIndex;
+    }
+    NodeIndex getDoubleConstant(double value, unsigned constant)
+    {
+        NodeIndex index = m_constants[constant].asNumeric;
+        if (index != NoNode)
+            return index;
+        NodeIndex resultIndex = addToGraph(DoubleConstant, OpInfo(constant));
+        m_graph[resultIndex].setDoubleConstant(value);
+        m_constants[constant].asNumeric = resultIndex;
+        return resultIndex;
+    }
+    NodeIndex getJSConstant(unsigned constant)
+    {
+        NodeIndex index = m_constants[constant].asJSValue;
+        if (index != NoNode)
+            return index;
+
+        NodeIndex resultIndex = addToGraph(JSConstant, OpInfo(constant));
+        m_constants[constant].asJSValue = resultIndex;
+        return resultIndex;
+    }
+
+    // Helper functions to get/set the this value.
+    NodeIndex getThis()
+    {
+        return getArgument(m_codeBlock->thisRegister());
+    }
+    void setThis(NodeIndex value)
+    {
+        setArgument(m_codeBlock->thisRegister(), value);
+    }
+
+    // Convenience methods for checking nodes for constants.
+    bool isInt32Constant(NodeIndex index)
+    {
+        return m_graph[index].op == Int32Constant;
+    }
+    bool isDoubleConstant(NodeIndex index)
+    {
+        return m_graph[index].op == DoubleConstant;
+    }
+    bool isJSConstant(NodeIndex index)
+    {
+        return m_graph[index].op == JSConstant;
+    }
+
+    // Convenience methods for getting constant values.
+    int32_t valueOfInt32Constant(NodeIndex index)
+    {
+        ASSERT(isInt32Constant(index));
+        return m_graph[index].int32Constant();
+    }
+    double valueOfDoubleConstant(NodeIndex index)
+    {
+        ASSERT(isDoubleConstant(index));
+        return m_graph[index].numericConstant();
+    }
+    JSValue valueOfJSConstant(NodeIndex index)
+    {
+        ASSERT(isJSConstant(index));
+        return m_codeBlock->getConstant(FirstConstantRegisterIndex + m_graph[index].constantNumber());
+    }
+
+    // This method returns a JSConstant with the value 'undefined'.
+    NodeIndex constantUndefined()
+    {
+        // Has m_constantUndefined been set up yet?
+        if (m_constantUndefined == UINT_MAX) {
+            // Search the constant pool for undefined, if we find it, we can just reuse this!
+            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
+            for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) {
+                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined);
+                if (testMe.isUndefined())
+                    return getJSConstant(m_constantUndefined);
+            }
+
+            // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.
+            ASSERT(m_constants.size() == numberOfConstants);
+            m_codeBlock->addConstant(jsUndefined());
+            m_constants.append(ConstantRecord());
+            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+        }
+
+        // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.
+        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined());
+        return getJSConstant(m_constantUndefined);
+    }
+
+    // This method returns a JSConstant with the value 'null'.
+    NodeIndex constantNull()
+    {
+        // Has m_constantNull been set up yet?
+        if (m_constantNull == UINT_MAX) {
+            // Search the constant pool for null, if we find it, we can just reuse this!
+            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
+            for (m_constantNull = 0; m_constantNull < numberOfConstants; ++m_constantNull) {
+                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull);
+                if (testMe.isNull())
+                    return getJSConstant(m_constantNull);
+            }
+
+            // Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.
+            ASSERT(m_constants.size() == numberOfConstants);
+            m_codeBlock->addConstant(jsNull());
+            m_constants.append(ConstantRecord());
+            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+        }
+
+        // m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.
+        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull).isNull());
+        return getJSConstant(m_constantNull);
+    }
+
+    // This method returns a DoubleConstant with the value 1.
+    NodeIndex one()
+    {
+        // Has m_constant1 been set up yet?
+        if (m_constant1 == UINT_MAX) {
+            // Search the constant pool for the value 1, if we find it, we can just reuse this!
+            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
+            for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
+                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
+                if (testMe.isInt32() && testMe.asInt32() == 1)
+                    return getDoubleConstant(1, m_constant1);
+            }
+
+            // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
+            ASSERT(m_constants.size() == numberOfConstants);
+            m_codeBlock->addConstant(jsNumber(1));
+            m_constants.append(ConstantRecord());
+            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+        }
+
+        // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
+        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());
+        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);
+        return getDoubleConstant(1, m_constant1);
+    }
+
+
+    // These methods create a node and add it to the graph. If nodes of this type are
+    // 'mustGenerate' then the node  will implicitly be ref'ed to ensure generation.
+    NodeIndex addToGraph(NodeType op, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+    {
+        NodeIndex resultIndex = (NodeIndex)m_graph.size();
+        m_graph.append(Node(op, m_currentIndex, child1, child2, child3));
+
+        if (op & NodeMustGenerate)
+            m_graph.ref(resultIndex);
+        return resultIndex;
+    }
+    NodeIndex addToGraph(NodeType op, OpInfo info, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+    {
+        NodeIndex resultIndex = (NodeIndex)m_graph.size();
+        m_graph.append(Node(op, m_currentIndex, info, child1, child2, child3));
+
+        if (op & NodeMustGenerate)
+            m_graph.ref(resultIndex);
+        return resultIndex;
+    }
+    NodeIndex addToGraph(NodeType op, OpInfo info1, OpInfo info2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+    {
+        NodeIndex resultIndex = (NodeIndex)m_graph.size();
+        m_graph.append(Node(op, m_currentIndex, info1, info2, child1, child2, child3));
+
+        if (op & NodeMustGenerate)
+            m_graph.ref(resultIndex);
+        return resultIndex;
+    }
+
+    void predictArray(NodeIndex nodeIndex)
+    {
+        Node* nodePtr = &m_graph[nodeIndex];
+
+        if (nodePtr->op == GetLocal)
+            m_graph.predict(nodePtr->local(), PredictArray);
+    }
+
+    void predictInt32(NodeIndex nodeIndex)
+    {
+        Node* nodePtr = &m_graph[nodeIndex];
+
+        if (nodePtr->op == ValueToNumber)
+            nodePtr = &m_graph[nodePtr->child1];
+
+        if (nodePtr->op == ValueToInt32)
+            nodePtr = &m_graph[nodePtr->child1];
+
+        if (nodePtr->op == NumberToInt32)
+            nodePtr = &m_graph[nodePtr->child1];
+
+        if (nodePtr->op == GetLocal)
+            m_graph.predict(nodePtr->local(), PredictInt32);
+    }
+
+    JSGlobalData* m_globalData;
+    CodeBlock* m_codeBlock;
+    Graph& m_graph;
+
+    // The current block being generated.
+    BasicBlock* m_currentBlock;
+    // The bytecode index of the current instruction being generated.
+    unsigned m_currentIndex;
+
+    // Record failures due to unimplemented functionality or regressions.
+    bool m_parseFailed;
+
+    // We use these values during code generation, and to avoid the need for
+    // special handling we make sure they are available as constants in the
+    // CodeBlock's constant pool. These variables are initialized to
+    // UINT_MAX, and lazily updated to hold an index into the CodeBlock's
+    // constant pool, as necessary.
+    unsigned m_constantUndefined;
+    unsigned m_constantNull;
+    unsigned m_constant1;
+
+    // A constant in the constant pool may be represented by more than one
+    // node in the graph, depending on the context in which it is being used.
+    struct ConstantRecord {
+        ConstantRecord()
+            : asInt32(NoNode)
+            , asNumeric(NoNode)
+            , asJSValue(NoNode)
+        {
+        }
+
+        NodeIndex asInt32;
+        NodeIndex asNumeric;
+        NodeIndex asJSValue;
+    };
+
+    // Track the index of the node whose result is the current value for every
+    // register value in the bytecode - argument, local, and temporary.
+    Vector<ConstantRecord, 16> m_constants;
+
+    // The number of arguments passed to the function.
+    unsigned m_numArguments;
+    // The number of locals (vars + temporaries) used in the function.
+    unsigned m_numLocals;
+    // The number of registers we need to preserve across BasicBlock boundaries;
+    // typically equal to the number vars, but we expand this to cover all
+    // temporaries that persist across blocks (dues to ?:, &&, ||, etc).
+    unsigned m_preservedVars;
+
+    struct PhiStackEntry {
+        PhiStackEntry(BasicBlock* block, NodeIndex phi, unsigned varNo)
+            : m_block(block)
+            , m_phi(phi)
+            , m_varNo(varNo)
+        {
+        }
+
+        BasicBlock* m_block;
+        NodeIndex m_phi;
+        unsigned m_varNo;
+    };
+    Vector<PhiStackEntry, 16> m_argumentPhiStack;
+    Vector<PhiStackEntry, 16> m_localPhiStack;
+
+    // These maps are used to unique ToNumber and ToInt32 operations.
+    typedef HashMap<NodeIndex, NodeIndex> UnaryOpMap;
+    UnaryOpMap m_int32ToNumberNodes;
+    UnaryOpMap m_numberToInt32Nodes;
+};
+
+#define NEXT_OPCODE(name) \
+    m_currentIndex += OPCODE_LENGTH(name); \
+    continue
+
+#define LAST_OPCODE(name) \
+    m_currentIndex += OPCODE_LENGTH(name); \
+    return !m_parseFailed
+
+bool ByteCodeParser::parseBlock(unsigned limit)
+{
+    // No need to reset state initially, since it has been set by the constructor.
+    if (m_currentIndex) {
+        for (unsigned i = 0; i < m_constants.size(); ++i)
+            m_constants[i] = ConstantRecord();
+    }
+
+    AliasTracker aliases(m_graph);
+
+    Interpreter* interpreter = m_globalData->interpreter;
+    Instruction* instructionsBegin = m_codeBlock->instructions().begin();
+    while (true) {
+        // Don't extend over jump destinations.
+        if (m_currentIndex == limit) {
+            addToGraph(Jump, OpInfo(m_currentIndex));
+            return !m_parseFailed;
+        }
+
+        // Switch on the current bytecode opcode.
+        Instruction* currentInstruction = instructionsBegin + m_currentIndex;
+        switch (interpreter->getOpcodeID(currentInstruction->u.opcode)) {
+
+        // === Function entry opcodes ===
+
+        case op_enter:
+            // Initialize all locals to undefined.
+            for (int i = 0; i < m_codeBlock->m_numVars; ++i)
+                set(i, constantUndefined());
+            NEXT_OPCODE(op_enter);
+
+        case op_convert_this: {
+            NodeIndex op1 = getThis();
+            setThis(addToGraph(ConvertThis, op1));
+            NEXT_OPCODE(op_convert_this);
+        }
+
+        // === Bitwise operations ===
+
+        case op_bitand: {
+            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
+            predictInt32(op1);
+            predictInt32(op2);
+            set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2), PredictInt32);
+            NEXT_OPCODE(op_bitand);
+        }
+
+        case op_bitor: {
+            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
+            predictInt32(op1);
+            predictInt32(op2);
+            set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2), PredictInt32);
+            NEXT_OPCODE(op_bitor);
+        }
+
+        case op_bitxor: {
+            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
+            predictInt32(op1);
+            predictInt32(op2);
+            set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2), PredictInt32);
+            NEXT_OPCODE(op_bitxor);
+        }
+
+        case op_rshift: {
+            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
+            predictInt32(op1);
+            predictInt32(op2);
+            NodeIndex result;
+            // Optimize out shifts by zero.
+            if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
+                result = op1;
+            else
+                result = addToGraph(BitRShift, op1, op2);
+            set(currentInstruction[1].u.operand, result, PredictInt32);
+            NEXT_OPCODE(op_rshift);
+        }
+
+        case op_lshift: {
+            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
+            predictInt32(op1);
+            predictInt32(op2);
+            NodeIndex result;
+            // Optimize out shifts by zero.
+            if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
+                result = op1;
+            else
+                result = addToGraph(BitLShift, op1, op2);
+            set(currentInstruction[1].u.operand, result, PredictInt32);
+            NEXT_OPCODE(op_lshift);
+        }
+
+        case op_urshift: {
+            NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
+            predictInt32(op1);
+            predictInt32(op2);
+            NodeIndex result;
+            // The result of a zero-extending right shift is treated as an unsigned value.
+            // This means that if the top bit is set, the result is not in the int32 range,
+            // and as such must be stored as a double. If the shift amount is a constant,
+            // we may be able to optimize.
+            if (isInt32Constant(op2)) {
+                // If we know we are shifting by a non-zero amount, then since the operation
+                // zero fills we know the top bit of the result must be zero, and as such the
+                // result must be within the int32 range. Conversely, if this is a shift by
+                // zero, then the result may be changed by the conversion to unsigned, but it
+                // is not necessary to perform the shift!
+                if (valueOfInt32Constant(op2) & 0x1f)
+                    result = addToGraph(BitURShift, op1, op2);
+                else
+                    result = addToGraph(UInt32ToNumber, op1);
+            }  else {
+                // Cannot optimize at this stage; shift & potentially rebox as a double.
+                result = addToGraph(BitURShift, op1, op2);
+                result = addToGraph(UInt32ToNumber, result);
+            }
+            set(currentInstruction[1].u.operand, result, PredictInt32);
+            NEXT_OPCODE(op_urshift);
+        }
+
+        // === Increment/Decrement opcodes ===
+
+        case op_pre_inc: {
+            unsigned srcDst = currentInstruction[1].u.operand;
+            NodeIndex op = getToNumber(srcDst);
+            predictInt32(op);
+            set(srcDst, addToGraph(ArithAdd, op, one()));
+            NEXT_OPCODE(op_pre_inc);
+        }
+
+        case op_post_inc: {
+            unsigned result = currentInstruction[1].u.operand;
+            unsigned srcDst = currentInstruction[2].u.operand;
+            NodeIndex op = getToNumber(srcDst);
+            predictInt32(op);
+            set(result, op);
+            set(srcDst, addToGraph(ArithAdd, op, one()));
+            NEXT_OPCODE(op_post_inc);
+        }
+
+        case op_pre_dec: {
+            unsigned srcDst = currentInstruction[1].u.operand;
+            NodeIndex op = getToNumber(srcDst);
+            predictInt32(op);
+            set(srcDst, addToGraph(ArithSub, op, one()));
+            NEXT_OPCODE(op_pre_dec);
+        }
+
+        case op_post_dec: {
+            unsigned result = currentInstruction[1].u.operand;
+            unsigned srcDst = currentInstruction[2].u.operand;
+            NodeIndex op = getToNumber(srcDst);
+            predictInt32(op);
+            set(result, op);
+            set(srcDst, addToGraph(ArithSub, op, one()));
+            NEXT_OPCODE(op_post_dec);
+        }
+
+        // === Arithmetic operations ===
+
+        case op_add: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            // If both operands can statically be determined to the numbers, then this is an arithmetic add.
+            // Otherwise, we must assume this may be performing a concatenation to a string.
+            if (m_graph[op1].hasNumericResult() && m_graph[op2].hasNumericResult())
+                set(currentInstruction[1].u.operand, addToGraph(ArithAdd, toNumber(op1), toNumber(op2)));
+            else
+                set(currentInstruction[1].u.operand, addToGraph(ValueAdd, op1, op2));
+            NEXT_OPCODE(op_add);
+        }
+
+        case op_sub: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(ArithSub, op1, op2));
+            NEXT_OPCODE(op_sub);
+        }
+
+        case op_mul: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(ArithMul, op1, op2));
+            NEXT_OPCODE(op_mul);
+        }
+
+        case op_mod: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(ArithMod, op1, op2));
+            NEXT_OPCODE(op_mod);
+        }
+
+        case op_div: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
+            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(ArithDiv, op1, op2));
+            NEXT_OPCODE(op_div);
+        }
+
+        // === Misc operations ===
+
+        case op_mov: {
+            NodeIndex op = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, op);
+            NEXT_OPCODE(op_mov);
+        }
+
+        case op_not: {
+            ARITHMETIC_OP();
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, value));
+            NEXT_OPCODE(op_not);
+        }
+
+        case op_less: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareLess, op1, op2));
+            NEXT_OPCODE(op_less);
+        }
+
+        case op_lesseq: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareLessEq, op1, op2));
+            NEXT_OPCODE(op_lesseq);
+        }
+
+        case op_eq: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareEq, op1, op2));
+            NEXT_OPCODE(op_eq);
+        }
+
+        case op_eq_null: {
+            ARITHMETIC_OP();
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareEq, value, constantNull()));
+            NEXT_OPCODE(op_eq_null);
+        }
+
+        case op_stricteq: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(CompareStrictEq, op1, op2));
+            NEXT_OPCODE(op_stricteq);
+        }
+
+        case op_neq: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, op1, op2)));
+            NEXT_OPCODE(op_neq);
+        }
+
+        case op_neq_null: {
+            ARITHMETIC_OP();
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareEq, value, constantNull())));
+            NEXT_OPCODE(op_neq_null);
+        }
+
+        case op_nstricteq: {
+            ARITHMETIC_OP();
+            NodeIndex op1 = get(currentInstruction[2].u.operand);
+            NodeIndex op2 = get(currentInstruction[3].u.operand);
+            set(currentInstruction[1].u.operand, addToGraph(LogicalNot, addToGraph(CompareStrictEq, op1, op2)));
+            NEXT_OPCODE(op_nstricteq);
+        }
+
+        // === Property access operations ===
+
+        case op_get_by_val: {
+            NodeIndex base = get(currentInstruction[2].u.operand);
+            NodeIndex property = get(currentInstruction[3].u.operand);
+            predictArray(base);
+            predictInt32(property);
+
+            NodeIndex getByVal = addToGraph(GetByVal, base, property, aliases.lookupGetByVal(base, property));
+            set(currentInstruction[1].u.operand, getByVal);
+            aliases.recordGetByVal(getByVal);
+
+            NEXT_OPCODE(op_get_by_val);
+        }
+
+        case op_put_by_val: {
+            NodeIndex base = get(currentInstruction[1].u.operand);
+            NodeIndex property = get(currentInstruction[2].u.operand);
+            NodeIndex value = get(currentInstruction[3].u.operand);
+            predictArray(base);
+            predictInt32(property);
+
+            NodeIndex aliasedGet = aliases.lookupGetByVal(base, property);
+            NodeIndex putByVal = addToGraph(aliasedGet != NoNode ? PutByValAlias : PutByVal, base, property, value);
+            aliases.recordPutByVal(putByVal);
+
+            NEXT_OPCODE(op_put_by_val);
+        }
+
+        case op_get_by_id: {
+            NodeIndex base = get(currentInstruction[2].u.operand);
+            unsigned identifier = currentInstruction[3].u.operand;
+
+            NodeIndex getById = addToGraph(GetById, OpInfo(identifier), base);
+            set(currentInstruction[1].u.operand, getById);
+            aliases.recordGetById(getById);
+
+            NEXT_OPCODE(op_get_by_id);
+        }
+
+        case op_put_by_id: {
+            NodeIndex value = get(currentInstruction[3].u.operand);
+            NodeIndex base = get(currentInstruction[1].u.operand);
+            unsigned identifier = currentInstruction[2].u.operand;
+            bool direct = currentInstruction[8].u.operand;
+
+            if (direct) {
+                NodeIndex putByIdDirect = addToGraph(PutByIdDirect, OpInfo(identifier), base, value);
+                aliases.recordPutByIdDirect(putByIdDirect);
+            } else {
+                NodeIndex putById = addToGraph(PutById, OpInfo(identifier), base, value);
+                aliases.recordPutById(putById);
+            }
+
+            NEXT_OPCODE(op_put_by_id);
+        }
+
+        case op_get_global_var: {
+            NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
+            set(currentInstruction[1].u.operand, getGlobalVar);
+            NEXT_OPCODE(op_get_global_var);
+        }
+
+        case op_put_global_var: {
+            NodeIndex value = get(currentInstruction[2].u.operand);
+            addToGraph(PutGlobalVar, OpInfo(currentInstruction[1].u.operand), value);
+            NEXT_OPCODE(op_put_global_var);
+        }
+
+        // === Block terminators. ===
+
+        case op_jmp: {
+            unsigned relativeOffset = currentInstruction[1].u.operand;
+            addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
+            LAST_OPCODE(op_jmp);
+        }
+
+        case op_loop: {
+            unsigned relativeOffset = currentInstruction[1].u.operand;
+            addToGraph(Jump, OpInfo(m_currentIndex + relativeOffset));
+            LAST_OPCODE(op_loop);
+        }
+
+        case op_jtrue: {
+            unsigned relativeOffset = currentInstruction[2].u.operand;
+            NodeIndex condition = get(currentInstruction[1].u.operand);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jtrue)), condition);
+            LAST_OPCODE(op_jtrue);
+        }
+
+        case op_jfalse: {
+            unsigned relativeOffset = currentInstruction[2].u.operand;
+            NodeIndex condition = get(currentInstruction[1].u.operand);
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jfalse)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_jfalse);
+        }
+
+        case op_loop_if_true: {
+            unsigned relativeOffset = currentInstruction[2].u.operand;
+            NodeIndex condition = get(currentInstruction[1].u.operand);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_true)), condition);
+            LAST_OPCODE(op_loop_if_true);
+        }
+
+        case op_loop_if_false: {
+            unsigned relativeOffset = currentInstruction[2].u.operand;
+            NodeIndex condition = get(currentInstruction[1].u.operand);
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_false)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_loop_if_false);
+        }
+
+        case op_jeq_null: {
+            unsigned relativeOffset = currentInstruction[2].u.operand;
+            NodeIndex value = get(currentInstruction[1].u.operand);
+            NodeIndex condition = addToGraph(CompareEq, value, constantNull());
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jeq_null)), condition);
+            LAST_OPCODE(op_jeq_null);
+        }
+
+        case op_jneq_null: {
+            unsigned relativeOffset = currentInstruction[2].u.operand;
+            NodeIndex value = get(currentInstruction[1].u.operand);
+            NodeIndex condition = addToGraph(CompareEq, value, constantNull());
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_null)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_jneq_null);
+        }
+
+        case op_jnless: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareLess, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnless)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_jnless);
+        }
+
+        case op_jnlesseq: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jnlesseq)), OpInfo(m_currentIndex + relativeOffset), condition);
+            LAST_OPCODE(op_jnlesseq);
+        }
+
+        case op_jless: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareLess, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jless)), condition);
+            LAST_OPCODE(op_jless);
+        }
+
+        case op_jlesseq: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_jlesseq)), condition);
+            LAST_OPCODE(op_jlesseq);
+        }
+
+        case op_loop_if_less: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareLess, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_less)), condition);
+            LAST_OPCODE(op_loop_if_less);
+        }
+
+        case op_loop_if_lesseq: {
+            unsigned relativeOffset = currentInstruction[3].u.operand;
+            NodeIndex op1 = get(currentInstruction[1].u.operand);
+            NodeIndex op2 = get(currentInstruction[2].u.operand);
+            NodeIndex condition = addToGraph(CompareLessEq, op1, op2);
+            addToGraph(Branch, OpInfo(m_currentIndex + relativeOffset), OpInfo(m_currentIndex + OPCODE_LENGTH(op_loop_if_lesseq)), condition);
+            LAST_OPCODE(op_loop_if_lesseq);
+        }
+
+        case op_ret: {
+            addToGraph(Return, get(currentInstruction[1].u.operand));
+            LAST_OPCODE(op_ret);
+        }
+
+        default:
+            // Parse failed!
+            return false;
+        }
+    }
+}
+
+template<ByteCodeParser::PhiStackType stackType>
+void ByteCodeParser::processPhiStack()
+{
+    Vector<PhiStackEntry, 16>& phiStack = (stackType == ArgumentPhiStack) ? m_argumentPhiStack : m_localPhiStack;
+
+    while (!phiStack.isEmpty()) {
+        PhiStackEntry entry = phiStack.last();
+        phiStack.removeLast();
+        
+        Node& phiNode = m_graph[entry.m_phi];
+        PredecessorList& predecessors = entry.m_block->m_predecessors;
+        unsigned varNo = entry.m_varNo;
+
+        for (size_t i = 0; i < predecessors.size(); ++i) {
+            BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
+
+            VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_arguments[varNo] : predecessorBlock->m_locals[varNo];
+
+            NodeIndex valueInPredecessor = var.value;
+            if (valueInPredecessor == NoNode) {
+                valueInPredecessor = addToGraph(Phi);
+                var.value = valueInPredecessor;
+                phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
+            } else if (m_graph[valueInPredecessor].op == GetLocal)
+                valueInPredecessor = m_graph[valueInPredecessor].child1;
+            ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi);
+
+            if (phiNode.refCount())
+                m_graph.ref(valueInPredecessor);
+
+            if (phiNode.child1 == NoNode) {
+                phiNode.child1 = valueInPredecessor;
+                continue;
+            }
+            if (phiNode.child2 == NoNode) {
+                phiNode.child2 = valueInPredecessor;
+                continue;
+            }
+            if (phiNode.child3 == NoNode) {
+                phiNode.child3 = valueInPredecessor;
+                continue;
+            }
+
+            NodeIndex newPhi = addToGraph(Phi);
+            Node& newPhiNode = m_graph[newPhi];
+            if (phiNode.refCount())
+                m_graph.ref(newPhi);
+
+            newPhiNode.child1 = phiNode.child1;
+            newPhiNode.child2 = phiNode.child2;
+            newPhiNode.child3 = phiNode.child3;
+
+            phiNode.child1 = newPhi;
+            phiNode.child1 = valueInPredecessor;
+            phiNode.child3 = NoNode;
+        }
+    }
+}
+
+void ByteCodeParser::setupPredecessors()
+{
+    for (BlockIndex index = 0; index < m_graph.m_blocks.size(); ++index) {
+        BasicBlock* block = m_graph.m_blocks[index].get();
+        ASSERT(block->end != NoNode);
+        Node& node = m_graph[block->end - 1];
+        ASSERT(node.isTerminal());
+
+        if (node.isJump())
+            m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
+        else if (node.isBranch()) {
+            m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
+            m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index);
+        }
+    }
+}
+
+void ByteCodeParser::allocateVirtualRegisters()
+{
+    ScoreBoard scoreBoard(m_graph, m_preservedVars);
+    unsigned sizeExcludingPhiNodes = m_graph.m_blocks.last()->end;
+    for (size_t i = 0; i < sizeExcludingPhiNodes; ++i) {
+        Node& node = m_graph[i];
+        if (!node.shouldGenerate())
+            continue;
+
+        // GetLocal nodes are effectively phi nodes in the graph, referencing
+        // results from prior blocks.
+        if (node.op != GetLocal) {
+            // First, call use on all of the current node's children, then
+            // allocate a VirtualRegister for this node. We do so in this
+            // order so that if a child is on its last use, and a
+            // VirtualRegister is freed, then it may be reused for node.
+            scoreBoard.use(node.child1);
+            scoreBoard.use(node.child2);
+            scoreBoard.use(node.child3);
+        }
+
+        if (!node.hasResult())
+            continue;
+
+        node.setVirtualRegister(scoreBoard.allocate());
+        // 'mustGenerate' nodes have their useCount artificially elevated,
+        // call use now to account for this.
+        if (node.mustGenerate())
+            scoreBoard.use(i);
+    }
+
+    // 'm_numCalleeRegisters' is the number of locals and temporaries allocated
+    // for the function (and checked for on entry). Since we perform a new and
+    // different allocation of temporaries, more registers may now be required.
+    unsigned calleeRegisters = scoreBoard.allocatedCount() + m_preservedVars;
+    if ((unsigned)m_codeBlock->m_numCalleeRegisters < calleeRegisters)
+        m_codeBlock->m_numCalleeRegisters = calleeRegisters;
+}
+
+bool ByteCodeParser::parse()
+{
+    // Set during construction.
+    ASSERT(!m_currentIndex);
+
+    for (unsigned jumpTargetIndex = 0; jumpTargetIndex <= m_codeBlock->numberOfJumpTargets(); ++jumpTargetIndex) {
+        // The maximum bytecode offset to go into the current basicblock is either the next jump target, or the end of the instructions.
+        unsigned limit = jumpTargetIndex < m_codeBlock->numberOfJumpTargets() ? m_codeBlock->jumpTarget(jumpTargetIndex) : m_codeBlock->instructions().size();
+        ASSERT(m_currentIndex < limit);
+
+        // Loop until we reach the current limit (i.e. next jump target).
+        do {
+            OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals));
+            m_currentBlock = block.get();
+            m_graph.m_blocks.append(block.release());
+
+            if (!parseBlock(limit))
+                return false;
+            // We should not have gone beyond the limit.
+            ASSERT(m_currentIndex <= limit);
+
+            m_currentBlock->end = m_graph.size();
+        } while (m_currentIndex < limit);
+    }
+
+    // Should have reached the end of the instructions.
+    ASSERT(m_currentIndex == m_codeBlock->instructions().size());
+
+    setupPredecessors();
+    processPhiStack<LocalPhiStack>();
+    processPhiStack<ArgumentPhiStack>();
+
+    allocateVirtualRegisters();
+
+#if DFG_DEBUG_VERBOSE
+    m_graph.dump(m_codeBlock);
+#endif
+
+    return true;
+}
+
+bool parse(Graph& graph, JSGlobalData* globalData, CodeBlock* codeBlock)
+{
+#if DFG_DEBUG_LOCAL_DISBALE
+    UNUSED_PARAM(graph);
+    UNUSED_PARAM(globalData);
+    UNUSED_PARAM(codeBlock);
+    return false;
+#else
+    return ByteCodeParser(globalData, codeBlock, graph).parse();
+#endif
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGByteCodeParser.h b/dfg/DFGByteCodeParser.h
new file mode 100644 (file)
index 0000000..d4efe61
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 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 DFGByteCodeParser_h
+#define DFGByteCodeParser_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGGraph.h>
+
+namespace JSC {
+
+class CodeBlock;
+class JSGlobalData;
+
+namespace DFG {
+
+// Populate the Graph with a basic block of code from the CodeBlock,
+// starting at the provided bytecode index.
+bool parse(Graph&, JSGlobalData*, CodeBlock*);
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGFPRInfo.h b/dfg/DFGFPRInfo.h
new file mode 100644 (file)
index 0000000..87e44ea
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 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 DFGFPRInfo_h
+#define DFGFPRInfo_h
+
+#if ENABLE(DFG_JIT)
+
+#include <assembler/MacroAssembler.h>
+#include <dfg/DFGRegisterBank.h>
+
+namespace JSC { namespace DFG {
+
+typedef MacroAssembler::FPRegisterID FPRReg;
+#define InvalidFPRReg ((FPRReg)-1)
+
+class FPRInfo {
+public:
+    typedef FPRReg RegisterType;
+    static const unsigned numberOfRegisters = 6;
+
+    // Temporary registers.
+    static const FPRReg fpRegT0 = X86Registers::xmm0;
+    static const FPRReg fpRegT1 = X86Registers::xmm1;
+    static const FPRReg fpRegT2 = X86Registers::xmm2;
+    static const FPRReg fpRegT3 = X86Registers::xmm3;
+    static const FPRReg fpRegT4 = X86Registers::xmm4;
+    static const FPRReg fpRegT5 = X86Registers::xmm5;
+    // These constants provide the names for the general purpose argument & return value registers.
+    static const FPRReg argumentFPR0 = X86Registers::xmm0; // fpRegT0
+    static const FPRReg argumentFPR1 = X86Registers::xmm1; // fpRegT1
+    static const FPRReg argumentFPR2 = X86Registers::xmm2; // fpRegT2
+    static const FPRReg argumentFPR3 = X86Registers::xmm3; // fpRegT3
+    static const FPRReg returnValueFPR = X86Registers::xmm0; // fpRegT0
+
+    // FPRReg mapping is direct, the machine regsiter numbers can
+    // be used directly as indices into the FPR RegisterBank.
+    COMPILE_ASSERT(X86Registers::xmm0 == 0, xmm0_is_0);
+    COMPILE_ASSERT(X86Registers::xmm1 == 1, xmm1_is_1);
+    COMPILE_ASSERT(X86Registers::xmm2 == 2, xmm2_is_2);
+    COMPILE_ASSERT(X86Registers::xmm3 == 3, xmm3_is_3);
+    COMPILE_ASSERT(X86Registers::xmm4 == 4, xmm4_is_4);
+    COMPILE_ASSERT(X86Registers::xmm5 == 5, xmm5_is_5);
+    static FPRReg toRegister(unsigned index)
+    {
+        return (FPRReg)index;
+    }
+    static unsigned toIndex(FPRReg reg)
+    {
+        return (unsigned)reg;
+    }
+
+#ifndef NDEBUG
+    static const char* debugName(FPRReg reg)
+    {
+        ASSERT(reg != InvalidFPRReg);
+        ASSERT(reg < 16);
+        static const char* nameForRegister[16] = {
+            "xmm0", "xmm1", "xmm2", "xmm3",
+            "xmm4", "xmm5", "xmm6", "xmm7",
+            "xmm8", "xmm9", "xmm10", "xmm11",
+            "xmm12", "xmm13", "xmm14", "xmm15"
+        };
+        return nameForRegister[reg];
+    }
+#endif
+};
+
+typedef RegisterBank<FPRInfo>::iterator fpr_iterator;
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGGPRInfo.h b/dfg/DFGGPRInfo.h
new file mode 100644 (file)
index 0000000..f4e9f76
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2011 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 DFGGPRInfo_h
+#define DFGGPRInfo_h
+
+#if ENABLE(DFG_JIT)
+
+#include <assembler/MacroAssembler.h>
+#include <dfg/DFGRegisterBank.h>
+
+namespace JSC { namespace DFG {
+
+typedef MacroAssembler::RegisterID GPRReg;
+#define InvalidGPRReg ((GPRReg)-1)
+
+class GPRInfo {
+public:
+    typedef GPRReg RegisterType;
+    static const unsigned numberOfRegisters = 9;
+
+    // These registers match the old JIT.
+    static const GPRReg timeoutCheckRegister = X86Registers::r12;
+    static const GPRReg callFrameRegister = X86Registers::r13;
+    static const GPRReg tagTypeNumberRegister = X86Registers::r14;
+    static const GPRReg tagMaskRegister = X86Registers::r15;
+    // Temporary registers.
+    static const GPRReg regT0 = X86Registers::eax;
+    static const GPRReg regT1 = X86Registers::edx;
+    static const GPRReg regT2 = X86Registers::ecx;
+    static const GPRReg regT3 = X86Registers::ebx;
+    static const GPRReg regT4 = X86Registers::edi;
+    static const GPRReg regT5 = X86Registers::esi;
+    static const GPRReg regT6 = X86Registers::r8;
+    static const GPRReg regT7 = X86Registers::r9;
+    static const GPRReg regT8 = X86Registers::r10;
+    // These constants provide the names for the general purpose argument & return value registers.
+    static const GPRReg argumentGPR0 = X86Registers::edi; // regT4
+    static const GPRReg argumentGPR1 = X86Registers::esi; // regT5
+    static const GPRReg argumentGPR2 = X86Registers::edx; // regT1
+    static const GPRReg argumentGPR3 = X86Registers::ecx; // regT2
+    static const GPRReg returnValueGPR = X86Registers::eax; // regT0
+    static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
+
+    static GPRReg toRegister(unsigned index)
+    {
+        ASSERT(index < numberOfRegisters);
+        static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
+        return registerForIndex[index];
+    }
+
+    static unsigned toIndex(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(reg < 16);
+        static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
+        unsigned result = indexForRegister[reg];
+        ASSERT(result != InvalidIndex);
+        return result;
+    }
+
+#ifndef NDEBUG
+    static const char* debugName(GPRReg reg)
+    {
+        ASSERT(reg != InvalidGPRReg);
+        ASSERT(reg < 16);
+        static const char* nameForRegister[16] = {
+            "rax", "rcx", "rdx", "rbx",
+            "rsp", "rbp", "rsi", "rdi",
+            "r8", "r9", "r10", "r11",
+            "r12", "r13", "r14", "r15"
+        };
+        return nameForRegister[reg];
+    }
+#endif
+private:
+
+    static const unsigned InvalidIndex = 0xffffffff;
+};
+
+typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGGenerationInfo.h b/dfg/DFGGenerationInfo.h
new file mode 100644 (file)
index 0000000..968ea20
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2011 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 DFGGenerationInfo_h
+#define DFGGenerationInfo_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGJITCompiler.h>
+
+namespace JSC { namespace DFG {
+
+// === DataFormat ===
+//
+// This enum tracks the current representation in which a value is being held.
+// Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue.
+// For boxed values, we may know the type of boxing that has taken place.
+// (May also need bool, array, object, string types!)
+enum DataFormat {
+    DataFormatNone = 0,
+    DataFormatInteger = 1,
+    DataFormatDouble = 2,
+    DataFormatCell = 3,
+    DataFormatJS = 8,
+    DataFormatJSInteger = DataFormatJS | DataFormatInteger,
+    DataFormatJSDouble = DataFormatJS | DataFormatDouble,
+    DataFormatJSCell = DataFormatJS | DataFormatCell,
+};
+
+// === GenerationInfo ===
+//
+// This class is used to track the current status of a live values during code generation.
+// Can provide information as to whether a value is in machine registers, and if so which,
+// whether a value has been spilled to the RegsiterFile, and if so may be able to provide
+// details of the format in memory (all values are spilled in a boxed form, but we may be
+// able to track the type of box), and tracks how many outstanding uses of a value remain,
+// so that we know when the value is dead and the machine registers associated with it
+// may be released.
+class GenerationInfo {
+public:
+    GenerationInfo()
+        : m_nodeIndex(NoNode)
+        , m_useCount(0)
+        , m_registerFormat(DataFormatNone)
+        , m_spillFormat(DataFormatNone)
+        , m_canFill(false)
+    {
+    }
+
+    void initConstant(NodeIndex nodeIndex, uint32_t useCount)
+    {
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = DataFormatNone;
+        m_spillFormat = DataFormatNone;
+        m_canFill = true;
+    }
+    void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
+    {
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = DataFormatInteger;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.gpr = gpr;
+    }
+    void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
+    {
+        ASSERT(format & DataFormatJS);
+
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = format;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.gpr = gpr;
+    }
+    void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
+    {
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = DataFormatCell;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.gpr = gpr;
+    }
+    void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
+    {
+        m_nodeIndex = nodeIndex;
+        m_useCount = useCount;
+        m_registerFormat = DataFormatDouble;
+        m_spillFormat = DataFormatNone;
+        m_canFill = false;
+        u.fpr = fpr;
+    }
+
+    // Get the index of the node that produced this value.
+    NodeIndex nodeIndex() { return m_nodeIndex; }
+
+    // Mark the value as having been used (decrement the useCount).
+    // Returns true if this was the last use of the value, and any
+    // associated machine registers may be freed.
+    bool use()
+    {
+        return !--m_useCount;
+    }
+
+    // Used to check the operands of operations to see if they are on
+    // their last use; in some cases it may be safe to reuse the same
+    // machine register for the result of the operation.
+    bool canReuse()
+    {
+        ASSERT(m_useCount);
+        return m_useCount == 1;
+    }
+
+    // Get the format of the value in machine registers (or 'none').
+    DataFormat registerFormat() { return m_registerFormat; }
+    // Get the format of the value as it is spilled in the RegisterFile (or 'none').
+    DataFormat spillFormat() { return m_spillFormat; }
+
+    // Get the machine resister currently holding the value.
+    GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
+    FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
+
+    // Check whether a value needs spilling in order to free up any associated machine registers.
+    bool needsSpill()
+    {
+        // This should only be called on values that are currently in a register.
+        ASSERT(m_registerFormat != DataFormatNone);
+        // Constants do not need spilling, nor do values that have already been
+        // spilled to the RegisterFile.
+        return !m_canFill;
+    }
+
+    // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
+    void spill(DataFormat spillFormat)
+    {
+        // We shouldn't be spill values that don't need spilling.
+        ASSERT(!m_canFill);
+        ASSERT(m_spillFormat == DataFormatNone);
+        // We should only be spilling values that are currently in machine registers.
+        ASSERT(m_registerFormat != DataFormatNone);
+        // We only spill values that have been boxed as a JSValue; otherwise the GC
+        // would need a way to distinguish cell pointers from numeric primitives.
+        ASSERT(spillFormat & DataFormatJS);
+
+        m_registerFormat = DataFormatNone;
+        m_spillFormat = spillFormat;
+        m_canFill = true;
+    }
+
+    // Called on values that don't need spilling (constants and values that have
+    // already been spilled), to mark them as no longer being in machine registers.
+    void setSpilled()
+    {
+        // Should only be called on values that don't need spilling, and are currently in registers.
+        ASSERT(m_canFill && m_registerFormat != DataFormatNone);
+        m_registerFormat = DataFormatNone;
+    }
+
+    // Record that this value is filled into machine registers,
+    // tracking which registers, and what format the value has.
+    void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
+    {
+        ASSERT(format & DataFormatJS);
+        m_registerFormat = format;
+        u.gpr = gpr;
+    }
+    void fillInteger(GPRReg gpr)
+    {
+        m_registerFormat = DataFormatInteger;
+        u.gpr = gpr;
+    }
+    void fillDouble(FPRReg fpr)
+    {
+        m_registerFormat = DataFormatDouble;
+        u.fpr = fpr;
+    }
+
+#ifndef NDEBUG
+    bool alive()
+    {
+        return m_useCount;
+    }
+#endif
+
+private:
+    // The index of the node whose result is stored in this virtual register.
+    // FIXME: Can we remove this? - this is currently only used when collecting
+    // snapshots of the RegisterBank for SpeculationCheck/EntryLocation. Could
+    // investigate storing NodeIndex as the name in RegsiterBank, instead of
+    // VirtualRegister.
+    NodeIndex m_nodeIndex;
+    uint32_t m_useCount;
+    DataFormat m_registerFormat;
+    DataFormat m_spillFormat;
+    bool m_canFill;
+    union {
+        GPRReg gpr;
+        FPRReg fpr;
+    } u;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGGraph.cpp b/dfg/DFGGraph.cpp
new file mode 100644 (file)
index 0000000..b1e6991
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGGraph.h"
+
+#include "CodeBlock.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+#ifndef NDEBUG
+
+// Creates an array of stringized names.
+static const char* dfgOpNames[] = {
+#define STRINGIZE_DFG_OP_ENUM(opcode, flags) #opcode ,
+    FOR_EACH_DFG_OP(STRINGIZE_DFG_OP_ENUM)
+#undef STRINGIZE_DFG_OP_ENUM
+};
+
+void Graph::dump(NodeIndex nodeIndex, CodeBlock* codeBlock)
+{
+    Node& node = at(nodeIndex);
+    NodeType op = node.op;
+
+    unsigned refCount = node.refCount();
+    if (!refCount)
+        return;
+    bool mustGenerate = node.mustGenerate();
+    if (mustGenerate)
+        --refCount;
+
+    // Example/explanation of dataflow dump output
+    //
+    //   14:   <!2:7>  GetByVal(@3, @13)
+    //   ^1     ^2 ^3     ^4       ^5
+    //
+    // (1) The nodeIndex of this operation.
+    // (2) The reference count. The number printed is the 'real' count,
+    //     not including the 'mustGenerate' ref. If the node is
+    //     'mustGenerate' then the count it prefixed with '!'.
+    // (3) The virtual register slot assigned to this node.
+    // (4) The name of the operation.
+    // (5) The arguments to the operation. The may be of the form:
+    //         @#   - a NodeIndex referencing a prior node in the graph.
+    //         arg# - an argument number.
+    //         $#   - the index in the CodeBlock of a constant { for numeric constants the value is displayed | for integers, in both decimal and hex }.
+    //         id#  - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
+    //         var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
+    printf("% 4d:\t<%c%u:", (int)nodeIndex, mustGenerate ? '!' : ' ', refCount);
+    if (node.hasResult())
+        printf("%u", node.virtualRegister());
+    else
+        printf("-");
+    printf(">\t%s(", dfgOpNames[op & NodeIdMask]);
+    if (node.child1 != NoNode)
+        printf("@%u", node.child1);
+    if (node.child2 != NoNode)
+        printf(", @%u", node.child2);
+    if (node.child3 != NoNode)
+        printf(", @%u", node.child3);
+    bool hasPrinted = node.child1 != NoNode;
+
+    if (node.hasVarNumber()) {
+        printf("%svar%u", hasPrinted ? ", " : "", node.varNumber());
+        hasPrinted = true;
+    }
+    if (node.hasIdentifier()) {
+        if (codeBlock)
+            printf("%sid%u{%s}", hasPrinted ? ", " : "", node.identifierNumber(), codeBlock->identifier(node.identifierNumber()).ustring().utf8().data());
+        else
+            printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber());
+        hasPrinted = true;
+    }
+    if (node.hasLocal()) {
+        int local = node.local();
+        if (operandIsArgument(local))
+            printf("%sarg%u", hasPrinted ? ", " : "", local - codeBlock->thisRegister());
+        else
+            printf("%sr%u", hasPrinted ? ", " : "", local);
+        hasPrinted = true;
+    }
+    if (op == Int32Constant) {
+        printf("%s$%u{%d|0x%08x}", hasPrinted ? ", " : "", node.constantNumber(), node.int32Constant(), node.int32Constant());
+        hasPrinted = true;
+    }
+    if (op == DoubleConstant) {
+        printf("%s$%u{%f})", hasPrinted ? ", " : "", node.constantNumber(), node.numericConstant());
+        hasPrinted = true;
+    }
+    if (op == JSConstant) {
+        printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
+        hasPrinted = true;
+    }
+    if  (node.isBranch() || node.isJump()) {
+        printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));
+        hasPrinted = true;
+    }
+    if  (node.isBranch()) {
+        printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));
+        hasPrinted = true;
+    }
+
+    printf(")\n");
+}
+
+void Graph::dump(CodeBlock* codeBlock)
+{
+    for (size_t b = 0; b < m_blocks.size(); ++b) {
+        printf("Block #%u:\n", (int)b);
+        for (size_t i = m_blocks[b]->begin; i < m_blocks[b]->end; ++i)
+            dump(i, codeBlock);
+    }
+    printf("Phi Nodes:\n");
+    for (size_t i = m_blocks.last()->end; i < size(); ++i)
+        dump(i, codeBlock);
+}
+
+#endif
+
+// FIXME: Convert this method to be iterative, not recursive.
+void Graph::refChildren(NodeIndex op)
+{
+    Node& node = at(op);
+
+    if (node.child1 == NoNode) {
+        ASSERT(node.child2 == NoNode && node.child3 == NoNode);
+        return;
+    }
+    ref(node.child1);
+
+    if (node.child2 == NoNode) {
+        ASSERT(node.child3 == NoNode);
+        return;
+    }
+    ref(node.child2);
+
+    if (node.child3 == NoNode)
+        return;
+    ref(node.child3);
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGGraph.h b/dfg/DFGGraph.h
new file mode 100644 (file)
index 0000000..9fc490c
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2011 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 DFGGraph_h
+#define DFGGraph_h
+
+#if ENABLE(DFG_JIT)
+
+#include <RegisterFile.h>
+#include <dfg/DFGNode.h>
+#include <wtf/Vector.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+class CodeBlock;
+
+namespace DFG {
+
+// helper function to distinguish vars & temporaries from arguments.
+inline bool operandIsArgument(int operand) { return operand < 0; }
+
+typedef uint8_t PredictedType;
+static const PredictedType PredictNone  = 0;
+static const PredictedType PredictCell  = 0x01;
+static const PredictedType PredictArray = 0x03;
+static const PredictedType PredictInt32 = 0x04;
+
+struct PredictionSlot {
+public:
+    PredictionSlot()
+        : m_value(PredictNone)
+    {
+    }
+    PredictedType m_value;
+};
+
+typedef uint32_t BlockIndex;
+
+// For every local variable we track any existing get or set of the value.
+// We track the get so that these may be shared, and we track the set to
+// retrieve the current value, and to reference the final definition.
+struct VariableRecord {
+    VariableRecord()
+        : value(NoNode)
+    {
+    }
+
+    NodeIndex value;
+};
+
+typedef Vector <BlockIndex, 2> PredecessorList;
+
+struct BasicBlock {
+    BasicBlock(unsigned bytecodeBegin, NodeIndex begin, unsigned numArguments, unsigned numLocals)
+        : bytecodeBegin(bytecodeBegin)
+        , begin(begin)
+        , end(NoNode)
+        , m_arguments(numArguments)
+        , m_locals(numLocals)
+    {
+    }
+
+    static inline BlockIndex getBytecodeBegin(OwnPtr<BasicBlock>* block)
+    {
+        return (*block)->bytecodeBegin;
+    }
+
+    unsigned bytecodeBegin;
+    NodeIndex begin;
+    NodeIndex end;
+
+    PredecessorList m_predecessors;
+    Vector <VariableRecord, 8> m_arguments;
+    Vector <VariableRecord, 16> m_locals;
+};
+
+// 
+// === Graph ===
+//
+// The dataflow graph is an ordered vector of nodes.
+// The order may be significant for nodes with side-effects (property accesses, value conversions).
+// Nodes that are 'dead' remain in the vector with refCount 0.
+class Graph : public Vector<Node, 64> {
+public:
+    Graph(unsigned numArguments, unsigned numVariables)
+        : m_argumentPredictions(numArguments)
+        , m_variablePredictions(numVariables)
+    {
+    }
+
+    // Mark a node as being referenced.
+    void ref(NodeIndex nodeIndex)
+    {
+        Node& node = at(nodeIndex);
+        // If the value (before incrementing) was at refCount zero then we need to ref its children.
+        if (node.ref())
+            refChildren(nodeIndex);
+    }
+
+#ifndef NDEBUG
+    // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names).
+    void dump(CodeBlock* = 0);
+    void dump(NodeIndex, CodeBlock* = 0);
+#endif
+
+    BlockIndex blockIndexForBytecodeOffset(unsigned bytecodeBegin)
+    {
+        OwnPtr<BasicBlock>* begin = m_blocks.begin();
+        OwnPtr<BasicBlock>* block = binarySearch<OwnPtr<BasicBlock>, unsigned, BasicBlock::getBytecodeBegin>(begin, m_blocks.size(), bytecodeBegin);
+        ASSERT(block >= m_blocks.begin() && block < m_blocks.end());
+        return static_cast<BlockIndex>(block - begin);
+    }
+
+    BasicBlock& blockForBytecodeOffset(unsigned bytecodeBegin)
+    {
+        return *m_blocks[blockIndexForBytecodeOffset(bytecodeBegin)];
+    }
+
+    void predict(int operand, PredictedType prediction)
+    {
+        if (operandIsArgument(operand)) {
+            unsigned argument = operand + m_argumentPredictions.size() + RegisterFile::CallFrameHeaderSize;
+            m_argumentPredictions[argument].m_value |= prediction;
+        } else if ((unsigned)operand < m_variablePredictions.size())
+            m_variablePredictions[operand].m_value |= prediction;
+            
+    }
+
+    PredictedType getPrediction(int operand)
+    {
+        if (operandIsArgument(operand)) {
+            unsigned argument = operand + m_argumentPredictions.size() + RegisterFile::CallFrameHeaderSize;
+            return m_argumentPredictions[argument].m_value;
+        }
+        if ((unsigned)operand < m_variablePredictions.size())
+            return m_variablePredictions[operand].m_value;
+        return PredictNone;
+    }
+
+    Vector< OwnPtr<BasicBlock> , 8> m_blocks;
+private:
+
+    // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa.
+    void refChildren(NodeIndex);
+
+    Vector<PredictionSlot, 16> m_argumentPredictions;
+    Vector<PredictionSlot, 16> m_variablePredictions;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGJITCodeGenerator.cpp b/dfg/DFGJITCodeGenerator.cpp
new file mode 100644 (file)
index 0000000..781edbb
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGJITCodeGenerator.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGNonSpeculativeJIT.h"
+#include "DFGSpeculativeJIT.h"
+#include "LinkBuffer.h"
+
+namespace JSC { namespace DFG {
+
+GPRReg JITCodeGenerator::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        GPRReg gpr = allocate();
+
+        if (node.isConstant()) {
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            if (isInt32Constant(nodeIndex)) {
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+                info.fillInteger(gpr);
+                returnFormat = DataFormatInteger;
+                return gpr;
+            }
+            if (isDoubleConstant(nodeIndex)) {
+                JSValue jsValue = jsNumber(valueOfDoubleConstant(nodeIndex));
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            } else {
+                ASSERT(isJSConstant(nodeIndex));
+                JSValue jsValue = valueOfJSConstant(nodeIndex);
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            }
+        } else {
+            ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+        }
+
+        // Since we statically know that we're filling an integer, and values
+        // in the RegisterFile are boxed, this must be DataFormatJSInteger.
+        // We will check this with a jitAssert below.
+        info.fillJSValue(gpr, DataFormatJSInteger);
+        unlock(gpr);
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone:
+        // Should have filled, above.
+    case DataFormatJSDouble:
+    case DataFormatDouble:
+    case DataFormatJS:
+    case DataFormatCell:
+    case DataFormatJSCell:
+        // Should only be calling this function if we know this operand to be integer.
+        ASSERT_NOT_REACHED();
+
+    case DataFormatJSInteger: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.jitAssertIsJSInt32(gpr);
+        returnFormat = DataFormatJSInteger;
+        return gpr;
+    }
+
+    case DataFormatInteger: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        m_jit.jitAssertIsInt32(gpr);
+        returnFormat = DataFormatInteger;
+        return gpr;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+FPRReg JITCodeGenerator::fillDouble(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    if (info.registerFormat() == DataFormatNone) {
+        GPRReg gpr = allocate();
+
+        if (node.isConstant()) {
+            if (isInt32Constant(nodeIndex)) {
+                // FIXME: should not be reachable?
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                info.fillInteger(gpr);
+                unlock(gpr);
+            } else if (isDoubleConstant(nodeIndex)) {
+                FPRReg fpr = fprAllocate();
+                m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr);
+                m_jit.movePtrToDouble(gpr, fpr);
+                unlock(gpr);
+
+                m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+                info.fillDouble(fpr);
+                return fpr;
+            } else {
+                // FIXME: should not be reachable?
+                ASSERT(isJSConstant(nodeIndex));
+                JSValue jsValue = valueOfJSConstant(nodeIndex);
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+                info.fillJSValue(gpr, DataFormatJS);
+                unlock(gpr);
+            }
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT(spillFormat & DataFormatJS);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+            info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
+            unlock(gpr);
+        }
+    }
+
+    switch (info.registerFormat()) {
+    case DataFormatNone:
+        // Should have filled, above.
+    case DataFormatCell:
+    case DataFormatJSCell:
+        // Should only be calling this function if we know this operand to be numeric.
+        ASSERT_NOT_REACHED();
+
+    case DataFormatJS: {
+        GPRReg jsValueGpr = info.gpr();
+        m_gprs.lock(jsValueGpr);
+        FPRReg fpr = fprAllocate();
+        GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
+
+        JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+
+        m_jit.jitAssertIsJSDouble(jsValueGpr);
+
+        // First, if we get here we have a double encoded as a JSValue
+        m_jit.move(jsValueGpr, tempGpr);
+        m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
+        m_jit.movePtrToDouble(tempGpr, fpr);
+        JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+
+        // Finally, handle integers.
+        isInteger.link(&m_jit);
+        m_jit.convertInt32ToDouble(jsValueGpr, fpr);
+        hasUnboxedDouble.link(&m_jit);
+
+        m_gprs.release(jsValueGpr);
+        m_gprs.unlock(jsValueGpr);
+        m_gprs.unlock(tempGpr);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+        info.fillDouble(fpr);
+        return fpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger: {
+        FPRReg fpr = fprAllocate();
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+
+        m_jit.convertInt32ToDouble(gpr, fpr);
+
+        m_gprs.release(gpr);
+        m_gprs.unlock(gpr);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+        info.fillDouble(fpr);
+        return fpr;
+    }
+
+    // Unbox the double
+    case DataFormatJSDouble: {
+        GPRReg gpr = info.gpr();
+        FPRReg fpr = unboxDouble(gpr);
+
+        m_gprs.release(gpr);
+        m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
+
+        info.fillDouble(fpr);
+        return fpr;
+    }
+
+    case DataFormatDouble: {
+        FPRReg fpr = info.fpr();
+        m_fprs.lock(fpr);
+        return fpr;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidFPRReg;
+}
+
+GPRReg JITCodeGenerator::fillJSValue(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        GPRReg gpr = allocate();
+
+        if (node.isConstant()) {
+            if (isInt32Constant(nodeIndex)) {
+                info.fillJSValue(gpr, DataFormatJSInteger);
+                JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            } else if (isDoubleConstant(nodeIndex)) {
+                info.fillJSValue(gpr, DataFormatJSDouble);
+                JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex));
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+            } else {
+                ASSERT(isJSConstant(nodeIndex));
+                JSValue jsValue = valueOfJSConstant(nodeIndex);
+                m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+                info.fillJSValue(gpr, DataFormatJS);
+            }
+
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT(spillFormat & DataFormatJS);
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+            info.fillJSValue(gpr, m_isSpeculative ? spillFormat : DataFormatJS);
+        }
+        return gpr;
+    }
+
+    case DataFormatInteger: {
+        GPRReg gpr = info.gpr();
+        // If the register has already been locked we need to take a copy.
+        // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
+        if (m_gprs.isLocked(gpr)) {
+            GPRReg result = allocate();
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr, result);
+            return result;
+        }
+        m_gprs.lock(gpr);
+        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, gpr);
+        info.fillJSValue(gpr, DataFormatJSInteger);
+        return gpr;
+    }
+
+    case DataFormatDouble: {
+        FPRReg fpr = info.fpr();
+        GPRReg gpr = boxDouble(fpr);
+
+        // Update all info
+        info.fillJSValue(gpr, DataFormatJSDouble);
+        m_fprs.release(fpr);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
+
+        return gpr;
+    }
+
+    case DataFormatCell:
+        // No retag required on JSVALUE64!
+    case DataFormatJS:
+    case DataFormatJSInteger:
+    case DataFormatJSDouble:
+    case DataFormatJSCell: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        return gpr;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+void JITCodeGenerator::useChildren(Node& node)
+{
+    NodeIndex child1 = node.child1;
+    if (child1 == NoNode) {
+        ASSERT(node.child2 == NoNode && node.child3 == NoNode);
+        return;
+    }
+    use(child1);
+
+    NodeIndex child2 = node.child2;
+    if (child2 == NoNode) {
+        ASSERT(node.child3 == NoNode);
+        return;
+    }
+    use(child2);
+
+    NodeIndex child3 = node.child3;
+    if (child3 == NoNode)
+        return;
+    use(child3);
+}
+
+#ifndef NDEBUG
+static const char* dataFormatString(DataFormat format)
+{
+    // These values correspond to the DataFormat enum.
+    const char* strings[] = {
+        "[  ]",
+        "[ i]",
+        "[ d]",
+        "[ c]",
+        "Err!",
+        "Err!",
+        "Err!",
+        "Err!",
+        "[J ]",
+        "[Ji]",
+        "[Jd]",
+        "[Jc]",
+        "Err!",
+        "Err!",
+        "Err!",
+        "Err!",
+    };
+    return strings[format];
+}
+
+void JITCodeGenerator::dump(const char* label)
+{
+    if (label)
+        fprintf(stderr, "<%s>\n", label);
+
+    fprintf(stderr, "  gprs:\n");
+    m_gprs.dump();
+    fprintf(stderr, "  fprs:\n");
+    m_fprs.dump();
+    fprintf(stderr, "  VirtualRegisters:\n");
+    for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
+        GenerationInfo& info = m_generationInfo[i];
+        if (info.alive())
+            fprintf(stderr, "    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
+        else
+            fprintf(stderr, "    % 3d:[__][__]", i);
+        if (info.registerFormat() == DataFormatDouble)
+            fprintf(stderr, ":fpr%d\n", info.fpr());
+        else if (info.registerFormat() != DataFormatNone) {
+            ASSERT(info.gpr() != InvalidGPRReg);
+            fprintf(stderr, ":%s\n", GPRInfo::debugName(info.gpr()));
+        } else
+            fprintf(stderr, "\n");
+    }
+    if (label)
+        fprintf(stderr, "</%s>\n", label);
+}
+#endif
+
+
+#if DFG_CONSISTENCY_CHECK
+void JITCodeGenerator::checkConsistency()
+{
+    bool failed = false;
+
+    for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+        if (iter.isLocked()) {
+            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
+            failed = true;
+        }
+    }
+    for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+        if (iter.isLocked()) {
+            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
+            failed = true;
+        }
+    }
+
+    for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
+        VirtualRegister virtualRegister = (VirtualRegister)i;
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        if (!info.alive())
+            continue;
+        switch (info.registerFormat()) {
+        case DataFormatNone:
+            break;
+        case DataFormatInteger:
+        case DataFormatCell:
+        case DataFormatJS:
+        case DataFormatJSInteger:
+        case DataFormatJSDouble:
+        case DataFormatJSCell: {
+            GPRReg gpr = info.gpr();
+            ASSERT(gpr != InvalidGPRReg);
+            if (m_gprs.name(gpr) != virtualRegister) {
+                fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
+                failed = true;
+            }
+            break;
+        }
+        case DataFormatDouble: {
+            FPRReg fpr = info.fpr();
+            ASSERT(fpr != InvalidFPRReg);
+            if (m_fprs.name(fpr) != virtualRegister) {
+                fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
+                failed = true;
+            }
+            break;
+        }
+        }
+    }
+
+    for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+        VirtualRegister virtualRegister = iter.name();
+        if (virtualRegister == InvalidVirtualRegister)
+            continue;
+
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        if (iter.regID() != info.gpr()) {
+            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+            failed = true;
+        }
+    }
+
+    for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+        VirtualRegister virtualRegister = iter.name();
+        if (virtualRegister == InvalidVirtualRegister)
+            continue;
+
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        if (iter.regID() != info.fpr()) {
+            fprintf(stderr, "DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
+            failed = true;
+        }
+    }
+
+    if (failed) {
+        dump();
+        CRASH();
+    }
+}
+#endif
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    m_gpr = m_jit->allocate();
+}
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(op1.gpr());
+    else
+        m_gpr = m_jit->allocate();
+}
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(op1.gpr());
+    else if (m_jit->canReuse(op2.index()))
+        m_gpr = m_jit->reuse(op2.gpr());
+    else
+        m_gpr = m_jit->allocate();
+}
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(op1.gpr());
+    else
+        m_gpr = m_jit->allocate();
+}
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit, IntegerOperand& op1, IntegerOperand& op2)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(op1.gpr());
+    else if (m_jit->canReuse(op2.index()))
+        m_gpr = m_jit->reuse(op2.gpr());
+    else
+        m_gpr = m_jit->allocate();
+}
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit, SpeculateCellOperand& op1)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(op1.gpr());
+    else
+        m_gpr = m_jit->allocate();
+}
+
+GPRTemporary::GPRTemporary(JITCodeGenerator* jit, JSValueOperand& op1)
+    : m_jit(jit)
+    , m_gpr(InvalidGPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_gpr = m_jit->reuse(op1.gpr());
+    else
+        m_gpr = m_jit->allocate();
+}
+
+FPRTemporary::FPRTemporary(JITCodeGenerator* jit)
+    : m_jit(jit)
+    , m_fpr(InvalidFPRReg)
+{
+    m_fpr = m_jit->fprAllocate();
+}
+
+FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1)
+    : m_jit(jit)
+    , m_fpr(InvalidFPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_fpr = m_jit->reuse(op1.fpr());
+    else
+        m_fpr = m_jit->fprAllocate();
+}
+
+FPRTemporary::FPRTemporary(JITCodeGenerator* jit, DoubleOperand& op1, DoubleOperand& op2)
+    : m_jit(jit)
+    , m_fpr(InvalidFPRReg)
+{
+    if (m_jit->canReuse(op1.index()))
+        m_fpr = m_jit->reuse(op1.fpr());
+    else if (m_jit->canReuse(op2.index()))
+        m_fpr = m_jit->reuse(op2.fpr());
+    else
+        m_fpr = m_jit->fprAllocate();
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGJITCodeGenerator.h b/dfg/DFGJITCodeGenerator.h
new file mode 100644 (file)
index 0000000..3c0998d
--- /dev/null
@@ -0,0 +1,957 @@
+/*
+ * Copyright (C) 2011 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 DFGJITCodeGenerator_h
+#define DFGJITCodeGenerator_h
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include <dfg/DFGGenerationInfo.h>
+#include <dfg/DFGGraph.h>
+#include <dfg/DFGJITCompiler.h>
+#include <dfg/DFGOperations.h>
+#include <dfg/DFGRegisterBank.h>
+
+namespace JSC { namespace DFG {
+
+class SpeculateIntegerOperand;
+class SpeculateStrictInt32Operand;
+class SpeculateCellOperand;
+
+
+// === JITCodeGenerator ===
+//
+// This class provides common infrastructure used by the speculative &
+// non-speculative JITs. Provides common mechanisms for virtual and
+// physical register management, calls out from JIT code to helper
+// functions, etc.
+class JITCodeGenerator {
+protected:
+    typedef MacroAssembler::TrustedImm32 TrustedImm32;
+    typedef MacroAssembler::Imm32 Imm32;
+
+    // These constants are used to set priorities for spill order for
+    // the register allocator.
+    enum SpillOrder {
+        SpillOrderConstant = 1, // no spill, and cheap fill
+        SpillOrderSpilled = 2,  // no spill
+        SpillOrderJS = 4,       // needs spill
+        SpillOrderCell = 4,     // needs spill
+        SpillOrderInteger = 5,  // needs spill and box
+        SpillOrderDouble = 6,   // needs spill and convert
+    };
+
+
+public:
+    GPRReg fillInteger(NodeIndex, DataFormat& returnFormat);
+    FPRReg fillDouble(NodeIndex);
+    GPRReg fillJSValue(NodeIndex);
+
+    // lock and unlock GPR & FPR registers.
+    void lock(GPRReg reg)
+    {
+        m_gprs.lock(reg);
+    }
+    void lock(FPRReg reg)
+    {
+        m_fprs.lock(reg);
+    }
+    void unlock(GPRReg reg)
+    {
+        m_gprs.unlock(reg);
+    }
+    void unlock(FPRReg reg)
+    {
+        m_fprs.unlock(reg);
+    }
+
+    // Used to check whether a child node is on its last use,
+    // and its machine registers may be reused.
+    bool canReuse(NodeIndex nodeIndex)
+    {
+        VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        return info.canReuse();
+    }
+    GPRReg reuse(GPRReg reg)
+    {
+        m_gprs.lock(reg);
+        return reg;
+    }
+    FPRReg reuse(FPRReg reg)
+    {
+        m_fprs.lock(reg);
+        return reg;
+    }
+
+    // Allocate a gpr/fpr.
+    GPRReg allocate()
+    {
+        VirtualRegister spillMe;
+        GPRReg gpr = m_gprs.allocate(spillMe);
+        if (spillMe != InvalidVirtualRegister)
+            spill(spillMe);
+        return gpr;
+    }
+    FPRReg fprAllocate()
+    {
+        VirtualRegister spillMe;
+        FPRReg fpr = m_fprs.allocate(spillMe);
+        if (spillMe != InvalidVirtualRegister)
+            spill(spillMe);
+        return fpr;
+    }
+
+    // Check whether a VirtualRegsiter is currently in a machine register.
+    // We use this when filling operands to fill those that are already in
+    // machine registers first (by locking VirtualRegsiters that are already
+    // in machine register before filling those that are not we attempt to
+    // avoid spilling values we will need immediately).
+    bool isFilled(NodeIndex nodeIndex)
+    {
+        VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        return info.registerFormat() != DataFormatNone;
+    }
+    bool isFilledDouble(NodeIndex nodeIndex)
+    {
+        VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        return info.registerFormat() == DataFormatDouble;
+    }
+
+protected:
+    JITCodeGenerator(JITCompiler& jit, bool isSpeculative)
+        : m_jit(jit)
+        , m_isSpeculative(isSpeculative)
+        , m_compileIndex(0)
+        , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
+        , m_blockHeads(jit.graph().m_blocks.size())
+    {
+    }
+
+    // These methods convert between doubles, and doubles boxed and JSValues.
+    GPRReg boxDouble(FPRReg fpr, GPRReg gpr)
+    {
+        m_jit.moveDoubleToPtr(fpr, gpr);
+        m_jit.subPtr(GPRInfo::tagTypeNumberRegister, gpr);
+        return gpr;
+    }
+    FPRReg unboxDouble(GPRReg gpr, FPRReg fpr)
+    {
+        m_jit.addPtr(GPRInfo::tagTypeNumberRegister, gpr);
+        m_jit.movePtrToDouble(gpr, fpr);
+        return fpr;
+    }
+    GPRReg boxDouble(FPRReg fpr)
+    {
+        return boxDouble(fpr, allocate());
+    }
+    FPRReg unboxDouble(GPRReg gpr)
+    {
+        return unboxDouble(gpr, fprAllocate());
+    }
+
+    // Called on an operand once it has been consumed by a parent node.
+    void use(NodeIndex nodeIndex)
+    {
+        VirtualRegister virtualRegister = m_jit.graph()[nodeIndex].virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+
+        // use() returns true when the value becomes dead, and any
+        // associated resources may be freed.
+        if (!info.use())
+            return;
+
+        // Release the associated machine registers.
+        DataFormat registerFormat = info.registerFormat();
+        if (registerFormat == DataFormatDouble)
+            m_fprs.release(info.fpr());
+        else if (registerFormat != DataFormatNone)
+            m_gprs.release(info.gpr());
+    }
+
+    // Spill a VirtualRegister to the RegisterFile.
+    void spill(VirtualRegister spillMe)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+
+        // Check the GenerationInfo to see if this value need writing
+        // to the RegisterFile - if not, mark it as spilled & return.
+        if (!info.needsSpill()) {
+            info.setSpilled();
+            return;
+        }
+
+        DataFormat spillFormat = info.registerFormat();
+        if (spillFormat == DataFormatDouble) {
+            // All values are spilled as JSValues, so box the double via a temporary gpr.
+            GPRReg gpr = boxDouble(info.fpr());
+            m_jit.storePtr(gpr, JITCompiler::addressFor(spillMe));
+            unlock(gpr);
+            info.spill(DataFormatJSDouble);
+            return;
+        }
+
+        // The following code handles JSValues, int32s, and cells.
+        ASSERT(spillFormat == DataFormatInteger || spillFormat == DataFormatCell || spillFormat & DataFormatJS);
+
+        GPRReg reg = info.gpr();
+        // We need to box int32 and cell values ...
+        // but on JSVALUE64 boxing a cell is a no-op!
+        if (spillFormat == DataFormatInteger)
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, reg);
+
+        // Spill the value, and record it as spilled in its boxed form.
+        m_jit.storePtr(reg, JITCompiler::addressFor(spillMe));
+        info.spill((DataFormat)(spillFormat | DataFormatJS));
+    }
+
+    // Checks/accessors for constant values.
+    bool isConstant(NodeIndex nodeIndex) { return m_jit.isConstant(nodeIndex); }
+    bool isInt32Constant(NodeIndex nodeIndex) { return m_jit.isInt32Constant(nodeIndex); }
+    bool isDoubleConstant(NodeIndex nodeIndex) { return m_jit.isDoubleConstant(nodeIndex); }
+    bool isJSConstant(NodeIndex nodeIndex) { return m_jit.isJSConstant(nodeIndex); }
+    int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return m_jit.valueOfInt32Constant(nodeIndex); }
+    double valueOfDoubleConstant(NodeIndex nodeIndex) { return m_jit.valueOfDoubleConstant(nodeIndex); }
+    JSValue valueOfJSConstant(NodeIndex nodeIndex) { return m_jit.valueOfJSConstant(nodeIndex); }
+
+    Identifier* identifier(unsigned index)
+    {
+        return &m_jit.codeBlock()->identifier(index);
+    }
+
+    // Spill all VirtualRegisters back to the RegisterFile.
+    void flushRegisters()
+    {
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister) {
+                spill(iter.name());
+                iter.release();
+            }
+        }
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister) {
+                spill(iter.name());
+                iter.release();
+            }
+        }
+    }
+
+#ifndef NDEBUG
+    // Used to ASSERT flushRegisters() has been called prior to
+    // calling out from JIT code to a C helper function.
+    bool isFlushed()
+    {
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                return false;
+        }
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                return false;
+        }
+        return true;
+    }
+#endif
+
+    // Get the JSValue representation of a constant.
+    JSValue constantAsJSValue(NodeIndex nodeIndex)
+    {
+        Node& node = m_jit.graph()[nodeIndex];
+        if (isInt32Constant(nodeIndex))
+            return jsNumber(node.int32Constant());
+        if (isDoubleConstant(nodeIndex))
+            return JSValue(JSValue::EncodeAsDouble, node.numericConstant());
+        ASSERT(isJSConstant(nodeIndex));
+        return valueOfJSConstant(nodeIndex);
+    }
+    MacroAssembler::ImmPtr constantAsJSValueAsImmPtr(NodeIndex nodeIndex)
+    {
+        return MacroAssembler::ImmPtr(JSValue::encode(constantAsJSValue(nodeIndex)));
+    }
+
+    // Helper functions to enable code sharing in implementations of bit/shift ops.
+    void bitOp(NodeType op, int32_t imm, GPRReg op1, GPRReg result)
+    {
+        switch (op) {
+        case BitAnd:
+            m_jit.and32(Imm32(imm), op1, result);
+            break;
+        case BitOr:
+            m_jit.or32(Imm32(imm), op1, result);
+            break;
+        case BitXor:
+            m_jit.xor32(Imm32(imm), op1, result);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+    void bitOp(NodeType op, GPRReg op1, GPRReg op2, GPRReg result)
+    {
+        switch (op) {
+        case BitAnd:
+            m_jit.and32(op1, op2, result);
+            break;
+        case BitOr:
+            m_jit.or32(op1, op2, result);
+            break;
+        case BitXor:
+            m_jit.xor32(op1, op2, result);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+    void shiftOp(NodeType op, GPRReg op1, int32_t shiftAmount, GPRReg result)
+    {
+        switch (op) {
+        case BitRShift:
+            m_jit.rshift32(op1, Imm32(shiftAmount), result);
+            break;
+        case BitLShift:
+            m_jit.lshift32(op1, Imm32(shiftAmount), result);
+            break;
+        case BitURShift:
+            m_jit.urshift32(op1, Imm32(shiftAmount), result);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+    void shiftOp(NodeType op, GPRReg op1, GPRReg shiftAmount, GPRReg result)
+    {
+        switch (op) {
+        case BitRShift:
+            m_jit.rshift32(op1, shiftAmount, result);
+            break;
+        case BitLShift:
+            m_jit.lshift32(op1, shiftAmount, result);
+            break;
+        case BitURShift:
+            m_jit.urshift32(op1, shiftAmount, result);
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    // Called once a node has completed code generation but prior to setting
+    // its result, to free up its children. (This must happen prior to setting
+    // the nodes result, since the node may have the same VirtualRegister as
+    // a child, and as such will use the same GeneratioInfo).
+    void useChildren(Node&);
+
+    // These method called to initialize the the GenerationInfo
+    // to describe the result of an operation.
+    void integerResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatInteger)
+    {
+        Node& node = m_jit.graph()[nodeIndex];
+        useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+
+        if (format == DataFormatInteger) {
+            m_jit.jitAssertIsInt32(reg);
+            m_gprs.retain(reg, virtualRegister, SpillOrderInteger);
+            info.initInteger(nodeIndex, node.refCount(), reg);
+        } else {
+            ASSERT(format == DataFormatJSInteger);
+            m_jit.jitAssertIsJSInt32(reg);
+            m_gprs.retain(reg, virtualRegister, SpillOrderJS);
+            info.initJSValue(nodeIndex, node.refCount(), reg, format);
+        }
+    }
+    void noResult(NodeIndex nodeIndex)
+    {
+        Node& node = m_jit.graph()[nodeIndex];
+        useChildren(node);
+    }
+    void cellResult(GPRReg reg, NodeIndex nodeIndex)
+    {
+        Node& node = m_jit.graph()[nodeIndex];
+        useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(reg, virtualRegister, SpillOrderCell);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initCell(nodeIndex, node.refCount(), reg);
+    }
+    void jsValueResult(GPRReg reg, NodeIndex nodeIndex, DataFormat format = DataFormatJS)
+    {
+        if (format == DataFormatJSInteger)
+            m_jit.jitAssertIsJSInt32(reg);
+        
+        Node& node = m_jit.graph()[nodeIndex];
+        useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(reg, virtualRegister, SpillOrderJS);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initJSValue(nodeIndex, node.refCount(), reg, format);
+    }
+    void doubleResult(FPRReg reg, NodeIndex nodeIndex)
+    {
+        Node& node = m_jit.graph()[nodeIndex];
+        useChildren(node);
+
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_fprs.retain(reg, virtualRegister, SpillOrderDouble);
+        GenerationInfo& info = m_generationInfo[virtualRegister];
+        info.initDouble(nodeIndex, node.refCount(), reg);
+    }
+    void initConstantInfo(NodeIndex nodeIndex)
+    {
+        ASSERT(isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex) || isJSConstant(nodeIndex));
+        Node& node = m_jit.graph()[nodeIndex];
+        m_generationInfo[node.virtualRegister()].initConstant(nodeIndex, node.refCount());
+    }
+
+    // These methods used to sort arguments into the correct registers.
+    template<GPRReg destA, GPRReg destB>
+    void setupTwoStubArgs(GPRReg srcA, GPRReg srcB)
+    {
+        // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
+        // (1) both are already in arg regs, the right way around.
+        // (2) both are already in arg regs, the wrong way around.
+        // (3) neither are currently in arg registers.
+        // (4) srcA in in its correct reg.
+        // (5) srcA in in the incorrect reg.
+        // (6) srcB in in its correct reg.
+        // (7) srcB in in the incorrect reg.
+        //
+        // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
+        // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
+        // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
+        // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
+
+        if (srcB != destA) {
+            // Handle the easy cases - two simple moves.
+            m_jit.move(srcA, destA);
+            m_jit.move(srcB, destB);
+        } else if (srcA != destB) {
+            // Handle the non-swap case - just put srcB in place first.
+            m_jit.move(srcB, destB);
+            m_jit.move(srcA, destA);
+        } else
+            m_jit.swap(destB, destB);
+    }
+    template<FPRReg destA, FPRReg destB>
+    void setupTwoStubArgs(FPRReg srcA, FPRReg srcB)
+    {
+        // Assuming that srcA != srcB, there are 7 interesting states the registers may be in:
+        // (1) both are already in arg regs, the right way around.
+        // (2) both are already in arg regs, the wrong way around.
+        // (3) neither are currently in arg registers.
+        // (4) srcA in in its correct reg.
+        // (5) srcA in in the incorrect reg.
+        // (6) srcB in in its correct reg.
+        // (7) srcB in in the incorrect reg.
+        //
+        // The trivial approach is to simply emit two moves, to put srcA in place then srcB in
+        // place (the MacroAssembler will omit redundant moves). This apporach will be safe in
+        // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2
+        // (requires a swap) and 7 (must move srcB first, to avoid trampling.)
+
+        if (srcB != destA) {
+            // Handle the easy cases - two simple moves.
+            m_jit.moveDouble(srcA, destA);
+            m_jit.moveDouble(srcB, destB);
+            return;
+        }
+        
+        if (srcA != destB) {
+            // Handle the non-swap case - just put srcB in place first.
+            m_jit.moveDouble(srcB, destB);
+            m_jit.moveDouble(srcA, destA);
+            return;
+        }
+
+        ASSERT(srcB == destA && srcA == destB);
+        // Need to swap; pick a temporary register.
+        FPRReg temp;
+        if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3)
+            temp = FPRInfo::argumentFPR3;
+        else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2)
+            temp = FPRInfo::argumentFPR2;
+        else {
+            ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1);
+            temp = FPRInfo::argumentFPR1;
+        }
+        m_jit.moveDouble(destA, temp);
+        m_jit.moveDouble(destB, destA);
+        m_jit.moveDouble(temp, destB);
+    }
+    void setupStubArguments(GPRReg arg1, GPRReg arg2)
+    {
+        setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
+    }
+    void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        // If neither of arg2/arg3 are in our way, then we can move arg1 into place.
+        // Then we can use setupTwoStubArgs to fix arg2/arg3.
+        if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) {
+            m_jit.move(arg1, GPRInfo::argumentGPR1);
+            setupTwoStubArgs<GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg2, arg3);
+            return;
+        }
+
+        // If neither of arg1/arg3 are in our way, then we can move arg2 into place.
+        // Then we can use setupTwoStubArgs to fix arg1/arg3.
+        if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) {
+            m_jit.move(arg2, GPRInfo::argumentGPR2);
+            setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR3>(arg1, arg3);
+            return;
+        }
+
+        // If neither of arg1/arg2 are in our way, then we can move arg3 into place.
+        // Then we can use setupTwoStubArgs to fix arg1/arg2.
+        if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) {
+            m_jit.move(arg3, GPRInfo::argumentGPR3);
+            setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(arg1, arg2);
+            return;
+        }
+
+        // If we get here, we haven't been able to move any of arg1/arg2/arg3.
+        // Since all three are blocked, then all three must already be in the argument register.
+        // But are they in the right ones?
+
+        // First, ensure arg1 is in place.
+        if (arg1 != GPRInfo::argumentGPR1) {
+            m_jit.swap(arg1, GPRInfo::argumentGPR1);
+
+            // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be.
+            ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1);
+            // If arg2 was in argumentGPR1 it no longer is (due to the swap).
+            // Otherwise arg3 must have been. Mark him as moved.
+            if (arg2 == GPRInfo::argumentGPR1)
+                arg2 = arg1;
+            else
+                arg3 = arg1;
+        }
+
+        // Either arg2 & arg3 need swapping, or we're all done.
+        ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3)
+            || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2));
+
+        if (arg2 != GPRInfo::argumentGPR2)
+            m_jit.swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3);
+    }
+
+    // These methods add calls to C++ helper functions.
+    void callOperation(J_DFGOperation_EJP operation, GPRReg result, GPRReg arg1, void* pointer)
+    {
+        ASSERT(isFlushed());
+
+        m_jit.move(arg1, GPRInfo::argumentGPR1);
+        m_jit.move(JITCompiler::TrustedImmPtr(pointer), GPRInfo::argumentGPR2);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+    }
+    void callOperation(J_DFGOperation_EJI operation, GPRReg result, GPRReg arg1, Identifier* identifier)
+    {
+        callOperation((J_DFGOperation_EJP)operation, result, arg1, identifier);
+    }
+    void callOperation(J_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
+    {
+        ASSERT(isFlushed());
+
+        m_jit.move(arg1, GPRInfo::argumentGPR1);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+    }
+    void callOperation(Z_DFGOperation_EJ operation, GPRReg result, GPRReg arg1)
+    {
+        ASSERT(isFlushed());
+
+        m_jit.move(arg1, GPRInfo::argumentGPR1);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+    }
+    void callOperation(Z_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        ASSERT(isFlushed());
+
+        setupStubArguments(arg1, arg2);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+    }
+    void callOperation(J_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        ASSERT(isFlushed());
+
+        setupStubArguments(arg1, arg2);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+        m_jit.move(GPRInfo::returnValueGPR, result);
+    }
+    void callOperation(V_DFGOperation_EJJP operation, GPRReg arg1, GPRReg arg2, void* pointer)
+    {
+        ASSERT(isFlushed());
+
+        setupStubArguments(arg1, arg2);
+        m_jit.move(JITCompiler::TrustedImmPtr(pointer), GPRInfo::argumentGPR3);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+    }
+    void callOperation(V_DFGOperation_EJJI operation, GPRReg arg1, GPRReg arg2, Identifier* identifier)
+    {
+        callOperation((V_DFGOperation_EJJP)operation, arg1, arg2, identifier);
+    }
+    void callOperation(V_DFGOperation_EJJJ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        ASSERT(isFlushed());
+
+        setupStubArguments(arg1, arg2, arg3);
+        m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+
+        appendCallWithExceptionCheck(operation);
+    }
+    void callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2)
+    {
+        ASSERT(isFlushed());
+
+        setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(arg1, arg2);
+
+        m_jit.appendCall(operation);
+        m_jit.moveDouble(FPRInfo::returnValueFPR, result);
+    }
+
+    void appendCallWithExceptionCheck(const FunctionPtr& function)
+    {
+        m_jit.appendCallWithExceptionCheck(function, m_jit.graph()[m_compileIndex].exceptionInfo);
+    }
+
+    void addBranch(const MacroAssembler::Jump& jump, BlockIndex destination)
+    {
+        m_branches.append(BranchRecord(jump, destination));
+    }
+
+    void linkBranches()
+    {
+        for (size_t i = 0; i < m_branches.size(); ++i) {
+            BranchRecord& branch = m_branches[i];
+            branch.jump.linkTo(m_blockHeads[branch.destination], &m_jit);
+        }
+    }
+
+#ifndef NDEBUG
+    void dump(const char* label = 0);
+#endif
+
+#if DFG_CONSISTENCY_CHECK
+    void checkConsistency();
+#else
+    void checkConsistency() {}
+#endif
+
+    // The JIT, while also provides MacroAssembler functionality.
+    JITCompiler& m_jit;
+    // This flag is used to distinguish speculative and non-speculative
+    // code generation. This is significant when filling spilled values
+    // from the RegisterFile. When spilling we attempt to store information
+    // as to the type of boxed value being stored (int32, double, cell), and
+    // when filling on the speculative path we will retrieve this type info
+    // where available. On the non-speculative path, however, we cannot rely
+    // on the spill format info, since the a value being loaded might have
+    // been spilled by either the speculative or non-speculative paths (where
+    // we entered the non-speculative path on an intervening bail-out), and
+    // the value may have been boxed differently on the two paths.
+    bool m_isSpeculative;
+    // The current node being generated.
+    BlockIndex m_block;
+    NodeIndex m_compileIndex;
+    // Virtual and physical register maps.
+    Vector<GenerationInfo, 32> m_generationInfo;
+    RegisterBank<GPRInfo> m_gprs;
+    RegisterBank<FPRInfo> m_fprs;
+
+    Vector<MacroAssembler::Label> m_blockHeads;
+    struct BranchRecord {
+        BranchRecord(MacroAssembler::Jump jump, BlockIndex destination)
+            : jump(jump)
+            , destination(destination)
+        {
+        }
+
+        MacroAssembler::Jump jump;
+        BlockIndex destination;
+    };
+    Vector<BranchRecord, 8> m_branches;
+};
+
+// === Operand types ===
+//
+// IntegerOperand, DoubleOperand and JSValueOperand.
+//
+// These classes are used to lock the operands to a node into machine
+// registers. These classes implement of pattern of locking a value
+// into register at the point of construction only if it is already in
+// registers, and otherwise loading it lazily at the point it is first
+// used. We do so in order to attempt to avoid spilling one operand
+// in order to make space available for another.
+
+class IntegerOperand {
+public:
+    explicit IntegerOperand(JITCodeGenerator* jit, NodeIndex index)
+        : m_jit(jit)
+        , m_index(index)
+        , m_gprOrInvalid(InvalidGPRReg)
+#ifndef NDEBUG
+        , m_format(DataFormatNone)
+#endif
+    {
+        ASSERT(m_jit);
+        if (jit->isFilled(index))
+            gpr();
+    }
+
+    ~IntegerOperand()
+    {
+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    DataFormat format()
+    {
+        gpr(); // m_format is set when m_gpr is locked.
+        ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
+        return m_format;
+    }
+
+    GPRReg gpr()
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillInteger(index(), m_format);
+        return m_gprOrInvalid;
+    }
+
+private:
+    JITCodeGenerator* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+    DataFormat m_format;
+};
+
+class DoubleOperand {
+public:
+    explicit DoubleOperand(JITCodeGenerator* jit, NodeIndex index)
+        : m_jit(jit)
+        , m_index(index)
+        , m_fprOrInvalid(InvalidFPRReg)
+    {
+        ASSERT(m_jit);
+        if (jit->isFilledDouble(index))
+            fpr();
+    }
+
+    ~DoubleOperand()
+    {
+        ASSERT(m_fprOrInvalid != InvalidFPRReg);
+        m_jit->unlock(m_fprOrInvalid);
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    FPRReg fpr()
+    {
+        if (m_fprOrInvalid == InvalidFPRReg)
+            m_fprOrInvalid = m_jit->fillDouble(index());
+        return m_fprOrInvalid;
+    }
+
+private:
+    JITCodeGenerator* m_jit;
+    NodeIndex m_index;
+    FPRReg m_fprOrInvalid;
+};
+
+class JSValueOperand {
+public:
+    explicit JSValueOperand(JITCodeGenerator* jit, NodeIndex index)
+        : m_jit(jit)
+        , m_index(index)
+        , m_gprOrInvalid(InvalidGPRReg)
+    {
+        ASSERT(m_jit);
+        if (jit->isFilled(index))
+            gpr();
+    }
+
+    ~JSValueOperand()
+    {
+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    GPRReg gpr()
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillJSValue(index());
+        return m_gprOrInvalid;
+    }
+
+private:
+    JITCodeGenerator* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+};
+
+
+// === Temporaries ===
+//
+// These classes are used to allocate temporary registers.
+// A mechanism is provided to attempt to reuse the registers
+// currently allocated to child nodes whose value is consumed
+// by, and not live after, this operation.
+
+class GPRTemporary {
+public:
+    GPRTemporary(JITCodeGenerator*);
+    GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&);
+    GPRTemporary(JITCodeGenerator*, SpeculateIntegerOperand&, SpeculateIntegerOperand&);
+    GPRTemporary(JITCodeGenerator*, IntegerOperand&);
+    GPRTemporary(JITCodeGenerator*, IntegerOperand&, IntegerOperand&);
+    GPRTemporary(JITCodeGenerator*, SpeculateCellOperand&);
+    GPRTemporary(JITCodeGenerator*, JSValueOperand&);
+
+    ~GPRTemporary()
+    {
+        m_jit->unlock(gpr());
+    }
+
+    GPRReg gpr()
+    {
+        ASSERT(m_gpr != InvalidGPRReg);
+        return m_gpr;
+    }
+
+protected:
+    GPRTemporary(JITCodeGenerator* jit, GPRReg lockedGPR)
+        : m_jit(jit)
+        , m_gpr(lockedGPR)
+    {
+    }
+
+private:
+    JITCodeGenerator* m_jit;
+    GPRReg m_gpr;
+};
+
+class FPRTemporary {
+public:
+    FPRTemporary(JITCodeGenerator*);
+    FPRTemporary(JITCodeGenerator*, DoubleOperand&);
+    FPRTemporary(JITCodeGenerator*, DoubleOperand&, DoubleOperand&);
+
+    ~FPRTemporary()
+    {
+        m_jit->unlock(fpr());
+    }
+
+    FPRReg fpr() const
+    {
+        ASSERT(m_fpr != InvalidFPRReg);
+        return m_fpr;
+    }
+
+protected:
+    FPRTemporary(JITCodeGenerator* jit, FPRReg lockedFPR)
+        : m_jit(jit)
+        , m_fpr(lockedFPR)
+    {
+    }
+
+private:
+    JITCodeGenerator* m_jit;
+    FPRReg m_fpr;
+};
+
+
+// === Results ===
+//
+// These classes lock the result of a call to a C++ helper function.
+
+class GPRResult : public GPRTemporary {
+public:
+    GPRResult(JITCodeGenerator* jit)
+        : GPRTemporary(jit, lockedResult(jit))
+    {
+    }
+
+private:
+    static GPRReg lockedResult(JITCodeGenerator* jit)
+    {
+        jit->lock(GPRInfo::returnValueGPR);
+        return GPRInfo::returnValueGPR;
+    }
+};
+
+class FPRResult : public FPRTemporary {
+public:
+    FPRResult(JITCodeGenerator* jit)
+        : FPRTemporary(jit, lockedResult(jit))
+    {
+    }
+
+private:
+    static FPRReg lockedResult(JITCodeGenerator* jit)
+    {
+        jit->lock(FPRInfo::returnValueFPR);
+        return FPRInfo::returnValueFPR;
+    }
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
+
diff --git a/dfg/DFGJITCompiler.cpp b/dfg/DFGJITCompiler.cpp
new file mode 100644 (file)
index 0000000..9e946d2
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGJITCompiler.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "DFGJITCodeGenerator.h"
+#include "DFGNonSpeculativeJIT.h"
+#include "DFGOperations.h"
+#include "DFGRegisterBank.h"
+#include "DFGSpeculativeJIT.h"
+#include "JSGlobalData.h"
+#include "LinkBuffer.h"
+
+namespace JSC { namespace DFG {
+
+// This method used to fill a numeric value to a FPR when linking speculative -> non-speculative.
+void JITCompiler::fillNumericToDouble(NodeIndex nodeIndex, FPRReg fpr, GPRReg temporary)
+{
+    Node& node = graph()[nodeIndex];
+
+    if (node.isConstant()) {
+        ASSERT(node.op == DoubleConstant);
+        move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), temporary);
+        movePtrToDouble(temporary, fpr);
+    } else {
+        loadPtr(addressFor(node.virtualRegister()), temporary);
+        Jump isInteger = branchPtr(MacroAssembler::AboveOrEqual, temporary, GPRInfo::tagTypeNumberRegister);
+        jitAssertIsJSDouble(temporary);
+        addPtr(GPRInfo::tagTypeNumberRegister, temporary);
+        movePtrToDouble(temporary, fpr);
+        Jump hasUnboxedDouble = jump();
+        isInteger.link(this);
+        convertInt32ToDouble(temporary, fpr);
+        hasUnboxedDouble.link(this);
+    }
+}
+
+// This method used to fill an integer value to a GPR when linking speculative -> non-speculative.
+void JITCompiler::fillInt32ToInteger(NodeIndex nodeIndex, GPRReg gpr)
+{
+    Node& node = graph()[nodeIndex];
+
+    if (node.isConstant()) {
+        ASSERT(node.op == Int32Constant);
+        move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+    } else {
+#if DFG_JIT_ASSERT
+        // Redundant load, just so we can check the tag!
+        loadPtr(addressFor(node.virtualRegister()), gpr);
+        jitAssertIsJSInt32(gpr);
+#endif
+        load32(addressFor(node.virtualRegister()), gpr);
+    }
+}
+
+// This method used to fill a JSValue to a GPR when linking speculative -> non-speculative.
+void JITCompiler::fillToJS(NodeIndex nodeIndex, GPRReg gpr)
+{
+    Node& node = graph()[nodeIndex];
+
+    if (node.isConstant()) {
+        if (isInt32Constant(nodeIndex)) {
+            JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
+            move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+        } else if (isDoubleConstant(nodeIndex)) {
+            JSValue jsValue(JSValue::EncodeAsDouble, valueOfDoubleConstant(nodeIndex));
+            move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+        } else {
+            ASSERT(isJSConstant(nodeIndex));
+            JSValue jsValue = valueOfJSConstant(nodeIndex);
+            move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
+        }
+        return;
+    }
+
+    loadPtr(addressFor(node.virtualRegister()), gpr);
+}
+
+void JITCompiler::jumpFromSpeculativeToNonSpeculative(const SpeculationCheck& check, const EntryLocation& entry, SpeculationRecovery* recovery)
+{
+    ASSERT(check.m_nodeIndex == entry.m_nodeIndex);
+
+    // Link the jump from the Speculative path to here.
+    check.m_check.link(this);
+
+    // Does this speculation check require any additional recovery to be performed,
+    // to restore any state that has been overwritten before we enter back in to the
+    // non-speculative path.
+    if (recovery) {
+        // The only additional recovery we currently support is for integer add operation
+        ASSERT(recovery->type() == SpeculativeAdd);
+        // Revert the add.
+        sub32(recovery->src(), recovery->dest());
+    }
+
+    // FIXME: - This is hideously inefficient!
+    // Where a value is live in a register in the speculative path, and is required in a register
+    // on the non-speculative path, we should not need to be spilling it and reloading (we may
+    // need to spill anyway, if the value is marked as spilled on the non-speculative path).
+    // This may also be spilling values that don't need spilling, e.g. are already spilled,
+    // are constants, or are arguments.
+
+    // Spill all GPRs in use by the speculative path.
+    for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) {
+        NodeIndex nodeIndex = check.m_gprInfo[index].nodeIndex;
+        if (nodeIndex == NoNode)
+            continue;
+
+        DataFormat dataFormat = check.m_gprInfo[index].format;
+        VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister();
+
+        ASSERT(dataFormat == DataFormatInteger || DataFormatCell || dataFormat & DataFormatJS);
+        if (dataFormat == DataFormatInteger)
+            orPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::toRegister(index));
+        storePtr(GPRInfo::toRegister(index), addressFor(virtualRegister));
+    }
+
+    // Spill all FPRs in use by the speculative path.
+    for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) {
+        NodeIndex nodeIndex = check.m_fprInfo[index];
+        if (nodeIndex == NoNode)
+            continue;
+
+        VirtualRegister virtualRegister = graph()[nodeIndex].virtualRegister();
+
+        moveDoubleToPtr(FPRInfo::toRegister(index), GPRInfo::regT0);
+        subPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
+        storePtr(GPRInfo::regT0, addressFor(virtualRegister));
+    }
+
+    // Fill all FPRs in use by the non-speculative path.
+    for (unsigned index = 0; index < FPRInfo::numberOfRegisters; ++index) {
+        NodeIndex nodeIndex = entry.m_fprInfo[index];
+        if (nodeIndex == NoNode)
+            continue;
+
+        fillNumericToDouble(nodeIndex, FPRInfo::toRegister(index), GPRInfo::regT0);
+    }
+
+    // Fill all GPRs in use by the non-speculative path.
+    for (unsigned index = 0; index < GPRInfo::numberOfRegisters; ++index) {
+        NodeIndex nodeIndex = entry.m_gprInfo[index].nodeIndex;
+        if (nodeIndex == NoNode)
+            continue;
+
+        DataFormat dataFormat = entry.m_gprInfo[index].format;
+        if (dataFormat == DataFormatInteger)
+            fillInt32ToInteger(nodeIndex, GPRInfo::toRegister(index));
+        else {
+            ASSERT(dataFormat & DataFormatJS || dataFormat == DataFormatCell); // Treat cell as JSValue for now!
+            fillToJS(nodeIndex, GPRInfo::toRegister(index));
+            // FIXME: For subtypes of DataFormatJS, should jitAssert the subtype?
+        }
+    }
+
+    // Jump into the non-speculative path.
+    jump(entry.m_entry);
+}
+
+void JITCompiler::linkSpeculationChecks(SpeculativeJIT& speculative, NonSpeculativeJIT& nonSpeculative)
+{
+    // Iterators to walk over the set of bail outs & corresponding entry points.
+    SpeculationCheckVector::Iterator checksIter = speculative.speculationChecks().begin();
+    SpeculationCheckVector::Iterator checksEnd = speculative.speculationChecks().end();
+    NonSpeculativeJIT::EntryLocationVector::Iterator entriesIter = nonSpeculative.entryLocations().begin();
+    NonSpeculativeJIT::EntryLocationVector::Iterator entriesEnd = nonSpeculative.entryLocations().end();
+
+    // Iterate over the speculation checks.
+    while (checksIter != checksEnd) {
+        // For every bail out from the speculative path, we must have provided an entry point
+        // into the non-speculative one.
+        ASSERT(checksIter->m_nodeIndex == entriesIter->m_nodeIndex);
+
+        // There may be multiple bail outs that map to the same entry point!
+        do {
+            ASSERT(checksIter != checksEnd);
+            ASSERT(entriesIter != entriesEnd);
+
+            // Plant code to link this speculation failure.
+            const SpeculationCheck& check = *checksIter;
+            const EntryLocation& entry = *entriesIter;
+            jumpFromSpeculativeToNonSpeculative(check, entry, speculative.speculationRecovery(check.m_recoveryIndex));
+             ++checksIter;
+        } while (checksIter != checksEnd && checksIter->m_nodeIndex == entriesIter->m_nodeIndex);
+         ++entriesIter;
+    }
+
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56289
+    ASSERT(!(checksIter != checksEnd));
+    ASSERT(!(entriesIter != entriesEnd));
+}
+
+void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck)
+{
+    // === Stage 1 - Function header code generation ===
+    //
+    // This code currently matches the old JIT. In the function header we need to
+    // pop the return address (since we do not allow any recursion on the machine
+    // stack), and perform a fast register file check.
+
+    // This is the main entry point, without performing an arity check.
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56292
+    // We'll need to convert the remaining cti_ style calls (specifically the register file
+    // check) which will be dependent on stack layout. (We'd need to account for this in
+    // both normal return code and when jumping to an exception handler).
+    preserveReturnAddressAfterCall(GPRInfo::regT2);
+    emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
+    // If we needed to perform an arity check we will already have moved the return address,
+    // so enter after this.
+    Label fromArityCheck(this);
+
+    // Setup a pointer to the codeblock in the CallFrameHeader.
+    emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
+
+    // Plant a check that sufficient space is available in the RegisterFile.
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=56291
+    addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister, GPRInfo::regT1);
+    Jump registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), GPRInfo::regT1);
+    // Return here after register file check.
+    Label fromRegisterFileCheck = label();
+
+
+    // === Stage 2 - Function body code generation ===
+    //
+    // We generate the speculative code path, followed by the non-speculative
+    // code for the function. Next we need to link the two together, making
+    // bail-outs from the speculative path jump to the corresponding point on
+    // the non-speculative one (and generating any code necessary to juggle
+    // register values around, rebox values, and ensure spilled, to match the
+    // non-speculative path's requirements).
+
+#if DFG_JIT_BREAK_ON_EVERY_FUNCTION
+    // Handy debug tool!
+    breakpoint();
+#endif
+
+    // First generate the speculative path.
+    Label speculativePathBegin = label();
+    SpeculativeJIT speculative(*this);
+#if !DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE
+    bool compiledSpeculative = speculative.compile();
+#else
+    bool compiledSpeculative = false;
+#endif
+
+    // Next, generate the non-speculative path. We pass this a SpeculationCheckIndexIterator
+    // to allow it to check which nodes in the graph may bail out, and may need to reenter the
+    // non-speculative path.
+    if (compiledSpeculative) {
+        SpeculationCheckIndexIterator checkIterator(speculative.speculationChecks());
+        NonSpeculativeJIT nonSpeculative(*this);
+        nonSpeculative.compile(checkIterator);
+
+        // Link the bail-outs from the speculative path to the corresponding entry points into the non-speculative one.
+        linkSpeculationChecks(speculative, nonSpeculative);
+    } else {
+        // If compilation through the SpeculativeJIT failed, throw away the code we generated.
+        m_calls.clear();
+        rewindToLabel(speculativePathBegin);
+
+        SpeculationCheckVector noChecks;
+        SpeculationCheckIndexIterator checkIterator(noChecks);
+        NonSpeculativeJIT nonSpeculative(*this);
+        nonSpeculative.compile(checkIterator);
+    }
+
+    // === Stage 3 - Function footer code generation ===
+    //
+    // Generate code to lookup and jump to exception handlers, to perform the slow
+    // register file check (if the fast one in the function header fails), and
+    // generate the entry point with arity check.
+
+    // Iterate over the m_calls vector, checking for exception checks,
+    // and linking them to here.
+    unsigned exceptionCheckCount = 0;
+    for (unsigned i = 0; i < m_calls.size(); ++i) {
+        Jump& exceptionCheck = m_calls[i].m_exceptionCheck;
+        if (exceptionCheck.isSet()) {
+            exceptionCheck.link(this);
+            ++exceptionCheckCount;
+        }
+    }
+    // If any exception checks were linked, generate code to lookup a handler.
+    if (exceptionCheckCount) {
+        // lookupExceptionHandler is passed two arguments, exec (the CallFrame*), and
+        // an identifier for the operation that threw the exception, which we can use
+        // to look up handler information. The identifier we use is the return address
+        // of the call out from JIT code that threw the exception; this is still
+        // available on the stack, just below the stack pointer!
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        peek(GPRInfo::argumentGPR1, -1);
+        m_calls.append(CallRecord(call(), lookupExceptionHandler));
+        // lookupExceptionHandler leaves the handler CallFrame* in the returnValueGPR,
+        // and the address of the handler in returnValueGPR2.
+        jump(GPRInfo::returnValueGPR2);
+    }
+
+    // Generate the register file check; if the fast check in the function head fails,
+    // we need to call out to a helper function to check whether more space is available.
+    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
+    registerFileCheck.link(this);
+    move(stackPointerRegister, GPRInfo::argumentGPR0);
+    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    Call callRegisterFileCheck = call();
+    jump(fromRegisterFileCheck);
+
+    // The fast entry point into a function does not check the correct number of arguments
+    // have been passed to the call (we only use the fast entry point where we can statically
+    // determine the correct number of arguments have been passed, or have already checked).
+    // In cases where an arity check is necessary, we enter here.
+    // FIXME: change this from a cti call to a DFG style operation (normal C calling conventions).
+    Label arityCheck = label();
+    preserveReturnAddressAfterCall(GPRInfo::regT2);
+    emitPutToCallFrameHeader(GPRInfo::regT2, RegisterFile::ReturnPC);
+    branch32(Equal, GPRInfo::regT1, Imm32(m_codeBlock->m_numParameters)).linkTo(fromArityCheck, this);
+    move(stackPointerRegister, GPRInfo::argumentGPR0);
+    poke(GPRInfo::callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    Call callArityCheck = call();
+    move(GPRInfo::regT0, GPRInfo::callFrameRegister);
+    jump(fromArityCheck);
+
+
+    // === Stage 4 - Link ===
+    //
+    // Link the code, populate data in CodeBlock data structures.
+
+    LinkBuffer linkBuffer(*m_globalData, this, m_globalData->executableAllocator);
+
+#if DFG_DEBUG_VERBOSE
+    fprintf(stderr, "JIT code start at %p\n", linkBuffer.debugAddress());
+#endif
+
+    // Link all calls out from the JIT code to their respective functions.
+    for (unsigned i = 0; i < m_calls.size(); ++i)
+        linkBuffer.link(m_calls[i].m_call, m_calls[i].m_function);
+
+    if (m_codeBlock->needsCallReturnIndices()) {
+        m_codeBlock->callReturnIndexVector().reserveCapacity(exceptionCheckCount);
+        for (unsigned i = 0; i < m_calls.size(); ++i) {
+            if (m_calls[i].m_exceptionCheck.isSet()) {
+                unsigned returnAddressOffset = linkBuffer.returnAddressOffset(m_calls[i].m_call);
+                unsigned exceptionInfo = m_calls[i].m_exceptionInfo;
+                m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(returnAddressOffset, exceptionInfo));
+            }
+        }
+    }
+
+    // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs.
+    linkBuffer.link(callRegisterFileCheck, cti_register_file_check);
+    linkBuffer.link(callArityCheck, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck);
+
+    entryWithArityCheck = linkBuffer.locationOf(arityCheck);
+    entry = linkBuffer.finalizeCode();
+}
+
+#if DFG_JIT_ASSERT
+void JITCompiler::jitAssertIsInt32(GPRReg gpr)
+{
+#if CPU(X86_64)
+    Jump checkInt32 = branchPtr(BelowOrEqual, gpr, TrustedImmPtr(reinterpret_cast<void*>(static_cast<uintptr_t>(0xFFFFFFFFu))));
+    breakpoint();
+    checkInt32.link(this);
+#else
+    UNUSED_PARAM(gpr);
+#endif
+}
+
+void JITCompiler::jitAssertIsJSInt32(GPRReg gpr)
+{
+    Jump checkJSInt32 = branchPtr(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
+    breakpoint();
+    checkJSInt32.link(this);
+}
+
+void JITCompiler::jitAssertIsJSNumber(GPRReg gpr)
+{
+    Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
+    breakpoint();
+    checkJSNumber.link(this);
+}
+
+void JITCompiler::jitAssertIsJSDouble(GPRReg gpr)
+{
+    Jump checkJSInt32 = branchPtr(AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
+    Jump checkJSNumber = branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
+    checkJSInt32.link(this);
+    breakpoint();
+    checkJSNumber.link(this);
+}
+#endif
+
+#if ENABLE(SAMPLING_COUNTERS) && CPU(X86_64) // Or any other 64-bit platform!
+void JITCompiler::emitCount(AbstractSamplingCounter& counter, uint32_t increment)
+{
+    addPtr(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter()));
+}
+#endif
+
+#if ENABLE(SAMPLING_COUNTERS) && CPU(X86) // Or any other little-endian 32-bit platform!
+void JITCompiler::emitCount(AbstractSamplingCounter& counter, uint32_t increment)
+{
+    intptr_t hiWord = reinterpret_cast<intptr_t>(counter.addressOfCounter()) + sizeof(int32_t);
+    add32(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter()));
+    addWithCarry32(TrustedImm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
+}
+#endif
+
+#if ENABLE(SAMPLING_FLAGS)
+void JITCompiler::setSamplingFlag(int32_t flag)
+{
+    ASSERT(flag >= 1);
+    ASSERT(flag <= 32);
+    or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags()));
+}
+
+void JITCompiler::clearSamplingFlag(int32_t flag)
+{
+    ASSERT(flag >= 1);
+    ASSERT(flag <= 32);
+    and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags()));
+}
+#endif
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGJITCompiler.h b/dfg/DFGJITCompiler.h
new file mode 100644 (file)
index 0000000..7ed9a2f
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2011 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 DFGJITCompiler_h
+#define DFGJITCompiler_h
+
+#if ENABLE(DFG_JIT)
+
+#include <assembler/MacroAssembler.h>
+#include <bytecode/CodeBlock.h>
+#include <dfg/DFGGraph.h>
+#include <dfg/DFGRegisterBank.h>
+#include <jit/JITCode.h>
+
+#include <dfg/DFGFPRInfo.h>
+#include <dfg/DFGGPRInfo.h>
+
+namespace JSC {
+
+class AbstractSamplingCounter;
+class CodeBlock;
+class JSGlobalData;
+
+namespace DFG {
+
+class JITCodeGenerator;
+class NonSpeculativeJIT;
+class SpeculativeJIT;
+class SpeculationRecovery;
+
+struct EntryLocation;
+struct SpeculationCheck;
+
+// === CallRecord ===
+//
+// A record of a call out from JIT code to a helper function.
+// Every CallRecord contains a reference to the call instruction & the function
+// that it needs to be linked to. Calls that might throw an exception also record
+// the Jump taken on exception (unset if not present), and ExceptionInfo (presently
+// an unsigned, bytecode index) used to recover handler/source info.
+struct CallRecord {
+    // Constructor for a call with no exception handler.
+    CallRecord(MacroAssembler::Call call, FunctionPtr function)
+        : m_call(call)
+        , m_function(function)
+    {
+    }
+
+    // Constructor for a call with an exception handler.
+    CallRecord(MacroAssembler::Call call, FunctionPtr function, MacroAssembler::Jump exceptionCheck, ExceptionInfo exceptionInfo)
+        : m_call(call)
+        , m_function(function)
+        , m_exceptionCheck(exceptionCheck)
+        , m_exceptionInfo(exceptionInfo)
+    {
+    }
+
+    MacroAssembler::Call m_call;
+    FunctionPtr m_function;
+    MacroAssembler::Jump m_exceptionCheck;
+    ExceptionInfo m_exceptionInfo;
+};
+
+// === JITCompiler ===
+//
+// DFG::JITCompiler is responsible for generating JIT code from the dataflow graph.
+// It does so by delegating to the speculative & non-speculative JITs, which
+// generate to a MacroAssembler (which the JITCompiler owns through an inheritance
+// relationship). The JITCompiler holds references to information required during
+// compilation, and also records information used in linking (e.g. a list of all
+// call to be linked).
+class JITCompiler : public MacroAssembler {
+public:
+    JITCompiler(JSGlobalData* globalData, Graph& dfg, CodeBlock* codeBlock)
+        : m_globalData(globalData)
+        , m_graph(dfg)
+        , m_codeBlock(codeBlock)
+    {
+    }
+
+    void compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWithArityCheck);
+
+    // Accessors for properties.
+    Graph& graph() { return m_graph; }
+    CodeBlock* codeBlock() { return m_codeBlock; }
+    JSGlobalData* globalData() { return m_globalData; }
+
+#if CPU(X86_64)
+    void preserveReturnAddressAfterCall(GPRReg reg)
+    {
+        pop(reg);
+    }
+
+    void restoreReturnAddressBeforeReturn(GPRReg reg)
+    {
+        push(reg);
+    }
+
+    void restoreReturnAddressBeforeReturn(Address address)
+    {
+        push(address);
+    }
+
+    void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, GPRReg to)
+    {
+        loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to);
+    }
+    void emitPutToCallFrameHeader(GPRReg from, RegisterFile::CallFrameHeaderEntry entry)
+    {
+        storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
+    }
+
+    void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
+    {
+        storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
+    }
+#endif
+
+    static Address addressForGlobalVar(GPRReg global, int32_t varNumber)
+    {
+        return Address(global, varNumber * sizeof(Register));
+    }
+
+    static Address addressFor(VirtualRegister virtualRegister)
+    {
+        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
+    }
+
+    static Address tagFor(VirtualRegister virtualRegister)
+    {
+        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+    }
+
+    static Address payloadFor(VirtualRegister virtualRegister)
+    {
+        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+    }
+
+    // Add a call out from JIT code, without an exception check.
+    void appendCall(const FunctionPtr& function)
+    {
+        m_calls.append(CallRecord(call(), function));
+        // FIXME: should be able to JIT_ASSERT here that globalData->exception is null on return back to JIT code.
+    }
+
+    // Add a call out from JIT code, with an exception check.
+    void appendCallWithExceptionCheck(const FunctionPtr& function, unsigned exceptionInfo)
+    {
+        Call functionCall = call();
+        Jump exceptionCheck = branchTestPtr(NonZero, AbsoluteAddress(&globalData()->exception));
+        m_calls.append(CallRecord(functionCall, function, exceptionCheck, exceptionInfo));
+    }
+
+    // Helper methods to check nodes for constants.
+    bool isConstant(NodeIndex nodeIndex)
+    {
+        return graph()[nodeIndex].isConstant();
+    }
+    bool isInt32Constant(NodeIndex nodeIndex)
+    {
+        return graph()[nodeIndex].op == Int32Constant;
+    }
+    bool isDoubleConstant(NodeIndex nodeIndex)
+    {
+        return graph()[nodeIndex].op == DoubleConstant;
+    }
+    bool isJSConstant(NodeIndex nodeIndex)
+    {
+        return graph()[nodeIndex].op == JSConstant;
+    }
+
+    // Helper methods get constant values from nodes.
+    int32_t valueOfInt32Constant(NodeIndex nodeIndex)
+    {
+        ASSERT(isInt32Constant(nodeIndex));
+        return graph()[nodeIndex].int32Constant();
+    }
+    double valueOfDoubleConstant(NodeIndex nodeIndex)
+    {
+        ASSERT(isDoubleConstant(nodeIndex));
+        return graph()[nodeIndex].numericConstant();
+    }
+    JSValue valueOfJSConstant(NodeIndex nodeIndex)
+    {
+        ASSERT(isJSConstant(nodeIndex));
+        unsigned constantIndex = graph()[nodeIndex].constantNumber();
+        return codeBlock()->constantRegister(FirstConstantRegisterIndex + constantIndex).get();
+    }
+
+    // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
+#if DFG_JIT_ASSERT
+    void jitAssertIsInt32(GPRReg);
+    void jitAssertIsJSInt32(GPRReg);
+    void jitAssertIsJSNumber(GPRReg);
+    void jitAssertIsJSDouble(GPRReg);
+#else
+    void jitAssertIsInt32(GPRReg) {}
+    void jitAssertIsJSInt32(GPRReg) {}
+    void jitAssertIsJSNumber(GPRReg) {}
+    void jitAssertIsJSDouble(GPRReg) {}
+#endif
+
+#if ENABLE(SAMPLING_COUNTERS)
+    // Debug profiling tool.
+    void emitCount(AbstractSamplingCounter&, uint32_t increment = 1);
+#endif
+
+#if ENABLE(SAMPLING_FLAGS)
+    void setSamplingFlag(int32_t flag);
+    void clearSamplingFlag(int32_t flag);
+#endif
+
+private:
+    // These methods used in linking the speculative & non-speculative paths together.
+    void fillNumericToDouble(NodeIndex, FPRReg, GPRReg temporary);
+    void fillInt32ToInteger(NodeIndex, GPRReg);
+    void fillToJS(NodeIndex, GPRReg);
+    void jumpFromSpeculativeToNonSpeculative(const SpeculationCheck&, const EntryLocation&, SpeculationRecovery*);
+    void linkSpeculationChecks(SpeculativeJIT&, NonSpeculativeJIT&);
+
+    // The globalData, used to access constants such as the vPtrs.
+    JSGlobalData* m_globalData;
+
+    // The dataflow graph currently being generated.
+    Graph& m_graph;
+
+    // The codeBlock currently being generated, used to access information such as constant values, immediates.
+    CodeBlock* m_codeBlock;
+
+    // Vector of calls out from JIT code, including exception handler information.
+    Vector<CallRecord> m_calls;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
+
diff --git a/dfg/DFGNode.h b/dfg/DFGNode.h
new file mode 100644 (file)
index 0000000..903be46
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 2011 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 DFGNode_h
+#define DFGNode_h
+
+// Emit various logging information for debugging, including dumping the dataflow graphs.
+#define DFG_DEBUG_VERBOSE 0
+// Enable generation of dynamic checks into the instruction stream.
+#define DFG_JIT_ASSERT 0
+// Consistency check contents compiler data structures.
+#define DFG_CONSISTENCY_CHECK 0
+// Emit a breakpoint into the head of every generated function, to aid debugging in GDB.
+#define DFG_JIT_BREAK_ON_EVERY_FUNCTION 0
+// Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
+#define DFG_JIT_BREAK_ON_EVERY_BLOCK 0
+// Emit a breakpoint into the head of every generated node, to aid debugging in GDB.
+#define DFG_JIT_BREAK_ON_EVERY_NODE 0
+// Disable the DFG JIT without having to touch Platform.h!
+#define DFG_DEBUG_LOCAL_DISBALE 0
+// Disable the SpeculativeJIT without having to touch Platform.h!
+#define DFG_DEBUG_LOCAL_DISBALE_SPECULATIVE 0
+// Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path.
+#define DFG_SUCCESS_STATS 0
+
+
+#if ENABLE(DFG_JIT)
+
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+// Type for a virtual register number (spill location).
+// Using an enum to make this type-checked at compile time, to avert programmer errors.
+enum VirtualRegister { InvalidVirtualRegister = -1 };
+COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
+
+// Type for a reference to another node in the graph.
+typedef uint32_t NodeIndex;
+static const NodeIndex NoNode = UINT_MAX;
+
+// Information used to map back from an exception to any handler/source information.
+// (Presently implemented as a bytecode index).
+typedef uint32_t ExceptionInfo;
+
+// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
+// and some additional informative flags (must generate, is constant, etc).
+#define NodeIdMask          0xFFF
+#define NodeResultMask     0xF000
+#define NodeMustGenerate  0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
+#define NodeIsConstant    0x20000
+#define NodeIsJump        0x40000
+#define NodeIsBranch      0x80000
+#define NodeIsTerminal   0x100000
+
+// These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
+#define NodeResultJS      0x1000
+#define NodeResultDouble  0x2000
+#define NodeResultInt32   0x3000
+
+// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
+#define FOR_EACH_DFG_OP(macro) \
+    /* Nodes for constants. */\
+    macro(JSConstant, NodeResultJS | NodeIsConstant) \
+    macro(Int32Constant, NodeResultJS | NodeIsConstant) \
+    macro(DoubleConstant, NodeResultJS | NodeIsConstant) \
+    macro(ConvertThis, NodeResultJS) \
+    \
+    /* Nodes for local variable access. */\
+    macro(GetLocal, NodeResultJS) \
+    macro(SetLocal, 0) \
+    macro(Phi, 0) \
+    \
+    /* Nodes for bitwise operations. */\
+    macro(BitAnd, NodeResultInt32) \
+    macro(BitOr, NodeResultInt32) \
+    macro(BitXor, NodeResultInt32) \
+    macro(BitLShift, NodeResultInt32) \
+    macro(BitRShift, NodeResultInt32) \
+    macro(BitURShift, NodeResultInt32) \
+    /* Bitwise operators call ToInt32 on their operands. */\
+    macro(NumberToInt32, NodeResultInt32) \
+    macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
+    /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
+    macro(UInt32ToNumber, NodeResultDouble) \
+    \
+    /* Nodes for arithmetic operations. */\
+    macro(ArithAdd, NodeResultDouble) \
+    macro(ArithSub, NodeResultDouble) \
+    macro(ArithMul, NodeResultDouble) \
+    macro(ArithDiv, NodeResultDouble) \
+    macro(ArithMod, NodeResultDouble) \
+    /* Arithmetic operators call ToNumber on their operands. */\
+    macro(Int32ToNumber, NodeResultDouble) \
+    macro(ValueToNumber, NodeResultDouble | NodeMustGenerate) \
+    \
+    /* Add of values may either be arithmetic, or result in string concatenation. */\
+    macro(ValueAdd, NodeResultJS | NodeMustGenerate) \
+    \
+    /* Property access. */\
+    /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
+    /* Since a put to 'length' may invalidate optimizations here, */\
+    /* this must be the directly subsequent property put. */\
+    macro(GetByVal, NodeResultJS | NodeMustGenerate) \
+    macro(PutByVal, NodeMustGenerate) \
+    macro(PutByValAlias, NodeMustGenerate) \
+    macro(GetById, NodeResultJS | NodeMustGenerate) \
+    macro(PutById, NodeMustGenerate) \
+    macro(PutByIdDirect, NodeMustGenerate) \
+    macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
+    macro(PutGlobalVar, NodeMustGenerate) \
+    \
+    /* Nodes for comparison operations. */\
+    macro(CompareLess, NodeResultJS | NodeMustGenerate) \
+    macro(CompareLessEq, NodeResultJS | NodeMustGenerate) \
+    macro(CompareEq, NodeResultJS | NodeMustGenerate) \
+    macro(CompareStrictEq, NodeResultJS) \
+    \
+    /* Nodes for misc operations. */\
+    macro(LogicalNot, NodeResultJS) \
+    \
+    /* Block terminals. */\
+    macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
+    macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
+    macro(Return, NodeMustGenerate | NodeIsTerminal)
+
+// This enum generates a monotonically increasing id for all Node types,
+// and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
+enum NodeId {
+#define DFG_OP_ENUM(opcode, flags) opcode##_id,
+    FOR_EACH_DFG_OP(DFG_OP_ENUM)
+#undef DFG_OP_ENUM
+};
+
+// Entries in this enum describe all Node types.
+// The enum value contains a monotonically increasing id, a result type, and additional flags.
+enum NodeType {
+#define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
+    FOR_EACH_DFG_OP(DFG_OP_ENUM)
+#undef DFG_OP_ENUM
+};
+
+// This type used in passing an immediate argument to Node constructor;
+// distinguishes an immediate value (typically an index into a CodeBlock data structure - 
+// a constant index, argument, or identifier) from a NodeIndex.
+struct OpInfo {
+    explicit OpInfo(unsigned value) : m_value(value) {}
+    unsigned m_value;
+};
+
+// === Node ===
+//
+// Node represents a single operation in the data flow graph.
+struct Node {
+    // Construct a node with up to 3 children, no immediate value.
+    Node(NodeType op, ExceptionInfo exceptionInfo, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+        : op(op)
+        , exceptionInfo(exceptionInfo)
+        , child1(child1)
+        , child2(child2)
+        , child3(child3)
+        , m_virtualRegister(InvalidVirtualRegister)
+        , m_refCount(0)
+    {
+    }
+
+    // Construct a node with up to 3 children and an immediate value.
+    Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+        : op(op)
+        , exceptionInfo(exceptionInfo)
+        , child1(child1)
+        , child2(child2)
+        , child3(child3)
+        , m_virtualRegister(InvalidVirtualRegister)
+        , m_refCount(0)
+        , m_opInfo(imm.m_value)
+    {
+    }
+
+    // Construct a node with up to 3 children and two immediate values.
+    Node(NodeType op, ExceptionInfo exceptionInfo, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
+        : op(op)
+        , exceptionInfo(exceptionInfo)
+        , child1(child1)
+        , child2(child2)
+        , child3(child3)
+        , m_virtualRegister(InvalidVirtualRegister)
+        , m_refCount(0)
+        , m_opInfo(imm1.m_value)
+    {
+        m_constantValue.opInfo2 = imm2.m_value;
+    }
+
+    bool mustGenerate()
+    {
+        return op & NodeMustGenerate;
+    }
+
+    bool isConstant()
+    {
+        return op & NodeIsConstant;
+    }
+
+    unsigned constantNumber()
+    {
+        ASSERT(isConstant());
+        return m_opInfo;
+    }
+
+    bool hasLocal()
+    {
+        return op == GetLocal || op == SetLocal;
+    }
+
+    VirtualRegister local()
+    {
+        ASSERT(hasLocal());
+        return (VirtualRegister)m_opInfo;
+    }
+
+    bool hasIdentifier()
+    {
+        return op == GetById || op == PutById || op == PutByIdDirect;
+    }
+
+    unsigned identifierNumber()
+    {
+        ASSERT(hasIdentifier());
+        return m_opInfo;
+    }
+
+    bool hasVarNumber()
+    {
+        return op == GetGlobalVar || op == PutGlobalVar;
+    }
+
+    unsigned varNumber()
+    {
+        ASSERT(hasVarNumber());
+        return m_opInfo;
+    }
+
+    bool hasResult()
+    {
+        return op & NodeResultMask;
+    }
+
+    bool hasInt32Result()
+    {
+        return (op & NodeResultMask) == NodeResultInt32;
+    }
+
+    bool hasDoubleResult()
+    {
+        return (op & NodeResultMask) == NodeResultDouble;
+    }
+
+    bool hasJSResult()
+    {
+        return (op & NodeResultMask) == NodeResultJS;
+    }
+
+    // Check for integers or doubles.
+    bool hasNumericResult()
+    {
+        // This check will need updating if more result types are added.
+        ASSERT((hasInt32Result() || hasDoubleResult()) == !hasJSResult());
+        return !hasJSResult();
+    }
+
+    int32_t int32Constant()
+    {
+        ASSERT(op == Int32Constant);
+        return m_constantValue.asInt32;
+    }
+
+    void setInt32Constant(int32_t value)
+    {
+        ASSERT(op == Int32Constant);
+        m_constantValue.asInt32 = value;
+    }
+
+    double numericConstant()
+    {
+        ASSERT(op == DoubleConstant);
+        return m_constantValue.asDouble;
+    }
+
+    void setDoubleConstant(double value)
+    {
+        ASSERT(op == DoubleConstant);
+        m_constantValue.asDouble = value;
+    }
+
+    bool isJump()
+    {
+        return op & NodeIsJump;
+    }
+
+    bool isBranch()
+    {
+        return op & NodeIsBranch;
+    }
+
+    bool isTerminal()
+    {
+        return op & NodeIsTerminal;
+    }
+
+    unsigned takenBytecodeOffset()
+    {
+        ASSERT(isBranch() || isJump());
+        return m_opInfo;
+    }
+
+    unsigned notTakenBytecodeOffset()
+    {
+        ASSERT(isBranch());
+        return m_constantValue.opInfo2;
+    }
+
+    VirtualRegister virtualRegister()
+    {
+        ASSERT(hasResult());
+        ASSERT(m_virtualRegister != InvalidVirtualRegister);
+        return m_virtualRegister;
+    }
+
+    void setVirtualRegister(VirtualRegister virtualRegister)
+    {
+        ASSERT(hasResult());
+        ASSERT(m_virtualRegister == InvalidVirtualRegister);
+        m_virtualRegister = virtualRegister;
+    }
+
+    bool shouldGenerate()
+    {
+        return m_refCount && op != Phi;
+    }
+
+    unsigned refCount()
+    {
+        return m_refCount;
+    }
+
+    // returns true when ref count passes from 0 to 1.
+    bool ref()
+    {
+        return !m_refCount++;
+    }
+
+    unsigned adjustedRefCount()
+    {
+        return mustGenerate() ? m_refCount - 1 : m_refCount;
+    }
+
+    // This enum value describes the type of the node.
+    NodeType op;
+    // Used to look up exception handling information (currently implemented as a bytecode index).
+    ExceptionInfo exceptionInfo;
+    // References to up to 3 children (0 for no child).
+    NodeIndex child1, child2, child3;
+
+private:
+    // The virtual register number (spill location) associated with this .
+    VirtualRegister m_virtualRegister;
+    // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
+    unsigned m_refCount;
+    // An immediate value, accesses type-checked via accessors above.
+    unsigned m_opInfo;
+    // The value of an int32/double constant.
+    union {
+        int32_t asInt32;
+        double asDouble;
+        unsigned opInfo2;
+    } m_constantValue;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGNonSpeculativeJIT.cpp b/dfg/DFGNonSpeculativeJIT.cpp
new file mode 100644 (file)
index 0000000..7c50715
--- /dev/null
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGNonSpeculativeJIT.h"
+
+#include "DFGSpeculativeJIT.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+const double twoToThe32 = (double)0x100000000ull;
+
+EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit)
+    : m_entry(entry)
+    , m_nodeIndex(jit->m_compileIndex)
+{
+    for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
+        if (iter.name() != InvalidVirtualRegister) {
+            GenerationInfo& info =  jit->m_generationInfo[iter.name()];
+            m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
+            m_gprInfo[iter.index()].format = info.registerFormat();
+        } else
+            m_gprInfo[iter.index()].nodeIndex = NoNode;
+    }
+    for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
+        if (iter.name() != InvalidVirtualRegister) {
+            GenerationInfo& info =  jit->m_generationInfo[iter.name()];
+            ASSERT(info.registerFormat() == DataFormatDouble);
+            m_fprInfo[iter.index()] = info.nodeIndex();
+        } else
+            m_fprInfo[iter.index()] = NoNode;
+    }
+}
+
+void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, FPRReg fpr)
+{
+    GPRReg jsValueGpr = operand.gpr();
+    GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
+
+    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+    JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+
+    // First, if we get here we have a double encoded as a JSValue
+    m_jit.move(jsValueGpr, tempGpr);
+    m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
+    m_jit.movePtrToDouble(tempGpr, fpr);
+    JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
+
+    // Next handle cells (& other JS immediates)
+    nonNumeric.link(&m_jit);
+    silentSpillAllRegisters(fpr, jsValueGpr);
+    m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
+    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    appendCallWithExceptionCheck(dfgConvertJSValueToNumber);
+    m_jit.moveDouble(FPRInfo::returnValueFPR, fpr);
+    silentFillAllRegisters(fpr);
+    JITCompiler::Jump hasCalledToNumber = m_jit.jump();
+    
+    // Finally, handle integers.
+    isInteger.link(&m_jit);
+    m_jit.convertInt32ToDouble(jsValueGpr, fpr);
+    hasUnboxedDouble.link(&m_jit);
+    hasCalledToNumber.link(&m_jit);
+
+    m_gprs.unlock(tempGpr);
+}
+
+void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)
+{
+    GPRReg jsValueGpr = operand.gpr();
+
+    JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
+
+    // First handle non-integers
+    silentSpillAllRegisters(result, jsValueGpr);
+    m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);
+    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    appendCallWithExceptionCheck(dfgConvertJSValueToInt32);
+    m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);
+    silentFillAllRegisters(result);
+    JITCompiler::Jump hasCalledToInt32 = m_jit.jump();
+    
+    // Then handle integers.
+    isInteger.link(&m_jit);
+    m_jit.zeroExtend32ToPtr(jsValueGpr, result);
+    hasCalledToInt32.link(&m_jit);
+}
+
+void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)
+{
+    JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
+
+    silentSpillAllRegisters(gpr);
+
+    m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);
+    appendCallWithExceptionCheck(toInt32);
+    m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);
+
+    silentFillAllRegisters(gpr);
+
+    truncatedToInteger.link(&m_jit);
+}
+
+bool NonSpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
+{
+    GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
+
+    DataFormat registerFormat = info.registerFormat();
+    if (registerFormat != DataFormatNone)
+        return (registerFormat | DataFormatJS) == DataFormatJSInteger;
+
+    DataFormat spillFormat = info.spillFormat();
+    if (spillFormat != DataFormatNone)
+        return (spillFormat | DataFormatJS) == DataFormatJSInteger;
+
+    ASSERT(isConstant(nodeIndex));
+    return isInt32Constant(nodeIndex);
+}
+
+bool NonSpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
+{
+    GenerationInfo& info = m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()];
+
+    DataFormat registerFormat = info.registerFormat();
+    if (registerFormat != DataFormatNone)
+        return (registerFormat | DataFormatJS) == DataFormatJSInteger
+            || (registerFormat | DataFormatJS) == DataFormatJSDouble;
+
+    DataFormat spillFormat = info.spillFormat();
+    if (spillFormat != DataFormatNone)
+        return (spillFormat | DataFormatJS) == DataFormatJSInteger
+            || (spillFormat | DataFormatJS) == DataFormatJSDouble;
+
+    ASSERT(isConstant(nodeIndex));
+    return isInt32Constant(nodeIndex) || isDoubleConstant(nodeIndex);
+}
+
+void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node)
+{
+    // Check for speculation checks from the corresponding instruction in the
+    // speculative path. Do not check for NodeIndex 0, since this is checked
+    // in the outermost compile layer, at the head of the non-speculative path
+    // (for index 0 we may need to check regardless of whether or not the node
+    // will be generated, since argument type speculation checks will appear
+    // as speculation checks at this index).
+    if (m_compileIndex && checkIterator.hasCheckAtIndex(m_compileIndex))
+        trackEntry(m_jit.label());
+
+    NodeType op = node.op;
+
+    switch (op) {
+    case ConvertThis: {
+        JSValueOperand thisValue(this, node.child1);
+        GPRReg thisGPR = thisValue.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationConvertThis, result.gpr(), thisGPR);
+        cellResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case Int32Constant:
+    case DoubleConstant:
+    case JSConstant:
+        initConstantInfo(m_compileIndex);
+        break;
+
+    case GetLocal: {
+        GPRTemporary result(this);
+        m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
+
+        // Like jsValueResult, but don't useChildren - our children are phi nodes,
+        // and don't represent values within this dataflow with virtual registers.
+        VirtualRegister virtualRegister = node.virtualRegister();
+        m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
+        m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), DataFormatJS);
+        break;
+    }
+
+    case SetLocal: {
+        JSValueOperand value(this, node.child1);
+        m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case BitAnd:
+    case BitOr:
+    case BitXor:
+        if (isInt32Constant(node.child1)) {
+            IntegerOperand op2(this, node.child2);
+            GPRTemporary result(this, op2);
+
+            bitOp(op, valueOfInt32Constant(node.child1), op2.gpr(), result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else if (isInt32Constant(node.child2)) {
+            IntegerOperand op1(this, node.child1);
+            GPRTemporary result(this, op1);
+
+            bitOp(op, valueOfInt32Constant(node.child2), op1.gpr(), result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else {
+            IntegerOperand op1(this, node.child1);
+            IntegerOperand op2(this, node.child2);
+            GPRTemporary result(this, op1, op2);
+
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            bitOp(op, reg1, reg2, result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        }
+        break;
+
+    case BitRShift:
+    case BitLShift:
+    case BitURShift:
+        if (isInt32Constant(node.child2)) {
+            IntegerOperand op1(this, node.child1);
+            GPRTemporary result(this, op1);
+
+            int shiftAmount = valueOfInt32Constant(node.child2) & 0x1f;
+            // Shifts by zero should have been optimized out of the graph!
+            ASSERT(shiftAmount);
+            shiftOp(op, op1.gpr(), shiftAmount, result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else {
+            // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
+            IntegerOperand op1(this, node.child1);
+            IntegerOperand op2(this, node.child2);
+            GPRTemporary result(this, op1);
+
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            shiftOp(op, reg1, reg2, result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        }
+        break;
+
+    case UInt32ToNumber: {
+        IntegerOperand op1(this, node.child1);
+        FPRTemporary result(this);
+        m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
+
+        MacroAssembler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
+        m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), result.fpr());
+        positive.link(&m_jit);
+
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case Int32ToNumber: {
+        IntegerOperand op1(this, node.child1);
+        FPRTemporary result(this);
+        m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case NumberToInt32:
+    case ValueToInt32: {
+        ASSERT(!isInt32Constant(node.child1));
+
+        if (isKnownInteger(node.child1)) {
+            IntegerOperand op1(this, node.child1);
+            GPRTemporary result(this, op1);
+            m_jit.move(op1.gpr(), result.gpr());
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+
+        if (isKnownNumeric(node.child1)) {
+            DoubleOperand op1(this, node.child1);
+            GPRTemporary result(this);
+            numberToInt32(op1.fpr(), result.gpr());
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+
+        // We should have handled this via isKnownInteger, or isKnownNumeric!
+        ASSERT(op != NumberToInt32);
+
+        JSValueOperand op1(this, node.child1);
+        GPRTemporary result(this, op1);
+        valueToInt32(op1, result.gpr());
+        integerResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ValueToNumber: {
+        ASSERT(!isInt32Constant(node.child1));
+        ASSERT(!isDoubleConstant(node.child1));
+
+        if (isKnownInteger(node.child1)) {
+            IntegerOperand op1(this, node.child1);
+            FPRTemporary result(this);
+            m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
+            doubleResult(result.fpr(), m_compileIndex);
+            break;
+        }
+
+        if (isKnownNumeric(node.child1)) {
+            DoubleOperand op1(this, node.child1);
+            FPRTemporary result(this, op1);
+            m_jit.moveDouble(op1.fpr(), result.fpr());
+            doubleResult(result.fpr(), m_compileIndex);
+            break;
+        }
+
+        JSValueOperand op1(this, node.child1);
+        FPRTemporary result(this);
+        valueToNumber(op1, result.fpr());
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case ValueAdd: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationValueAdd, result.gpr(), arg1GPR, arg2GPR);
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+        
+    case ArithAdd: {
+        DoubleOperand op1(this, node.child1);
+        DoubleOperand op2(this, node.child2);
+        FPRTemporary result(this, op1, op2);
+
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.addDouble(reg1, reg2, result.fpr());
+
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithSub: {
+        DoubleOperand op1(this, node.child1);
+        DoubleOperand op2(this, node.child2);
+        FPRTemporary result(this, op1);
+
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.subDouble(reg1, reg2, result.fpr());
+
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithMul: {
+        DoubleOperand op1(this, node.child1);
+        DoubleOperand op2(this, node.child2);
+        FPRTemporary result(this, op1, op2);
+
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.mulDouble(reg1, reg2, result.fpr());
+
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithDiv: {
+        DoubleOperand op1(this, node.child1);
+        DoubleOperand op2(this, node.child2);
+        FPRTemporary result(this, op1);
+
+        FPRReg reg1 = op1.fpr();
+        FPRReg reg2 = op2.fpr();
+        m_jit.divDouble(reg1, reg2, result.fpr());
+
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithMod: {
+        DoubleOperand arg1(this, node.child1);
+        DoubleOperand arg2(this, node.child2);
+        FPRReg arg1FPR = arg1.fpr();
+        FPRReg arg2FPR = arg2.fpr();
+        flushRegisters();
+
+        FPRResult result(this);
+        callOperation(fmod, result.fpr(), arg1FPR, arg2FPR);
+
+        doubleResult(result.fpr(), m_compileIndex);
+        break;
+    }
+
+    case LogicalNot: {
+        JSValueOperand arg1(this, node.child1);
+        GPRReg arg1GPR = arg1.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(dfgConvertJSValueToBoolean, result.gpr(), arg1GPR);
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.xor32(TrustedImm32(ValueTrue), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareLess: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationCompareLess, result.gpr(), arg1GPR, arg2GPR);
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareLessEq: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationCompareLessEq, result.gpr(), arg1GPR, arg2GPR);
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareEq: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationCompareEq, result.gpr(), arg1GPR, arg2GPR);
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareStrictEq: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationCompareStrictEq, result.gpr(), arg1GPR, arg2GPR);
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case GetByVal: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationGetByVal, result.gpr(), arg1GPR, arg2GPR);
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutByVal:
+    case PutByValAlias: {
+        JSValueOperand arg1(this, node.child1);
+        JSValueOperand arg2(this, node.child2);
+        JSValueOperand arg3(this, node.child3);
+        GPRReg arg1GPR = arg1.gpr();
+        GPRReg arg2GPR = arg2.gpr();
+        GPRReg arg3GPR = arg3.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case GetById: {
+        JSValueOperand base(this, node.child1);
+        GPRReg baseGPR = base.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber()));
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutById: {
+        JSValueOperand base(this, node.child1);
+        JSValueOperand value(this, node.child2);
+        GPRReg valueGPR = value.gpr();
+        GPRReg baseGPR = base.gpr();
+        flushRegisters();
+
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case PutByIdDirect: {
+        JSValueOperand base(this, node.child1);
+        JSValueOperand value(this, node.child2);
+        GPRReg valueGPR = value.gpr();
+        GPRReg baseGPR = base.gpr();
+        flushRegisters();
+
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case GetGlobalVar: {
+        GPRTemporary result(this);
+
+        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
+        m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
+        m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutGlobalVar: {
+        JSValueOperand value(this, node.child1);
+        GPRTemporary temp(this);
+
+        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
+        m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
+        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case DFG::Jump: {
+        BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
+        if (taken != (m_block + 1))
+            addBranch(m_jit.jump(), taken);
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Branch: {
+        JSValueOperand value(this, node.child1);
+        GPRReg valueGPR = value.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(dfgConvertJSValueToBoolean, result.gpr(), valueGPR);
+
+        BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
+        BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
+
+        addBranch(m_jit.branchTest8(MacroAssembler::NonZero, result.gpr()), taken);
+        if (notTaken != (m_block + 1))
+            addBranch(m_jit.jump(), notTaken);
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Return: {
+        ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
+        ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
+        ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
+
+#if DFG_SUCCESS_STATS
+        static SamplingCounter counter("NonSpeculativeJIT");
+        m_jit.emitCount(counter);
+#endif
+
+        // Return the result in returnValueGPR.
+        JSValueOperand op1(this, node.child1);
+        m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
+
+        // Grab the return address.
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
+        // Restore our caller's "r".
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
+        // Return.
+        m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
+        m_jit.ret();
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Phi:
+        ASSERT_NOT_REACHED();
+    }
+
+    if (node.hasResult() && node.mustGenerate())
+        use(m_compileIndex);
+}
+
+void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, BasicBlock& block)
+{
+    ASSERT(m_compileIndex == block.begin);
+    m_blockHeads[m_block] = m_jit.label();
+
+#if DFG_JIT_BREAK_ON_EVERY_BLOCK
+    m_jit.breakpoint();
+#endif
+
+    for (; m_compileIndex < block.end; ++m_compileIndex) {
+        Node& node = m_jit.graph()[m_compileIndex];
+        if (!node.shouldGenerate())
+            continue;
+
+#if DFG_DEBUG_VERBOSE
+        fprintf(stderr, "NonSpeculativeJIT generating Node @%d at code offset 0x%x\n", (int)m_compileIndex, m_jit.debugOffset());
+#endif
+#if DFG_JIT_BREAK_ON_EVERY_NODE
+        m_jit.breakpoint();
+#endif
+
+        checkConsistency();
+        compile(checkIterator, node);
+        checkConsistency();
+    }
+}
+
+void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator)
+{
+    // Check for speculation checks added at function entry (checking argument types).
+    if (checkIterator.hasCheckAtIndex(m_compileIndex))
+        trackEntry(m_jit.label());
+
+    ASSERT(!m_compileIndex);
+    for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
+        compile(checkIterator, *m_jit.graph().m_blocks[m_block]);
+    linkBranches();
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGNonSpeculativeJIT.h b/dfg/DFGNonSpeculativeJIT.h
new file mode 100644 (file)
index 0000000..e213671
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2011 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 DFGNonSpeculativeJIT_h
+#define DFGNonSpeculativeJIT_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGJITCodeGenerator.h>
+
+namespace JSC { namespace DFG {
+
+class SpeculationCheckIndexIterator;
+
+// === EntryLocation ===
+//
+// This structure describes an entry point into the non-speculative
+// code path. This is used in linking bail-outs from the speculative path.
+struct EntryLocation {
+    EntryLocation(MacroAssembler::Label, NonSpeculativeJIT*);
+
+    // The node this entry point corresponds to, and the label
+    // marking the start of code for the given node.
+    MacroAssembler::Label m_entry;
+    NodeIndex m_nodeIndex;
+
+    // For every entry point we record a map recording for every
+    // machine register which, if any, values it contains. For
+    // GPR registers we must also record the format of the value.
+    struct RegisterInfo {
+        NodeIndex nodeIndex;
+        DataFormat format;
+    };
+    RegisterInfo m_gprInfo[GPRInfo::numberOfRegisters];
+    NodeIndex m_fprInfo[FPRInfo::numberOfRegisters];
+};
+
+// === NonSpeculativeJIT ===
+//
+// This class is used to generate code for the non-speculative path.
+// Code generation will take advantage of static information available
+// in the dataflow to perform safe optimizations - for example, avoiding
+// boxing numeric values between arithmetic operations, but will not
+// perform any unsafe optimizations that would render the code unable
+// to produce the correct results for any possible input.
+class NonSpeculativeJIT : public JITCodeGenerator {
+    friend struct EntryLocation;
+public:
+    NonSpeculativeJIT(JITCompiler& jit)
+        : JITCodeGenerator(jit, false)
+    {
+    }
+
+    void compile(SpeculationCheckIndexIterator&);
+
+    typedef SegmentedVector<EntryLocation, 16> EntryLocationVector;
+    EntryLocationVector& entryLocations() { return m_entryLocations; }
+
+private:
+    void compile(SpeculationCheckIndexIterator&, Node&);
+    void compile(SpeculationCheckIndexIterator&, BasicBlock&);
+
+    bool isKnownInteger(NodeIndex);
+    bool isKnownNumeric(NodeIndex);
+
+    // These methods are used when generating 'unexpected'
+    // calls out from JIT code to C++ helper routines -
+    // they spill all live values to the appropriate
+    // slots in the RegisterFile without changing any state
+    // in the GenerationInfo.
+    void silentSpillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        ASSERT(info.registerFormat() != DataFormatNone && info.registerFormat() != DataFormatDouble);
+
+        if (!info.needsSpill() || (info.gpr() == exclude))
+            return;
+
+        DataFormat registerFormat = info.registerFormat();
+
+        if (registerFormat == DataFormatInteger) {
+            m_jit.orPtr(GPRInfo::tagTypeNumberRegister, info.gpr());
+            m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
+        } else {
+            ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell);
+            m_jit.storePtr(info.gpr(), JITCompiler::addressFor(spillMe));
+        }
+    }
+    void silentSpillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg exclude = InvalidFPRReg)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        ASSERT(info.registerFormat() == DataFormatDouble);
+
+        if (!info.needsSpill() || (info.fpr() == exclude))
+            return;
+
+        boxDouble(info.fpr(), canTrample);
+        m_jit.storePtr(canTrample, JITCompiler::addressFor(spillMe));
+    }
+
+    void silentFillGPR(VirtualRegister spillMe, GPRReg exclude = InvalidGPRReg)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        if (info.gpr() == exclude)
+            return;
+
+        NodeIndex nodeIndex = info.nodeIndex();
+        Node& node = m_jit.graph()[nodeIndex];
+        ASSERT(info.registerFormat() != DataFormatNone && info.registerFormat() != DataFormatDouble);
+        DataFormat registerFormat = info.registerFormat();
+
+        if (registerFormat == DataFormatInteger) {
+            if (node.isConstant()) {
+                ASSERT(isInt32Constant(nodeIndex));
+                m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());
+            } else
+                m_jit.load32(JITCompiler::addressFor(spillMe), info.gpr());
+            return;
+        }
+
+        if (node.isConstant())
+            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), info.gpr());
+        else {
+            ASSERT(registerFormat & DataFormatJS || registerFormat == DataFormatCell);
+            m_jit.loadPtr(JITCompiler::addressFor(spillMe), info.gpr());
+        }
+    }
+    void silentFillFPR(VirtualRegister spillMe, GPRReg canTrample, FPRReg exclude = InvalidFPRReg)
+    {
+        GenerationInfo& info = m_generationInfo[spillMe];
+        if (info.fpr() == exclude)
+            return;
+
+        NodeIndex nodeIndex = info.nodeIndex();
+        Node& node = m_jit.graph()[nodeIndex];
+        ASSERT(info.registerFormat() == DataFormatDouble);
+
+        if (node.isConstant())
+            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), info.gpr());
+        else {
+            m_jit.loadPtr(JITCompiler::addressFor(spillMe), canTrample);
+            unboxDouble(canTrample, info.fpr());
+        }
+    }
+
+    void silentSpillAllRegisters(GPRReg exclude, GPRReg preserve = InvalidGPRReg)
+    {
+        GPRReg canTrample = GPRInfo::regT0;
+        if (preserve == GPRInfo::regT0)
+            canTrample = GPRInfo::regT1;
+        
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentSpillGPR(iter.name(), exclude);
+        }
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentSpillFPR(iter.name(), canTrample);
+        }
+    }
+    void silentSpillAllRegisters(FPRReg exclude, GPRReg preserve = InvalidGPRReg)
+    {
+        GPRReg canTrample = GPRInfo::regT0;
+        if (preserve == GPRInfo::regT0)
+            canTrample = GPRInfo::regT1;
+        
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentSpillGPR(iter.name());
+        }
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentSpillFPR(iter.name(), canTrample, exclude);
+        }
+    }
+    void silentFillAllRegisters(GPRReg exclude)
+    {
+        GPRReg canTrample = GPRInfo::regT0;
+        if (exclude == GPRInfo::regT0)
+            canTrample = GPRInfo::regT1;
+        
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentFillFPR(iter.name(), canTrample);
+        }
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentFillGPR(iter.name(), exclude);
+        }
+    }
+    void silentFillAllRegisters(FPRReg exclude)
+    {
+        GPRReg canTrample = GPRInfo::regT0;
+        
+        for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister) {
+                ASSERT_UNUSED(exclude, iter.regID() != exclude);
+                silentFillFPR(iter.name(), canTrample, exclude);
+            }
+        }
+        for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
+            if (iter.name() != InvalidVirtualRegister)
+                silentFillGPR(iter.name());
+        }
+    }
+
+    // These methods are used to plant calls out to C++
+    // helper routines to convert between types.
+    void valueToNumber(JSValueOperand&, FPRReg result);
+    void valueToInt32(JSValueOperand&, GPRReg result);
+    void numberToInt32(FPRReg, GPRReg result);
+
+    // Record an entry location into the non-speculative code path;
+    // for every bail-out on the speculative path we record information
+    // to be able to re-enter into the non-speculative one.
+    void trackEntry(MacroAssembler::Label entry)
+    {
+        m_entryLocations.append(EntryLocation(entry, this));
+    }
+
+    EntryLocationVector m_entryLocations;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
+
diff --git a/dfg/DFGOperations.cpp b/dfg/DFGOperations.cpp
new file mode 100644 (file)
index 0000000..a310d22
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGOperations.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "JSByteArray.h"
+#include "JSGlobalData.h"
+#include "Operations.h"
+
+namespace JSC { namespace DFG {
+
+EncodedJSValue operationConvertThis(ExecState* exec, EncodedJSValue encodedOp)
+{
+    return JSValue::encode(JSValue::decode(encodedOp).toThisObject(exec));
+}
+
+EncodedJSValue operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+
+    if (op1.isInt32() && op2.isInt32()) {
+        int64_t result64 = static_cast<int64_t>(op1.asInt32()) + static_cast<int64_t>(op2.asInt32());
+        int32_t result32 = static_cast<int32_t>(result64);
+        if (LIKELY(result32 == result64))
+            return JSValue::encode(jsNumber(result32));
+        return JSValue::encode(jsNumber((double)result64));
+    }
+    
+    double number1;
+    double number2;
+    if (op1.getNumber(number1) && op2.getNumber(number2))
+        return JSValue::encode(jsNumber(number1 + number2));
+
+    return JSValue::encode(jsAddSlowCase(exec, op1, op2));
+}
+
+EncodedJSValue operationGetByVal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty)
+{
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue property = JSValue::decode(encodedProperty);
+
+    if (LIKELY(baseValue.isCell())) {
+        JSCell* base = baseValue.asCell();
+
+        if (property.isUInt32()) {
+            JSGlobalData* globalData = &exec->globalData();
+            uint32_t i = property.asUInt32();
+
+            // FIXME: the JIT used to handle these in compiled code!
+            if (isJSArray(globalData, base) && asArray(base)->canGetIndex(i))
+                return JSValue::encode(asArray(base)->getIndex(i));
+
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (isJSString(globalData, base) && asString(base)->canGetIndex(i))
+                return JSValue::encode(asString(base)->getIndex(exec, i));
+
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (isJSByteArray(globalData, base) && asByteArray(base)->canAccessIndex(i))
+                return JSValue::encode(asByteArray(base)->getIndex(exec, i));
+
+            return JSValue::encode(baseValue.get(exec, i));
+        }
+
+        if (property.isString()) {
+            Identifier propertyName(exec, asString(property)->value(exec));
+            PropertySlot slot(base);
+            if (base->fastGetOwnPropertySlot(exec, propertyName, slot))
+                return JSValue::encode(slot.getValue(exec, propertyName));
+        }
+    }
+
+    Identifier ident(exec, property.toString(exec));
+    return JSValue::encode(baseValue.get(exec, ident));
+}
+
+EncodedJSValue operationGetById(ExecState* exec, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    JSValue baseValue = JSValue::decode(encodedBase);
+    PropertySlot slot(baseValue);
+    return JSValue::encode(baseValue.get(exec, *identifier, slot));
+}
+
+template<bool strict>
+ALWAYS_INLINE static void operationPutByValInternal(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    JSGlobalData* globalData = &exec->globalData();
+
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue property = JSValue::decode(encodedProperty);
+    JSValue value = JSValue::decode(encodedValue);
+
+    if (LIKELY(property.isUInt32())) {
+        uint32_t i = property.asUInt32();
+
+        if (isJSArray(globalData, baseValue)) {
+            JSArray* jsArray = asArray(baseValue);
+            if (jsArray->canSetIndex(i)) {
+                jsArray->setIndex(*globalData, i, value);
+                return;
+            }
+
+            jsArray->JSArray::put(exec, i, value);
+            return;
+        }
+
+        if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
+            JSByteArray* jsByteArray = asByteArray(baseValue);
+            // FIXME: the JITstub used to relink this to an optimized form!
+            if (value.isInt32()) {
+                jsByteArray->setIndex(i, value.asInt32());
+                return;
+            }
+
+            double dValue = 0;
+            if (value.getNumber(dValue)) {
+                jsByteArray->setIndex(i, dValue);
+                return;
+            }
+        }
+
+        baseValue.put(exec, i, value);
+        return;
+    }
+
+    // Don't put to an object if toString throws an exception.
+    Identifier ident(exec, property.toString(exec));
+    if (!globalData->exception) {
+        PutPropertySlot slot(strict);
+        baseValue.put(exec, ident, value, slot);
+    }
+}
+
+void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
+}
+
+void operationPutByValNonStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
+{
+    operationPutByValInternal<false>(exec, encodedBase, encodedProperty, encodedValue);
+}
+
+void operationPutByIdStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(true);
+    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+void operationPutByIdNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(false);
+    JSValue::decode(encodedBase).put(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+void operationPutByIdDirectStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(true);
+    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+void operationPutByIdDirectNonStrict(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* identifier)
+{
+    PutPropertySlot slot(false);
+    JSValue::decode(encodedBase).putDirect(exec, *identifier, JSValue::decode(encodedValue), slot);
+}
+
+bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return jsLess(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+bool operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return jsLessEq(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+bool operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return JSValue::equal(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+bool operationCompareStrictEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    return JSValue::strictEqual(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+}
+
+DFGHandler lookupExceptionHandler(ExecState* exec, ReturnAddressPtr faultLocation)
+{
+    JSValue exceptionValue = exec->exception();
+    ASSERT(exceptionValue);
+
+    unsigned vPCIndex = exec->codeBlock()->bytecodeOffset(faultLocation);
+    HandlerInfo* handler = exec->globalData().interpreter->throwException(exec, exceptionValue, vPCIndex);
+
+    void* catchRoutine = handler ? handler->nativeCode.executableAddress() : (void*)ctiOpThrowNotCaught;
+    ASSERT(catchRoutine);
+    return DFGHandler(exec, catchRoutine);
+}
+
+double dfgConvertJSValueToNumber(ExecState* exec, EncodedJSValue value)
+{
+    return JSValue::decode(value).toNumber(exec);
+}
+
+int32_t dfgConvertJSValueToInt32(ExecState* exec, EncodedJSValue value)
+{
+    return JSValue::decode(value).toInt32(exec);
+}
+
+bool dfgConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
+{
+    return JSValue::decode(encodedOp).toBoolean(exec);
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGOperations.h b/dfg/DFGOperations.h
new file mode 100644 (file)
index 0000000..d4c7c0f
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011 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 DFGOperations_h
+#define DFGOperations_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGJITCompiler.h>
+
+namespace JSC {
+
+class Identifier;
+
+namespace DFG {
+
+// These typedefs provide typechecking when generating calls out to helper routines;
+// this helps prevent calling a helper routine with the wrong arguments!
+typedef EncodedJSValue (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
+typedef EncodedJSValue (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue);
+typedef EncodedJSValue (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*);
+typedef EncodedJSValue (*J_DFGOperation_EJI)(ExecState*, EncodedJSValue, Identifier*);
+typedef bool (*Z_DFGOperation_EJ)(ExecState*, EncodedJSValue);
+typedef bool (*Z_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
+typedef void (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
+typedef void (*V_DFGOperation_EJJP)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
+typedef void (*V_DFGOperation_EJJI)(ExecState*, EncodedJSValue, EncodedJSValue, Identifier*);
+typedef double (*D_DFGOperation_DD)(double, double);
+
+// These routines are provide callbacks out to C++ implementations of operations too complex to JIT.
+EncodedJSValue operationConvertThis(ExecState*, EncodedJSValue encodedOp1);
+EncodedJSValue operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+EncodedJSValue operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
+EncodedJSValue operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*);
+void operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
+void operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
+void operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+bool operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+bool operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+bool operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+bool operationCompareStrictEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
+
+// This method is used to lookup an exception hander, keyed by faultLocation, which is
+// the return location from one of the calls out to one of the helper operations above.
+struct DFGHandler {
+    DFGHandler(ExecState* exec, void* handler)
+        : exec(exec)
+        , handler(handler)
+    {
+    }
+
+    ExecState* exec;
+    void* handler;
+};
+DFGHandler lookupExceptionHandler(ExecState*, ReturnAddressPtr faultLocation);
+
+// These operations implement the implicitly called ToInt32, ToNumber, and ToBoolean conversions from ES5.
+double dfgConvertJSValueToNumber(ExecState*, EncodedJSValue);
+int32_t dfgConvertJSValueToInt32(ExecState*, EncodedJSValue);
+bool dfgConvertJSValueToBoolean(ExecState*, EncodedJSValue);
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGRegisterBank.h b/dfg/DFGRegisterBank.h
new file mode 100644 (file)
index 0000000..f4fdd50
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2011 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 DFGRegisterBank_h
+#define DFGRegisterBank_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGNode.h>
+
+namespace JSC { namespace DFG {
+
+// === RegisterBank ===
+//
+// This class is used to implement the GPR and FPR register banks.
+// All registers have two pieces of state associated with them:
+// a lock count (used to indicate this register is already in use
+// in code generation of the current node, and cannot be spilled or
+// allocated as a temporary), and VirtualRegister 'name', recording
+// which value (if any) a machine register currently holds.
+// Either or both of these pieces of information may be valid for a
+// given register. A register may be:
+//
+//  - unlocked, and unnamed: Available for allocation.
+//  - locked, but unnamed:   Already allocated as a temporary or
+//                           result for the current node.
+//  - unlocked, but named:   Contains the result of a prior operation,
+//                           not yet in use for this node,
+//  - locked, but named:     Contains the result of a prior operation,
+//                           already allocated as a operand to the
+//                           current operation.
+//
+// For every named register we also record a hint value indicating
+// the order in which registers should be selected to be spilled;
+// registers that can be more cheaply spilled and/or filled should
+// be selected first.
+//
+// Locking register is a strong retention mechanism; a locked register
+// will never be reallocated (this is used to ensure the operands to
+// the current node are in registers). Naming, conversely, in a weak
+// retention mechanism - allocating a register may force a named value
+// to be spilled.
+//
+// All named values must be given a hint that is greater than Min and
+// less than Max.
+template<class BankInfo>
+class RegisterBank {
+    typedef typename BankInfo::RegisterType RegID;
+    static const size_t NUM_REGS = BankInfo::numberOfRegisters;
+
+    typedef uint32_t SpillHint;
+    static const SpillHint SpillHintInvalid = 0xffffffff;
+
+public:
+    RegisterBank()
+        : m_lastAllocated(NUM_REGS - 1)
+    {
+    }
+
+    // Allocate a register - this function finds an unlocked register,
+    // locks it, and returns it. If any named registers exist, one
+    // of these should be selected to be allocated. If all unlocked
+    // registers are named, then one of the named registers will need
+    // to be spilled. In this case the register selected to be spilled
+    // will be one of the registers that has the lowest 'spillOrder'
+    // cost associated with it.
+    //
+    // This method select the register to be allocated, and calls the
+    // private 'allocateInternal' method to update internal data
+    // structures accordingly.
+    RegID allocate(VirtualRegister &spillMe)
+    {
+        uint32_t currentLowest = NUM_REGS;
+        SpillHint currentSpillOrder = SpillHintInvalid;
+
+        // Scan through all register, starting at the last allocated & looping around.
+        ASSERT(m_lastAllocated < NUM_REGS);
+
+        // This loop is broken into two halves, looping from the last allocated
+        // register (the register returned last time this method was called) to
+        // the maximum register value, then from 0 to the last allocated.
+        // This implements a simple round-robin like approach to try to reduce
+        // thrash, and minimize time spent scanning locked registers in allocation.
+        // If a unlocked and unnamed register is found return it immediately.
+        // Otherwise, find the first unlocked register with the lowest spillOrder.
+        for (uint32_t i = m_lastAllocated + 1; i < NUM_REGS; ++i) {
+            // (1) If the current register is locked, it is not a candidate.
+            if (m_data[i].lockCount)
+                continue;
+            // (2) If the current register's spill order is 0, pick this! â€“ unassigned registers have spill order 0.
+            SpillHint spillOrder = m_data[i].spillOrder;
+            if (spillOrder == SpillHintInvalid)
+                return allocateInternal(i, spillMe);
+            // If this register is better (has a lower spill order value) than any prior
+            // candidate, then record it.
+            if (spillOrder < currentSpillOrder) {
+                currentSpillOrder = spillOrder;
+                currentLowest = i;
+            }
+        }
+        // Loop over the remaining entries.
+        for (uint32_t i = 0; i <= m_lastAllocated; ++i) {
+            if (m_data[i].lockCount)
+                continue;
+            SpillHint spillOrder = m_data[i].spillOrder;
+            if (spillOrder == SpillHintInvalid)
+                return allocateInternal(i, spillMe);
+            if (spillOrder < currentSpillOrder) {
+                currentSpillOrder = spillOrder;
+                currentLowest = i;
+            }
+        }
+
+        // Deadlock check - this could only occur is all registers are locked!
+        ASSERT(currentLowest != NUM_REGS && currentSpillOrder != SpillHintInvalid);
+        // There were no available registers; currentLowest will need to be spilled.
+        return allocateInternal(currentLowest, spillMe);
+    }
+
+    // retain/release - these methods are used to associate/disassociate names
+    // with values in registers. retain should only be called on locked registers.
+    void retain(RegID reg, VirtualRegister name, SpillHint spillOrder)
+    {
+        unsigned index = BankInfo::toIndex(reg);
+
+        // SpillHint must be valid.
+        ASSERT(spillOrder != SpillHintInvalid);
+        // 'index' must be a valid, locked register.
+        ASSERT(index < NUM_REGS);
+        ASSERT(m_data[index].lockCount);
+        // 'index' should not currently be named, the new name must be valid.
+        ASSERT(m_data[index].name == InvalidVirtualRegister);
+        ASSERT(name != InvalidVirtualRegister);
+        // 'index' should not currently have a spillOrder.
+        ASSERT(m_data[index].spillOrder == SpillHintInvalid);
+
+        m_data[index].name = name;
+        m_data[index].spillOrder = spillOrder;
+    }
+    void release(RegID reg)
+    {
+        releaseAtIndex(BankInfo::toIndex(reg));
+    }
+
+    // lock/unlock register, ensures that they are not spilled.
+    void lock(RegID reg)
+    {
+        unsigned index = BankInfo::toIndex(reg);
+
+        ASSERT(index < NUM_REGS);
+        ++m_data[index].lockCount;
+        ASSERT(m_data[index].lockCount);
+    }
+    void unlock(RegID reg)
+    {
+        unsigned index = BankInfo::toIndex(reg);
+
+        ASSERT(index < NUM_REGS);
+        ASSERT(m_data[index].lockCount);
+        --m_data[index].lockCount;
+    }
+    bool isLocked(RegID reg) const
+    {
+        return isLockedAtIndex(BankInfo::toIndex(reg));
+    }
+
+    // Get the name (VirtualRegister) associated with the
+    // given register (or InvalidVirtualRegister for none).
+    VirtualRegister name(RegID reg) const
+    {
+        return nameAtIndex(BankInfo::toIndex(reg));
+    }
+    
+#ifndef NDEBUG
+    void dump()
+    {
+        // For each register, print the VirtualRegister 'name'.
+        for (uint32_t i =0; i < NUM_REGS; ++i) {
+            if (m_data[i].name != InvalidVirtualRegister)
+                fprintf(stderr, "[%02d]", m_data[i].name);
+            else
+                fprintf(stderr, "[--]");
+        }
+        fprintf(stderr, "\n");
+    }
+#endif
+
+    class iterator {
+    friend class RegisterBank<BankInfo>;
+    public:
+        VirtualRegister name() const
+        {
+            return m_bank->nameAtIndex(m_index);
+        }
+
+        bool isLocked() const
+        {
+            return m_bank->isLockedAtIndex(m_index);
+        }
+
+        void release() const
+        {
+            m_bank->releaseAtIndex(m_index);
+        }
+
+        RegID regID() const
+        {
+            return BankInfo::toRegister(m_index);
+        }
+
+#ifndef NDEBUG
+        const char* debugName() const
+        {
+            return BankInfo::debugName(regID());
+        }
+#endif
+
+        iterator& operator++()
+        {
+            ++m_index;
+            return *this;
+        }
+
+        bool operator!=(const iterator& other) const
+        {
+            ASSERT(m_bank == other.m_bank);
+            return m_index != other.m_index;
+        }
+
+        unsigned index() const
+        {
+            return m_index;
+        }
+
+    private:
+        iterator(RegisterBank<BankInfo>* bank, unsigned index)
+            : m_bank(bank)
+            , m_index(index)
+        {
+        }
+
+        RegisterBank<BankInfo>* m_bank;
+        unsigned m_index;
+    };
+
+    iterator begin()
+    {
+        return iterator(this, 0);
+    }
+
+    iterator end()
+    {
+        return iterator(this, NUM_REGS);
+    }
+
+private:
+    bool isLockedAtIndex(unsigned index) const
+    {
+        ASSERT(index < NUM_REGS);
+        return m_data[index].lockCount;
+    }
+
+    VirtualRegister nameAtIndex(unsigned index) const
+    {
+        ASSERT(index < NUM_REGS);
+        return m_data[index].name;
+    }
+
+    void releaseAtIndex(unsigned index)
+    {
+        // 'index' must be a valid register.
+        ASSERT(index < NUM_REGS);
+        // 'index' should currently be named.
+        ASSERT(m_data[index].name != InvalidVirtualRegister);
+        // 'index' should currently have a valid spill order.
+        ASSERT(m_data[index].spillOrder != SpillHintInvalid);
+
+        m_data[index].name = InvalidVirtualRegister;
+        m_data[index].spillOrder = SpillHintInvalid;
+    }
+
+    // Used by 'allocate', above, to update inforamtion in the map.
+    RegID allocateInternal(uint32_t i, VirtualRegister &spillMe)
+    {
+        // 'i' must be a valid, unlocked register.
+        ASSERT(i < NUM_REGS && !m_data[i].lockCount);
+
+        // Return the VirtualRegister of the named value currently stored in
+        // the register being returned - or InvalidVirtualRegister if none.
+        spillMe = m_data[i].name;
+
+        // Clear any name/spillOrder currently associated with the register,
+        m_data[i] = MapEntry();
+        // Mark the register as locked (with a lock count of 1).
+        m_data[i].lockCount = 1;
+
+        m_lastAllocated = i;
+        return BankInfo::toRegister(i);
+    }
+
+    // === MapEntry ===
+    //
+    // This structure provides information for an individual machine register
+    // being managed by the RegisterBank. For each register we track a lock
+    // count, name and spillOrder hint.
+    struct MapEntry {
+        MapEntry()
+            : name(InvalidVirtualRegister)
+            , spillOrder(SpillHintInvalid)
+            , lockCount(0)
+        {
+        }
+
+        VirtualRegister name;
+        SpillHint spillOrder;
+        uint32_t lockCount;
+    };
+
+    // Holds the current status of all registers.
+    MapEntry m_data[NUM_REGS];
+    // Used to to implement a simple round-robin like allocation scheme.
+    uint32_t m_lastAllocated;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGScoreBoard.h b/dfg/DFGScoreBoard.h
new file mode 100644 (file)
index 0000000..1e44292
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2011 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 DFGScoreBoard_h
+#define DFGScoreBoard_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGGraph.h>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace DFG {
+
+// === ScoreBoard ===
+//
+// This class is used in performing a virtual register allocation over the graph.
+// VirtualRegisters are allocated to nodes, with a used count for each virtual
+// register tracking the lifespan of the value; after the final use of a node
+// the VirtualRegister associated is freed such that it can be reused for
+// another node.
+class ScoreBoard {
+public:
+    ScoreBoard(Graph& graph, uint32_t firstTemporary)
+        : m_graph(graph)
+        , m_firstTemporary(firstTemporary)
+    {
+    }
+
+#if DFG_CONSISTENCY_CHECK
+    ~ScoreBoard()
+    {
+        // Every VirtualRegister that was allocated should now be free.
+        ASSERT(m_used.size() == m_free.size());
+        // Every entry in the used list should be available in the free list.
+        for (size_t i = 0; i < m_used.size(); ++i)
+            ASSERT(m_free.contains(i));
+        // For every entry in the used list the use count of the virtual register should be zero.
+        for (size_t i = 0; i < m_free.size(); ++i)
+            ASSERT(!m_used[i]);
+    }
+#endif
+
+    VirtualRegister allocate()
+    {
+        // Do we have any VirtualRegsiters in the free list, that were used by
+        // prior nodes, but are now available?
+        if (!m_free.isEmpty()) {
+            uint32_t index = m_free.last();
+            m_free.removeLast();
+            // Use count must have hit zero for it to have been added to the free list!
+            ASSERT(!m_used[index]);
+            return (VirtualRegister)(m_firstTemporary + index);
+        }
+
+        // Allocate a new VirtualRegister, and add a corresponding entry to m_used.
+        size_t next = allocatedCount();
+        m_used.append(0);
+        return (VirtualRegister)(m_firstTemporary + next);
+    }
+
+    // Increment the usecount for the VirtualRegsiter associated with 'child',
+    // if it reaches the node's refcount, free the VirtualRegsiter.
+    void use(NodeIndex child)
+    {
+        if (child == NoNode)
+            return;
+
+        // Find the virtual register number for this child, increment its use count.
+        Node& node = m_graph[child];
+        uint32_t index = node.virtualRegister() - m_firstTemporary;
+        if (node.refCount() == ++m_used[index]) {
+            // If the use count in the scoreboard reaches the use count for the node,
+            // then this was its last use; the virtual register is now free.
+            // Clear the use count & add to the free list.
+            m_used[index] = 0;
+            m_free.append(index);
+        }
+    }
+
+    unsigned allocatedCount()
+    {
+        // m_used contains an entry for every allocated VirtualRegister.
+        return m_used.size();
+    }
+
+#ifndef NDEBUG
+    void dump()
+    {
+        printf("    USED: [ ");
+        for (unsigned i = 0; i < m_used.size(); ++i) {
+            if (!m_free.contains(i))
+                printf("%d:%d ", m_firstTemporary + i, m_used[i]);
+        }
+        printf("]\n");
+
+        printf("    FREE: [ ");
+        for (unsigned i = 0; i < m_used.size(); ++i) {
+            if (m_free.contains(i)) {
+                ASSERT(!m_used[i]);
+                printf("%d ", m_firstTemporary + i);
+            }
+        }
+        printf("]\n");
+    }
+
+#endif
+
+private:
+    // The graph, so we can get refCounts for nodes, to determine when values are dead.
+    Graph& m_graph;
+    // The first VirtualRegsiter to be used as a temporary.
+    uint32_t m_firstTemporary;
+    
+    // For every virtual register that has been allocated (either currently alive, or in
+    // the free list), we keep a count of the number of remaining uses until it is dead
+    // (0, in the case of entries in the free list). Since there is an entry for every
+    // allocated VirtualRegister, the length of this array conveniently provides the
+    // next available VirtualRegister number.
+    Vector<uint32_t, 64> m_used;
+    // A free list of VirtualRegsiters no longer alive.
+    Vector<uint32_t, 64> m_free;
+};
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
diff --git a/dfg/DFGSpeculativeJIT.cpp b/dfg/DFGSpeculativeJIT.cpp
new file mode 100644 (file)
index 0000000..71004fe
--- /dev/null
@@ -0,0 +1,956 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "DFGSpeculativeJIT.h"
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+template<bool strict>
+GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        GPRReg gpr = allocate();
+
+        if (node.isConstant()) {
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            if (isInt32Constant(nodeIndex)) {
+                m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
+                info.fillInteger(gpr);
+                returnFormat = DataFormatInteger;
+                return gpr;
+            }
+            m_jit.move(constantAsJSValueAsImmPtr(nodeIndex), gpr);
+        } else {
+            DataFormat spillFormat = info.spillFormat();
+            ASSERT(spillFormat & DataFormatJS);
+
+            m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+
+            if (spillFormat == DataFormatJSInteger) {
+                // If we know this was spilled as an integer we can fill without checking.
+                if (strict) {
+                    m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
+                    info.fillInteger(gpr);
+                    returnFormat = DataFormatInteger;
+                    return gpr;
+                }
+                m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+                info.fillJSValue(gpr, DataFormatJSInteger);
+                returnFormat = DataFormatJSInteger;
+                return gpr;
+            }
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+        }
+
+        // Fill as JSValue, and fall through.
+        info.fillJSValue(gpr, DataFormatJSInteger);
+        m_gprs.unlock(gpr);
+    }
+
+    case DataFormatJS: {
+        // Check the value is an integer.
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        speculationCheck(m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
+        info.fillJSValue(gpr, DataFormatJSInteger);
+        // If !strict we're done, return.
+        if (!strict) {
+            returnFormat = DataFormatJSInteger;
+            return gpr;
+        }
+        // else fall through & handle as DataFormatJSInteger.
+        m_gprs.unlock(gpr);
+    }
+
+    case DataFormatJSInteger: {
+        // In a strict fill we need to strip off the value tag.
+        if (strict) {
+            GPRReg gpr = info.gpr();
+            GPRReg result;
+            // If the register has already been locked we need to take a copy.
+            // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
+            if (m_gprs.isLocked(gpr))
+                result = allocate();
+            else {
+                m_gprs.lock(gpr);
+                info.fillInteger(gpr);
+                result = gpr;
+            }
+            m_jit.zeroExtend32ToPtr(gpr, result);
+            returnFormat = DataFormatInteger;
+            return result;
+        }
+
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        returnFormat = DataFormatJSInteger;
+        return gpr;
+    }
+
+    case DataFormatInteger: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        returnFormat = DataFormatInteger;
+        return gpr;
+    }
+
+    case DataFormatDouble:
+    case DataFormatCell:
+    case DataFormatJSDouble:
+    case DataFormatJSCell: {
+        terminateSpeculativeExecution();
+        returnFormat = DataFormatInteger;
+        return allocate();
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
+    : m_check(check)
+    , m_nodeIndex(jit->m_compileIndex)
+    , m_recoveryIndex(recoveryIndex)
+{
+    for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
+        if (iter.name() != InvalidVirtualRegister) {
+            GenerationInfo& info =  jit->m_generationInfo[iter.name()];
+            m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
+            m_gprInfo[iter.index()].format = info.registerFormat();
+        } else
+            m_gprInfo[iter.index()].nodeIndex = NoNode;
+    }
+    for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
+        if (iter.name() != InvalidVirtualRegister) {
+            GenerationInfo& info =  jit->m_generationInfo[iter.name()];
+            ASSERT(info.registerFormat() == DataFormatDouble);
+            m_fprInfo[iter.index()] = info.nodeIndex();
+        } else
+            m_fprInfo[iter.index()] = NoNode;
+    }
+}
+
+GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
+{
+    return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
+}
+
+GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
+{
+    DataFormat mustBeDataFormatInteger;
+    GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
+    ASSERT(mustBeDataFormatInteger == DataFormatInteger);
+    return result;
+}
+
+GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
+{
+    Node& node = m_jit.graph()[nodeIndex];
+    VirtualRegister virtualRegister = node.virtualRegister();
+    GenerationInfo& info = m_generationInfo[virtualRegister];
+
+    switch (info.registerFormat()) {
+    case DataFormatNone: {
+        GPRReg gpr = allocate();
+
+        if (node.isConstant()) {
+            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
+            JSValue jsValue = constantAsJSValue(nodeIndex);
+            if (jsValue.isCell()) {
+                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
+                info.fillJSValue(gpr, DataFormatJSCell);
+                return gpr;
+            }
+            terminateSpeculativeExecution();
+            return gpr;
+        }
+        ASSERT(info.spillFormat() & DataFormatJS);
+        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
+        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
+
+        if (info.spillFormat() != DataFormatJSCell)
+            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
+        info.fillJSValue(gpr, DataFormatJSCell);
+        return gpr;
+    }
+
+    case DataFormatCell:
+    case DataFormatJSCell: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        return gpr;
+    }
+
+    case DataFormatJS: {
+        GPRReg gpr = info.gpr();
+        m_gprs.lock(gpr);
+        speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
+        info.fillJSValue(gpr, DataFormatJSCell);
+        return gpr;
+    }
+
+    case DataFormatJSInteger:
+    case DataFormatInteger:
+    case DataFormatJSDouble:
+    case DataFormatDouble: {
+        terminateSpeculativeExecution();
+        return allocate();
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return InvalidGPRReg;
+}
+
+void SpeculativeJIT::compilePeepHoleBranch(Node& node, JITCompiler::RelationalCondition condition)
+{
+    Node& branchNode = m_jit.graph()[m_compileIndex + 1];
+    BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
+    BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
+
+    // The branch instruction will branch to the taken block.
+    // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
+    if (taken == (m_block + 1)) {
+        condition = JITCompiler::invert(condition);
+        BlockIndex tmp = taken;
+        taken = notTaken;
+        notTaken = tmp;
+    }
+
+    int32_t imm;
+    if (isJSConstantWithInt32Value(node.child1, imm)) {
+        SpeculateIntegerOperand op2(this, node.child2);
+        addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
+    } else if (isJSConstantWithInt32Value(node.child2, imm)) {
+        SpeculateIntegerOperand op1(this, node.child1);
+        addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
+    } else {
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
+    }
+
+    // Check for fall through, otherwise we need to jump.
+    if (notTaken != (m_block + 1))
+        addBranch(m_jit.jump(), notTaken);
+}
+
+void SpeculativeJIT::compile(Node& node)
+{
+    NodeType op = node.op;
+
+    switch (op) {
+    case Int32Constant:
+    case DoubleConstant:
+    case JSConstant:
+        initConstantInfo(m_compileIndex);
+        break;
+
+    case GetLocal: {
+        GPRTemporary result(this);
+        PredictedType prediction = m_jit.graph().getPrediction(node.local());
+        if (prediction == PredictInt32) {
+            m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
+
+            // Like integerResult, but don't useChildren - our children are phi nodes,
+            // and don't represent values within this dataflow with virtual registers.
+            VirtualRegister virtualRegister = node.virtualRegister();
+            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
+            m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
+        } else {
+            m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
+
+            // Like jsValueResult, but don't useChildren - our children are phi nodes,
+            // and don't represent values within this dataflow with virtual registers.
+            VirtualRegister virtualRegister = node.virtualRegister();
+            m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
+            m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), (prediction == PredictArray) ? DataFormatJSCell : DataFormatJS);
+        }
+        break;
+    }
+
+    case SetLocal: {
+        switch (m_jit.graph().getPrediction(node.local())) {
+        case PredictInt32: {
+            SpeculateIntegerOperand value(this, node.child1);
+            m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
+            noResult(m_compileIndex);
+            break;
+        }
+        case PredictArray: {
+            SpeculateCellOperand cell(this, node.child1);
+            m_jit.storePtr(cell.gpr(), JITCompiler::addressFor(node.local()));
+            noResult(m_compileIndex);
+            break;
+        }
+
+        default: {
+            JSValueOperand value(this, node.child1);
+            m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
+            noResult(m_compileIndex);
+            break;
+        }
+        }
+        break;
+    }
+
+    case BitAnd:
+    case BitOr:
+    case BitXor:
+        if (isInt32Constant(node.child1)) {
+            SpeculateIntegerOperand op2(this, node.child2);
+            GPRTemporary result(this, op2);
+
+            bitOp(op, valueOfInt32Constant(node.child1), op2.gpr(), result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else if (isInt32Constant(node.child2)) {
+            SpeculateIntegerOperand op1(this, node.child1);
+            GPRTemporary result(this, op1);
+
+            bitOp(op, valueOfInt32Constant(node.child2), op1.gpr(), result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else {
+            SpeculateIntegerOperand op1(this, node.child1);
+            SpeculateIntegerOperand op2(this, node.child2);
+            GPRTemporary result(this, op1, op2);
+
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            bitOp(op, reg1, reg2, result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        }
+        break;
+
+    case BitRShift:
+    case BitLShift:
+    case BitURShift:
+        if (isInt32Constant(node.child2)) {
+            SpeculateIntegerOperand op1(this, node.child1);
+            GPRTemporary result(this, op1);
+
+            shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2) & 0x1f, result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        } else {
+            // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
+            SpeculateIntegerOperand op1(this, node.child1);
+            SpeculateIntegerOperand op2(this, node.child2);
+            GPRTemporary result(this, op1);
+
+            GPRReg reg1 = op1.gpr();
+            GPRReg reg2 = op2.gpr();
+            shiftOp(op, reg1, reg2, result.gpr());
+
+            integerResult(result.gpr(), m_compileIndex);
+        }
+        break;
+
+    case UInt32ToNumber: {
+        IntegerOperand op1(this, node.child1);
+        GPRTemporary result(this, op1);
+
+        // Test the operand is positive.
+        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
+
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        break;
+    }
+
+    case NumberToInt32: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        break;
+    }
+
+    case Int32ToNumber: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        break;
+    }
+
+    case ValueToInt32: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        break;
+    }
+
+    case ValueToNumber: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        GPRTemporary result(this, op1);
+        m_jit.move(op1.gpr(), result.gpr());
+        integerResult(result.gpr(), m_compileIndex, op1.format());
+        break;
+    }
+
+    case ValueAdd:
+    case ArithAdd: {
+        int32_t imm1;
+        if (isDoubleConstantWithInt32Value(node.child1, imm1)) {
+            SpeculateIntegerOperand op2(this, node.child2);
+            GPRTemporary result(this);
+
+            speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
+
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+            
+        int32_t imm2;
+        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
+            SpeculateIntegerOperand op1(this, node.child1);
+            GPRTemporary result(this);
+
+            speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+            
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        GPRReg gpr1 = op1.gpr();
+        GPRReg gpr2 = op2.gpr();
+        GPRReg gprResult = result.gpr();
+        MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
+
+        if (gpr1 == gprResult)
+            speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
+        else if (gpr2 == gprResult)
+            speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
+        else
+            speculationCheck(check);
+
+        integerResult(gprResult, m_compileIndex);
+        break;
+    }
+
+    case ArithSub: {
+        int32_t imm2;
+        if (isDoubleConstantWithInt32Value(node.child2, imm2)) {
+            SpeculateIntegerOperand op1(this, node.child1);
+            GPRTemporary result(this);
+
+            speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
+
+            integerResult(result.gpr(), m_compileIndex);
+            break;
+        }
+            
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this);
+
+        speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
+
+        integerResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithMul: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this);
+
+        GPRReg reg1 = op1.gpr();
+        GPRReg reg2 = op2.gpr();
+        speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
+
+        MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
+        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
+        speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
+        resultNonZero.link(&m_jit);
+
+        integerResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithDiv: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        op1.gpr();
+        op2.gpr();
+        terminateSpeculativeExecution();
+
+        integerResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case ArithMod: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        op1.gpr();
+        op2.gpr();
+        terminateSpeculativeExecution();
+
+        integerResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case LogicalNot: {
+        JSValueOperand value(this, node.child1);
+        GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
+
+        m_jit.move(value.gpr(), result.gpr());
+        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
+        speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
+        m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareLess: {
+        // Fused compare & branch.
+        if (detectPeepHoleBranch()) {
+            // detectPeepHoleBranch currently only permits the branch to be the very next node,
+            // so can be no intervening nodes to also reference the compare. 
+            ASSERT(node.adjustedRefCount() == 1);
+
+            compilePeepHoleBranch(node, JITCompiler::LessThan);
+
+            use(node.child1);
+            use(node.child2);
+            ++m_compileIndex;
+            return;
+        }
+
+        // Normal case, not fused to branch.
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        m_jit.compare32(JITCompiler::LessThan, op1.gpr(), op2.gpr(), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareLessEq: {
+        // Fused compare & branch.
+        if (detectPeepHoleBranch()) {
+            // detectPeepHoleBranch currently only permits the branch to be the very next node,
+            // so can be no intervening nodes to also reference the compare. 
+            ASSERT(node.adjustedRefCount() == 1);
+
+            compilePeepHoleBranch(node, JITCompiler::LessThanOrEqual);
+
+            use(node.child1);
+            use(node.child2);
+            ++m_compileIndex;
+            return;
+        }
+
+        // Normal case, not fused to branch.
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        m_jit.compare32(JITCompiler::LessThanOrEqual, op1.gpr(), op2.gpr(), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareEq: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        m_jit.compare32(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case CompareStrictEq: {
+        SpeculateIntegerOperand op1(this, node.child1);
+        SpeculateIntegerOperand op2(this, node.child2);
+        GPRTemporary result(this, op1, op2);
+
+        m_jit.compare32(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
+
+        // If we add a DataFormatBool, we should use it here.
+        m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case GetByVal: {
+        NodeIndex alias = node.child3;
+        if (alias != NoNode) {
+            // FIXME: result should be able to reuse child1, child2. Should have an 'UnusedOperand' type.
+            JSValueOperand aliasedValue(this, node.child3);
+            GPRTemporary result(this, aliasedValue);
+            m_jit.move(aliasedValue.gpr(), result.gpr());
+            jsValueResult(result.gpr(), m_compileIndex);
+            break;
+        }
+
+        SpeculateCellOperand base(this, node.child1);
+        SpeculateStrictInt32Operand property(this, node.child2);
+        GPRTemporary storage(this);
+
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg storageReg = storage.gpr();
+
+        // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
+        // an access with offset JSArray::storageOffset() is valid for all JSCells!
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
+
+        // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
+        // If we have predicted the base to be type array, we can skip the check.
+        Node& baseNode = m_jit.graph()[node.child1];
+        if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+        speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
+
+        // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
+        // the storage pointer - especially if there happens to be another register free right now. If we do so,
+        // then we'll need to allocate a new temporary for result.
+        GPRTemporary& result = storage;
+        m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
+        speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutByVal: {
+        SpeculateCellOperand base(this, node.child1);
+        SpeculateStrictInt32Operand property(this, node.child2);
+        JSValueOperand value(this, node.child3);
+        GPRTemporary storage(this);
+
+        // Map base, property & value into registers, allocate a register for storage.
+        GPRReg baseReg = base.gpr();
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueReg = value.gpr();
+        GPRReg storageReg = storage.gpr();
+
+        // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
+        // If we have predicted the base to be type array, we can skip the check.
+        Node& baseNode = m_jit.graph()[node.child1];
+        if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+        speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
+
+        // Get the array storage.
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
+
+        // 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, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+        m_jit.add32(TrustedImm32(1), propertyReg);
+        m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
+        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])));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case PutByValAlias: {
+        SpeculateCellOperand base(this, node.child1);
+        SpeculateStrictInt32Operand property(this, node.child2);
+        JSValueOperand value(this, node.child3);
+        GPRTemporary storage(this, base); // storage may overwrite base.
+
+        // Get the array storage.
+        GPRReg storageReg = storage.gpr();
+        m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSArray::storageOffset()), storageReg);
+
+        // Map property & value into registers.
+        GPRReg propertyReg = property.gpr();
+        GPRReg valueReg = value.gpr();
+
+        // Store the value to the array.
+        m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case DFG::Jump: {
+        BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
+        if (taken != (m_block + 1))
+            addBranch(m_jit.jump(), taken);
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Branch: {
+        JSValueOperand value(this, node.child1);
+        GPRReg valueReg = value.gpr();
+
+        BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
+        BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
+
+        // Integers
+        addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
+        MacroAssembler::Jump isNonZeroInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueReg, GPRInfo::tagTypeNumberRegister);
+
+        // Booleans
+        addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
+        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))));
+
+        if (taken == (m_block + 1))
+            isNonZeroInteger.link(&m_jit);
+        else {
+            addBranch(isNonZeroInteger, taken);
+            addBranch(m_jit.jump(), taken);
+        }
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Return: {
+        ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
+        ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
+        ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
+
+#if DFG_SUCCESS_STATS
+        static SamplingCounter counter("SpeculativeJIT");
+        m_jit.emitCount(counter);
+#endif
+
+        // Return the result in returnValueGPR.
+        JSValueOperand op1(this, node.child1);
+        m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
+
+        // Grab the return address.
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
+        // Restore our caller's "r".
+        m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
+        // Return.
+        m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
+        m_jit.ret();
+        
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case ConvertThis: {
+        SpeculateCellOperand thisValue(this, node.child1);
+        GPRTemporary temp(this);
+
+        m_jit.loadPtr(JITCompiler::Address(thisValue.gpr(), JSCell::structureOffset()), temp.gpr());
+        speculationCheck(m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(temp.gpr(), Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(NeedsThisConversion)));
+
+        cellResult(thisValue.gpr(), m_compileIndex);
+        break;
+    }
+
+    case GetById: {
+        JSValueOperand base(this, node.child1);
+        GPRReg baseGPR = base.gpr();
+        flushRegisters();
+
+        GPRResult result(this);
+        callOperation(operationGetById, result.gpr(), baseGPR, identifier(node.identifierNumber()));
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutById: {
+        JSValueOperand base(this, node.child1);
+        JSValueOperand value(this, node.child2);
+        GPRReg valueGPR = value.gpr();
+        GPRReg baseGPR = base.gpr();
+        flushRegisters();
+
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case PutByIdDirect: {
+        JSValueOperand base(this, node.child1);
+        JSValueOperand value(this, node.child2);
+        GPRReg valueGPR = value.gpr();
+        GPRReg baseGPR = base.gpr();
+        flushRegisters();
+
+        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case GetGlobalVar: {
+        GPRTemporary result(this);
+
+        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
+        m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
+        m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
+
+        jsValueResult(result.gpr(), m_compileIndex);
+        break;
+    }
+
+    case PutGlobalVar: {
+        JSValueOperand value(this, node.child1);
+        GPRTemporary temp(this);
+
+        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
+        m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
+        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+
+        noResult(m_compileIndex);
+        break;
+    }
+
+    case Phi:
+        ASSERT_NOT_REACHED();
+    }
+
+    if (node.hasResult() && node.mustGenerate())
+        use(m_compileIndex);
+}
+
+void SpeculativeJIT::compile(BasicBlock& block)
+{
+    ASSERT(m_compileIndex == block.begin);
+    m_blockHeads[m_block] = m_jit.label();
+#if DFG_JIT_BREAK_ON_EVERY_BLOCK
+    m_jit.breakpoint();
+#endif
+
+    for (; m_compileIndex < block.end; ++m_compileIndex) {
+        Node& node = m_jit.graph()[m_compileIndex];
+        if (!node.shouldGenerate())
+            continue;
+
+#if DFG_DEBUG_VERBOSE
+        fprintf(stderr, "SpeculativeJIT generating Node @%d at JIT offset 0x%x\n", (int)m_compileIndex, m_jit.debugOffset());
+#endif
+#if DFG_JIT_BREAK_ON_EVERY_NODE
+        m_jit.breakpoint();
+#endif
+        checkConsistency();
+        compile(node);
+        if (!m_compileOkay)
+            return;
+        checkConsistency();
+    }
+}
+
+// If we are making type predictions about our arguments then
+// we need to check that they are correct on function entry.
+void SpeculativeJIT::checkArgumentTypes()
+{
+    ASSERT(!m_compileIndex);
+    for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
+        VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
+        switch (m_jit.graph().getPrediction(virtualRegister)) {
+        case PredictInt32:
+            speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
+            break;
+
+        case PredictArray: {
+            GPRTemporary temp(this);
+            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
+            speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
+            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
+            break;
+        }
+
+        default:
+            break;
+        }
+    }
+}
+
+// For any vars that we will be treating as numeric, write 0 to
+// the var on entry. Throughout the block we will only read/write
+// to the payload, by writing the tag now we prevent the GC from
+// misinterpreting values as pointers.
+void SpeculativeJIT::initializeVariableTypes()
+{
+    ASSERT(!m_compileIndex);
+    for (int var = 0; var < m_jit.codeBlock()->m_numVars; ++var) {
+        if (m_jit.graph().getPrediction(var) == PredictInt32)
+            m_jit.storePtr(GPRInfo::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
+    }
+}
+
+bool SpeculativeJIT::compile()
+{
+    checkArgumentTypes();
+    initializeVariableTypes();
+
+    ASSERT(!m_compileIndex);
+    for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
+        compile(*m_jit.graph().m_blocks[m_block]);
+        if (!m_compileOkay)
+            return false;
+    }
+    linkBranches();
+    return true;
+}
+
+} } // namespace JSC::DFG
+
+#endif
diff --git a/dfg/DFGSpeculativeJIT.h b/dfg/DFGSpeculativeJIT.h
new file mode 100644 (file)
index 0000000..82fd403
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2011 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 DFGSpeculativeJIT_h
+#define DFGSpeculativeJIT_h
+
+#if ENABLE(DFG_JIT)
+
+#include <dfg/DFGJITCodeGenerator.h>
+
+namespace JSC { namespace DFG {
+
+class SpeculativeJIT;
+
+// This enum describes the types of additional recovery that
+// may need be performed should a speculation check fail.
+enum SpeculationRecoveryType {
+    SpeculativeAdd
+};
+
+// === SpeculationRecovery ===
+//
+// This class provides additional information that may be associated with a
+// speculation check - for example 
+class SpeculationRecovery {
+public:
+    SpeculationRecovery(SpeculationRecoveryType type, GPRReg dest, GPRReg src)
+        : m_type(type)
+        , m_dest(dest)
+        , m_src(src)
+    {
+    }
+
+    SpeculationRecoveryType type() { return m_type; }
+    GPRReg dest() { return m_dest; }
+    GPRReg src() { return m_src; }
+
+private:
+    // Indicates the type of additional recovery to be performed.
+    SpeculationRecoveryType m_type;
+    // different recovery types may required different additional information here.
+    GPRReg m_dest;
+    GPRReg m_src;
+};
+
+// === SpeculationCheck ===
+//
+// This structure records a bail-out from the speculative path,
+// which will need to be linked in to the non-speculative one.
+struct SpeculationCheck {
+    SpeculationCheck(MacroAssembler::Jump, SpeculativeJIT*, unsigned recoveryIndex = 0);
+
+    // The location of the jump out from the speculative path, 
+    // and the node we were generating code for.
+    MacroAssembler::Jump m_check;
+    NodeIndex m_nodeIndex;
+    // Used to record any additional recovery to be performed; this
+    // value is an index into the SpeculativeJIT's m_speculationRecoveryList
+    // array, offset by 1. (m_recoveryIndex == 0) means no recovery.
+    unsigned m_recoveryIndex;
+
+    struct RegisterInfo {
+        NodeIndex nodeIndex;
+        DataFormat format;
+    };
+    RegisterInfo m_gprInfo[GPRInfo::numberOfRegisters];
+    NodeIndex m_fprInfo[FPRInfo::numberOfRegisters];
+};
+typedef SegmentedVector<SpeculationCheck, 16> SpeculationCheckVector;
+
+
+// === SpeculativeJIT ===
+//
+// The SpeculativeJIT is used to generate a fast, but potentially
+// incomplete code path for the dataflow. When code generating
+// we may make assumptions about operand types, dynamically check,
+// and bail-out to an alternate code path if these checks fail.
+// Importantly, the speculative code path cannot be reentered once
+// a speculative check has failed. This allows the SpeculativeJIT
+// to propagate type information (including information that has
+// only speculatively been asserted) through the dataflow.
+class SpeculativeJIT : public JITCodeGenerator {
+    friend struct SpeculationCheck;
+public:
+    SpeculativeJIT(JITCompiler& jit)
+        : JITCodeGenerator(jit, true)
+        , m_compileOkay(true)
+    {
+    }
+
+    bool compile();
+
+    // Retrieve the list of bail-outs from the speculative path,
+    // and additional recovery information.
+    SpeculationCheckVector& speculationChecks()
+    {
+        return m_speculationChecks;
+    }
+    SpeculationRecovery* speculationRecovery(size_t index)
+    {
+        // SpeculationCheck::m_recoveryIndex is offset by 1,
+        // 0 means no recovery.
+        return index ? &m_speculationRecoveryList[index - 1] : 0;
+    }
+
+    // Called by the speculative operand types, below, to fill operand to
+    // machine registers, implicitly generating speculation checks as needed.
+    GPRReg fillSpeculateInt(NodeIndex, DataFormat& returnFormat);
+    GPRReg fillSpeculateIntStrict(NodeIndex);
+    GPRReg fillSpeculateCell(NodeIndex);
+
+private:
+    void compile(Node&);
+    void compile(BasicBlock&);
+
+    void checkArgumentTypes();
+    void initializeVariableTypes();
+
+    bool isDoubleConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
+    {
+        if (!m_jit.isDoubleConstant(nodeIndex))
+            return false;
+        double value = m_jit.valueOfDoubleConstant(nodeIndex);
+
+        int32_t asInt32 = static_cast<int32_t>(value);
+        if (value != asInt32)
+            return false;
+        if (!asInt32 && signbit(value))
+            return false;
+
+        out = asInt32;
+        return true;
+    }
+
+    bool isJSConstantWithInt32Value(NodeIndex nodeIndex, int32_t& out)
+    {
+        if (!m_jit.isJSConstant(nodeIndex))
+            return false;
+        JSValue value = m_jit.valueOfJSConstant(nodeIndex);
+
+        if (!value.isInt32())
+            return false;
+        
+        out = value.asInt32();
+        return true;
+    }
+
+    bool detectPeepHoleBranch()
+    {
+        // Check if the block contains precisely one more node.
+        if (m_compileIndex + 2 != m_jit.graph().m_blocks[m_block]->end)
+            return false;
+
+        // Check if the lastNode is a branch on this node.
+        Node& lastNode = m_jit.graph()[m_compileIndex + 1];
+        return lastNode.op == Branch && lastNode.child1 == m_compileIndex;
+    }
+
+    void compilePeepHoleBranch(Node&, JITCompiler::RelationalCondition);
+
+    // Add a speculation check without additional recovery.
+    void speculationCheck(MacroAssembler::Jump jumpToFail)
+    {
+        m_speculationChecks.append(SpeculationCheck(jumpToFail, this));
+    }
+    // Add a speculation check with additional recovery.
+    void speculationCheck(MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
+    {
+        m_speculationRecoveryList.append(recovery);
+        m_speculationChecks.append(SpeculationCheck(jumpToFail, this, m_speculationRecoveryList.size()));
+    }
+
+    // Called when we statically determine that a speculation will fail.
+    void terminateSpeculativeExecution()
+    {
+        // FIXME: in cases where we can statically determine we're going to bail out from the speculative
+        // JIT we should probably rewind code generation and only produce the non-speculative path.
+        m_compileOkay = false;
+        speculationCheck(m_jit.jump());
+    }
+
+    template<bool strict>
+    GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);
+
+    // It is possible, during speculative generation, to reach a situation in which we
+    // can statically determine a speculation will fail (for example, when two nodes
+    // will make conflicting speculations about the same operand). In such cases this
+    // flag is cleared, indicating no further code generation should take place.
+    bool m_compileOkay;
+    // This vector tracks bail-outs from the speculative path to the non-speculative one.
+    SpeculationCheckVector m_speculationChecks;
+    // Some bail-outs need to record additional information recording specific recovery
+    // to be performed (for example, on detected overflow from an add, we may need to
+    // reverse the addition if an operand is being overwritten).
+    Vector<SpeculationRecovery, 16> m_speculationRecoveryList;
+};
+
+
+// === Speculative Operand types ===
+//
+// SpeculateIntegerOperand, SpeculateStrictInt32Operand and SpeculateCellOperand.
+//
+// These are used to lock the operands to a node into machine registers within the
+// SpeculativeJIT. The classes operate like those provided by the JITCodeGenerator,
+// however these will perform a speculative check for a more restrictive type than
+// we can statically determine the operand to have. If the operand does not have
+// the requested type, a bail-out to the non-speculative path will be taken.
+
+class SpeculateIntegerOperand {
+public:
+    explicit SpeculateIntegerOperand(SpeculativeJIT* jit, NodeIndex index)
+        : m_jit(jit)
+        , m_index(index)
+        , m_gprOrInvalid(InvalidGPRReg)
+#ifndef NDEBUG
+        , m_format(DataFormatNone)
+#endif
+    {
+        ASSERT(m_jit);
+        if (jit->isFilled(index))
+            gpr();
+    }
+
+    ~SpeculateIntegerOperand()
+    {
+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    DataFormat format()
+    {
+        gpr(); // m_format is set when m_gpr is locked.
+        ASSERT(m_format == DataFormatInteger || m_format == DataFormatJSInteger);
+        return m_format;
+    }
+
+    GPRReg gpr()
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillSpeculateInt(index(), m_format);
+        return m_gprOrInvalid;
+    }
+
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+    DataFormat m_format;
+};
+
+class SpeculateStrictInt32Operand {
+public:
+    explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, NodeIndex index)
+        : m_jit(jit)
+        , m_index(index)
+        , m_gprOrInvalid(InvalidGPRReg)
+    {
+        ASSERT(m_jit);
+        if (jit->isFilled(index))
+            gpr();
+    }
+
+    ~SpeculateStrictInt32Operand()
+    {
+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    GPRReg gpr()
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillSpeculateIntStrict(index());
+        return m_gprOrInvalid;
+    }
+
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+};
+
+class SpeculateCellOperand {
+public:
+    explicit SpeculateCellOperand(SpeculativeJIT* jit, NodeIndex index)
+        : m_jit(jit)
+        , m_index(index)
+        , m_gprOrInvalid(InvalidGPRReg)
+    {
+        ASSERT(m_jit);
+        if (jit->isFilled(index))
+            gpr();
+    }
+
+    ~SpeculateCellOperand()
+    {
+        ASSERT(m_gprOrInvalid != InvalidGPRReg);
+        m_jit->unlock(m_gprOrInvalid);
+    }
+
+    NodeIndex index() const
+    {
+        return m_index;
+    }
+
+    GPRReg gpr()
+    {
+        if (m_gprOrInvalid == InvalidGPRReg)
+            m_gprOrInvalid = m_jit->fillSpeculateCell(index());
+        return m_gprOrInvalid;
+    }
+
+private:
+    SpeculativeJIT* m_jit;
+    NodeIndex m_index;
+    GPRReg m_gprOrInvalid;
+};
+
+
+// === SpeculationCheckIndexIterator ===
+//
+// This class is used by the non-speculative JIT to check which
+// nodes require entry points from the speculative path.
+class SpeculationCheckIndexIterator {
+public:
+    SpeculationCheckIndexIterator(SpeculationCheckVector& speculationChecks)
+        : m_speculationChecks(speculationChecks)
+        , m_iter(m_speculationChecks.begin())
+        , m_end(m_speculationChecks.end())
+    {
+    }
+
+    bool hasCheckAtIndex(NodeIndex nodeIndex)
+    {
+        while (m_iter != m_end) {
+            NodeIndex current = m_iter->m_nodeIndex;
+            if (current >= nodeIndex)
+                return current == nodeIndex;
+            ++m_iter;
+        }
+        return false;
+    }
+
+private:
+    SpeculationCheckVector& m_speculationChecks;
+    SpeculationCheckVector::Iterator m_iter;
+    SpeculationCheckVector::Iterator m_end;
+};
+
+
+} } // namespace JSC::DFG
+
+#endif
+#endif
+
index 9494d1b1e615e947e192acf55b433f7a780ca0b5..5a95195a8af82977916d56d961171a12473b1a6b 100755 (executable)
@@ -7,6 +7,7 @@ open OUTPUT, ">" . $ARGV[1];
 
 my @undocumented = ();
 
+print OUTPUT "<!-- Generated from Interpreter.cpp by make-bytecode-docs.pl. -->\n";
 print OUTPUT "<style>p code \{ font-size: 14px; \}</style>\n";
 
 while (<MACHINE>) {
diff --git a/gyp/JavaScriptCore.gyp b/gyp/JavaScriptCore.gyp
new file mode 100644 (file)
index 0000000..a520344
--- /dev/null
@@ -0,0 +1,228 @@
+{
+  'includes': [
+    '../../gyp/common.gypi',
+    '../JavaScriptCore.gypi',
+  ],
+  'configurations': {
+    'Production': {
+      'xcode_config_file': '<(project_dir)/Configurations/Base.xcconfig',
+    },
+    'Profiling': {
+      'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig',
+      'xcode_settings': {
+        'STRIP_INSTALLED_PRODUCT': 'NO',
+      },
+    },
+    'Release': {
+      'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig',
+      'xcode_settings': {
+        'STRIP_INSTALLED_PRODUCT': 'NO',
+      },
+    },
+    'Debug': {
+      'xcode_config_file': '<(project_dir)/Configurations/DebugRelease.xcconfig',
+      'xcode_settings': {
+        'DEAD_CODE_STRIPPING': '$(DEAD_CODE_STRIPPING_debug)',
+        'DEBUG_DEFINES': '$(DEBUG_DEFINES_debug)',
+        'GCC_OPTIMIZATION_LEVEL': '$(GCC_OPTIMIZATION_LEVEL_debug)',
+        'STRIP_INSTALLED_PRODUCT': '$(STRIP_INSTALLED_PRODUCT_debug)',
+      },
+    },
+  },
+  'variables': {
+    'javascriptcore_include_dirs': [
+      '<(project_dir)',
+      '<(project_dir)/icu',
+    ],
+  },
+  'target_defaults': {
+    'configurations': {
+      'Profiling': {},
+    },
+  },
+  'targets': [
+    {
+      'target_name': 'JavaScriptCore',
+      'type': 'shared_library',
+      'dependencies': [
+        'Derived Sources',
+        'Update Version',
+      ],
+      'include_dirs': [
+        '<@(javascriptcore_include_dirs)',
+        '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore',
+      ],
+      'configurations': {
+        'Production': {
+          'INSTALL_PATH': '$(BUILT_PRODUCTS_DIR)',
+        },
+      },
+      'sources': [
+        '<@(javascriptcore_files)',
+        '<@(javascriptcore_publicheader_files)',
+        '<@(javascriptcore_privateheader_files)',
+        '<@(javascriptcore_derived_source_files)',
+        '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+        '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+        '/usr/lib/libicucore.dylib',
+        '/usr/lib/libobjc.dylib',
+      ],
+      'mac_framework_headers': [
+        '<@(javascriptcore_publicheader_files)',
+      ],
+      'mac_framework_private_headers': [
+        '<@(javascriptcore_privateheader_files)',
+      ],
+      'xcode_config_file': '<(project_dir)/Configurations/JavaScriptCore.xcconfig',
+      'sources/': [
+        ['exclude', 'API/tests/'],
+        ['exclude', 'ForwardingHeaders/'],
+        ['exclude', '(?<!unicode)/icu/'],
+        ['exclude', 'os-win32/'],
+        ['exclude', 'qt/'],
+        ['exclude', 'wtf/(android|brew|efl|gtk|haiku|qt|wince|wx)/'],
+        ['exclude', 'wtf/unicode/brew/'],
+        ['exclude', 'wtf/unicode/glib/'],
+        ['exclude', 'wtf/unicode/qt4/'],
+        ['exclude', 'wtf/unicode/wince/'],
+        ['exclude', 'wtf/url/'],
+        ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'],
+        ['exclude', '(Default|Gtk|Chromium|None|Qt|Win|Wx|Symbian)\\.(cpp|mm|h)$'],
+        ['exclude', 'GCActivityCallback\.cpp$'],
+        ['exclude', 'BSTR[^/]*$'],
+      ],
+      'postbuilds': [
+        {
+          'postbuild_name': 'Check For Global Initializers',
+          'action': [
+            'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-global-initializers'
+          ],
+        },
+        {
+          'postbuild_name': 'Check For Exit Time Destructors',
+          'action': [
+            'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-exit-time-destructors'
+          ],
+        },
+        {
+          'postbuild_name': 'Check For Weak VTables and Externals',
+          'action': [
+            'sh', '<(project_dir)/gyp/run-if-exists.sh', '<(DEPTH)/../Tools/Scripts/check-for-weak-vtables-and-externals'
+          ],
+        },
+      ],
+      'conditions': [
+        ['OS=="mac"', {
+          'mac_bundle': 1,
+          'xcode_settings': {
+            # FIXME: Remove these overrides once JavaScriptCore.xcconfig is
+            # used only by this project.
+            'GCC_PREFIX_HEADER': '<(project_dir)/JavaScriptCorePrefix.h',
+            'INFOPLIST_FILE': '<(project_dir)/Info.plist',
+          },
+        }],
+      ],
+    },
+    {
+      'target_name': 'Derived Sources',
+      'type': 'none',
+      'actions': [
+        {
+          'action_name': 'Generate Derived Sources',
+          'inputs': [],
+          'outputs': [
+            '<@(javascriptcore_derived_source_files)',
+          ],
+          'action': [
+            'sh', 'generate-derived-sources.sh'
+          ],
+        },
+        {
+          'action_name': 'Generate DTrace Header',
+          'inputs': [],
+           'outputs': [],
+           'action': [
+             'sh', '<(project_dir)/gyp/generate-dtrace-header.sh', '<(project_dir)'
+            ]
+        }
+      ],
+    },
+    {
+      'target_name': 'Update Version',
+      'type': 'none',
+      'actions': [{
+        'action_name': 'Update Info.plist with version information',
+        'inputs': [],
+         'outputs': [],
+         'action': [
+           'sh', '<(project_dir)/gyp/update-info-plist.sh', '<(project_dir)/Info.plist'
+          ]
+      }],
+    },
+    {
+      'target_name': 'minidom',
+      'type': 'executable',
+      'dependencies': [
+        'JavaScriptCore',
+      ],
+      # FIXME: We should use a header map instead of listing these explicitly.
+      'include_dirs': [
+        '<@(javascriptcore_include_dirs)',
+      ],
+      'sources': [
+        '<@(minidom_files)',
+        '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+      ],
+      'copies': [{
+        'destination': '<(PRODUCT_DIR)',
+        'files': [
+          '<@(minidom_support_files)',
+        ],
+      }],
+    },
+    {
+      'target_name': 'testapi',
+      'type': 'executable',
+      'dependencies': [
+        'JavaScriptCore',
+      ],
+      # FIXME: We should use a header map instead of listing these explicitly.
+      'include_dirs': [
+        '<@(javascriptcore_include_dirs)',
+      ],
+      'sources': [
+        '<@(testapi_files)',
+        '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+      ],
+      'copies': [{
+        'destination': '<(PRODUCT_DIR)',
+        'files': [
+          '<@(testapi_support_files)',
+        ],
+      }],
+    },
+    {
+      'target_name': 'jsc',
+      'type': 'executable',
+      'dependencies': [
+        'JavaScriptCore',
+      ],
+      # FIXME: We should use a header map instead of listing these explicitly.
+      'include_dirs': [
+        '<@(javascriptcore_include_dirs)',
+      ],
+      'configurations': {
+        'Production': {
+          'xcode_settings': {
+            'INSTALL_PATH': '$(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources',
+          },
+        },
+      },
+      'sources': [
+        '<@(jsc_files)',
+        '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework',
+        '/usr/lib/libedit.dylib',
+      ],
+    },
+  ], # targets
+}
diff --git a/gyp/generate-derived-sources.sh b/gyp/generate-derived-sources.sh
new file mode 100755 (executable)
index 0000000..a03af7d
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+mkdir -p "${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore/docs"
+cd "${BUILT_PRODUCTS_DIR}/DerivedSources/JavaScriptCore"
+
+/bin/ln -sfh "${SRCROOT}/.." JavaScriptCore
+export JavaScriptCore="JavaScriptCore"
+
+make --no-builtin-rules -f "JavaScriptCore/DerivedSources.make" -j `/usr/sbin/sysctl -n hw.ncpu`
diff --git a/gyp/generate-dtrace-header.sh b/gyp/generate-dtrace-header.sh
new file mode 100755 (executable)
index 0000000..a3c31dd
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+TRACING_D="$1/runtime/Tracing.d";
+TRACING_H="$BUILT_PRODUCTS_DIR/DerivedSources/JavaScriptCore/TracingDtrace.h";
+
+if [[ "${HAVE_DTRACE}" = "1" && "${TRACING_D}" -nt "${TRACING_H}" ]]; then
+    dtrace -h -o "${TRACING_H}" -s "${TRACING_D}";
+fi;
+
diff --git a/gyp/gtk.gyp b/gyp/gtk.gyp
new file mode 100644 (file)
index 0000000..33eaa17
--- /dev/null
@@ -0,0 +1,18 @@
+{ # Just a stub file to allow Source/gyp/configure to run successfully for testing.
+  'includes': [
+    '../../gyp/common.gypi',
+    '../JavaScriptCore.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'JavaScriptCore',
+      'type': 'static_library',
+      'sources': [
+        '<@(javascriptcore_files)',
+        '<@(javascriptcore_publicheader_files)',
+        '<@(javascriptcore_privateheader_files)',
+        '<@(javascriptcore_derived_source_files)',
+      ],
+    },
+  ], # targets
+}
diff --git a/gyp/run-if-exists.sh b/gyp/run-if-exists.sh
new file mode 100755 (executable)
index 0000000..242ffc8
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ -f $1 ]; then
+    $1 || exit $?;
+fi
diff --git a/gyp/update-info-plist.sh b/gyp/update-info-plist.sh
new file mode 100755 (executable)
index 0000000..d02ecce
--- /dev/null
@@ -0,0 +1,4 @@
+# Touch Info.plist to let Xcode know it needs to copy it into the built product
+if [[ "${CONFIGURATION}" != "Production" ]]; then
+    touch "$1";
+fi
diff --git a/heap/ConservativeRoots.cpp b/heap/ConservativeRoots.cpp
new file mode 100644 (file)
index 0000000..1aad779
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "ConservativeRoots.h"
+
+namespace JSC {
+
+inline bool isPointerAligned(void* p)
+{
+    return !((intptr_t)(p) & (sizeof(char*) - 1));
+}
+
+void ConservativeRoots::grow()
+{
+    size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2;
+    JSCell** newRoots = static_cast<JSCell**>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*)));
+    memcpy(newRoots, m_roots, m_size * sizeof(JSCell*));
+    if (m_roots != m_inlineRoots)
+        OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));
+    m_capacity = newCapacity;
+    m_roots = newRoots;
+}
+
+void ConservativeRoots::add(void* begin, void* end)
+{
+    ASSERT(begin <= end);
+    ASSERT((static_cast<char*>(end) - static_cast<char*>(begin)) < 0x1000000);
+    ASSERT(isPointerAligned(begin));
+    ASSERT(isPointerAligned(end));
+
+    for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it)
+        add(*it);
+}
+
+} // namespace JSC
diff --git a/heap/ConservativeRoots.h b/heap/ConservativeRoots.h
new file mode 100644 (file)
index 0000000..d078606
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 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 ConservativeRoots_h
+#define ConservativeRoots_h
+
+#include "Heap.h"
+#include <wtf/OSAllocator.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class JSCell;
+class Heap;
+
+// May contain duplicates.
+
+class ConservativeRoots {
+public:
+    ConservativeRoots(Heap*);
+    ~ConservativeRoots();
+
+    void add(void*);
+    void add(void* begin, void* end);
+    
+    size_t size();
+    JSCell** roots();
+
+private:
+    static const size_t inlineCapacity = 128;
+    static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*);
+    
+    void grow();
+
+    Heap* m_heap;
+    JSCell** m_roots;
+    size_t m_size;
+    size_t m_capacity;
+    JSCell* m_inlineRoots[inlineCapacity];
+};
+
+inline ConservativeRoots::ConservativeRoots(Heap* heap)
+    : m_heap(heap)
+    , m_roots(m_inlineRoots)
+    , m_size(0)
+    , m_capacity(inlineCapacity)
+{
+}
+
+inline ConservativeRoots::~ConservativeRoots()
+{
+    if (m_roots != m_inlineRoots)
+        OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*));
+}
+
+inline void ConservativeRoots::add(void* p)
+{
+    if (!m_heap->contains(p))
+        return;
+
+    if (m_size == m_capacity)
+        grow();
+
+    m_roots[m_size++] = reinterpret_cast<JSCell*>(p);
+}
+
+inline size_t ConservativeRoots::size()
+{
+    return m_size;
+}
+
+inline JSCell** ConservativeRoots::roots()
+{
+    return m_roots;
+}
+
+} // namespace JSC
+
+#endif // ConservativeRoots_h
diff --git a/heap/Handle.h b/heap/Handle.h
new file mode 100644 (file)
index 0000000..8ed2623
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 Handle_h
+#define Handle_h
+
+#include "HandleTypes.h"
+
+namespace JSC {
+
+/*
+    A Handle is a smart pointer that updates automatically when the garbage
+    collector moves the object to which it points.
+
+    The base Handle class represents a temporary reference to a pointer whose
+    lifetime is guaranteed by something else.
+*/
+
+template <class T> class Handle;
+
+// Creating a JSValue Handle is invalid
+template <> class Handle<JSValue>;
+
+// Forward declare WeakGCMap
+template<typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> class WeakGCMap;
+
+class HandleBase {
+    template <typename T> friend class Weak;
+    friend class HandleHeap;
+    friend struct JSCallbackObjectData;
+    template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap;
+
+public:
+    bool operator!() const { return !m_slot || !*m_slot; }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+    typedef JSValue (HandleBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+
+protected:
+    HandleBase(HandleSlot slot)
+        : m_slot(slot)
+    {
+    }
+    
+    void swap(HandleBase& other) { std::swap(m_slot, other.m_slot); }
+
+    HandleSlot slot() const { return m_slot; }
+    void setSlot(HandleSlot slot)
+    {
+        m_slot = slot;
+    }
+
+private:
+    HandleSlot m_slot;
+};
+
+template <typename Base, typename T> struct HandleConverter {
+    T* operator->()
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie());
+#endif
+        return static_cast<Base*>(this)->get();
+    }
+    const T* operator->() const
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie());
+#endif
+        return static_cast<const Base*>(this)->get();
+    }
+
+    T* operator*()
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie());
+#endif
+        return static_cast<Base*>(this)->get();
+    }
+    const T* operator*() const
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get()->isZombie());
+#endif
+        return static_cast<const Base*>(this)->get();
+    }
+};
+
+template <typename Base> struct HandleConverter<Base, Unknown> {
+    Handle<JSObject> asObject() const;
+    bool isObject() const { return jsValue().isObject(); }
+    bool getNumber(double number) const { return jsValue().getNumber(number); }
+    UString getString(ExecState*) const;
+    bool isUndefinedOrNull() const { return jsValue().isUndefinedOrNull(); }
+
+private:
+    JSValue jsValue() const
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!static_cast<const Base*>(this)->get() || !static_cast<const Base*>(this)->get().isZombie());
+#endif
+        return static_cast<const Base*>(this)->get();
+    }
+};
+
+template <typename T> class Handle : public HandleBase, public HandleConverter<Handle<T>, T> {
+public:
+    template <typename A, typename B> friend class HandleConverter;
+    typedef typename HandleTypes<T>::ExternalType ExternalType;
+    template <typename U> Handle(Handle<U> o)
+    {
+        typename HandleTypes<T>::template validateUpcast<U>();
+        setSlot(o.slot());
+    }
+
+    void swap(Handle& other) { HandleBase::swap(other); }
+
+    ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); }
+
+protected:
+    Handle(HandleSlot slot = 0)
+        : HandleBase(slot)
+    {
+    }
+    
+private:
+    friend class HandleHeap;
+
+    static Handle<T> wrapSlot(HandleSlot slot)
+    {
+        return Handle<T>(slot);
+    }
+};
+
+template <typename Base> Handle<JSObject> HandleConverter<Base, Unknown>::asObject() const
+{
+    return Handle<JSObject>::wrapSlot(static_cast<const Base*>(this)->slot());
+}
+
+template <typename T, typename U> inline bool operator==(const Handle<T>& a, const Handle<U>& b)
+{ 
+    return a.get() == b.get(); 
+}
+
+template <typename T, typename U> inline bool operator==(const Handle<T>& a, U* b)
+{ 
+    return a.get() == b; 
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const Handle<U>& b) 
+{
+    return a == b.get(); 
+}
+
+template <typename T, typename U> inline bool operator!=(const Handle<T>& a, const Handle<U>& b)
+{ 
+    return a.get() != b.get(); 
+}
+
+template <typename T, typename U> inline bool operator!=(const Handle<T>& a, U* b)
+{
+    return a.get() != b; 
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const Handle<U>& b)
+{ 
+    return a != b.get(); 
+}
+
+template <typename T, typename U> inline bool operator!=(const Handle<T>& a, JSValue b)
+{
+    return a.get() != b; 
+}
+
+template <typename T, typename U> inline bool operator!=(JSValue a, const Handle<U>& b)
+{ 
+    return a != b.get(); 
+}
+
+}
+
+#endif
diff --git a/heap/HandleHeap.cpp b/heap/HandleHeap.cpp
new file mode 100644 (file)
index 0000000..9b05db2
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "HandleHeap.h"
+
+#include "JSObject.h"
+
+namespace JSC {
+
+WeakHandleOwner::~WeakHandleOwner()
+{
+}
+
+bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&)
+{
+    return false;
+}
+
+void WeakHandleOwner::finalize(Handle<Unknown>, void*)
+{
+}
+
+HandleHeap::HandleHeap(JSGlobalData* globalData)
+    : m_globalData(globalData)
+    , m_nextToFinalize(0)
+{
+    grow();
+}
+
+void HandleHeap::grow()
+{
+    Node* block = m_blockStack.grow();
+    for (int i = m_blockStack.blockLength - 1; i >= 0; --i) {
+        Node* node = &block[i];
+        new (node) Node(this);
+        m_freeList.push(node);
+    }
+}
+
+void HandleHeap::markStrongHandles(HeapRootVisitor& heapRootMarker)
+{
+    Node* end = m_strongList.end();
+    for (Node* node = m_strongList.begin(); node != end; node = node->next())
+        heapRootMarker.mark(node->slot());
+}
+
+void HandleHeap::markWeakHandles(HeapRootVisitor& heapRootVisitor)
+{
+    SlotVisitor& visitor = heapRootVisitor.visitor();
+
+    Node* end = m_weakList.end();
+    for (Node* node = m_weakList.begin(); node != end; node = node->next()) {
+        ASSERT(isValidWeakNode(node));
+        JSCell* cell = node->slot()->asCell();
+        if (Heap::isMarked(cell))
+            continue;
+
+        WeakHandleOwner* weakOwner = node->weakOwner();
+        if (!weakOwner)
+            continue;
+
+        if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), visitor))
+            continue;
+
+        heapRootVisitor.mark(node->slot());
+    }
+}
+
+void HandleHeap::finalizeWeakHandles()
+{
+    Node* end = m_weakList.end();
+    for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) {
+        m_nextToFinalize = node->next();
+
+        ASSERT(isValidWeakNode(node));
+        JSCell* cell = node->slot()->asCell();
+        if (Heap::isMarked(cell))
+            continue;
+
+        if (WeakHandleOwner* weakOwner = node->weakOwner()) {
+            weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext());
+            if (m_nextToFinalize != node->next()) // Owner deallocated node.
+                continue;
+        }
+
+        *node->slot() = JSValue();
+        SentinelLinkedList<Node>::remove(node);
+        m_immediateList.push(node);
+    }
+    
+    m_nextToFinalize = 0;
+}
+
+void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value)
+{
+    ASSERT(!m_nextToFinalize); // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
+
+    if (!value == !*slot && slot->isCell() == value.isCell())
+        return;
+
+    Node* node = toNode(slot);
+    SentinelLinkedList<Node>::remove(node);
+    if (!value || !value.isCell()) {
+        m_immediateList.push(node);
+        return;
+    }
+
+    if (node->isWeak()) {
+        m_weakList.push(node);
+        return;
+    }
+
+    m_strongList.push(node);
+}
+
+unsigned HandleHeap::protectedGlobalObjectCount()
+{
+    unsigned count = 0;
+    Node* end = m_strongList.end();
+    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+        JSValue value = *node->slot();
+        if (value.isObject() && asObject(value.asCell())->isGlobalObject())
+            count++;
+    }
+    return count;
+}
+
+#if !ASSERT_DISABLED
+bool HandleHeap::isValidWeakNode(Node* node)
+{
+    if (!node->isWeak())
+        return false;
+
+    JSValue value = *node->slot();
+    if (!value || !value.isCell())
+        return false;
+
+    JSCell* cell = value.asCell();
+    if (!cell || !cell->structure())
+        return false;
+
+#if ENABLE(JSC_ZOMBIES)
+    if (cell->isZombie())
+        return false;
+#endif
+
+    return true;
+}
+#endif
+
+} // namespace JSC
diff --git a/heap/HandleHeap.h b/heap/HandleHeap.h
new file mode 100644 (file)
index 0000000..41b7fb2
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 HandleHeap_h
+#define HandleHeap_h
+
+#include "BlockStack.h"
+#include "Handle.h"
+#include "SentinelLinkedList.h"
+#include "SinglyLinkedList.h"
+
+namespace JSC {
+
+class HandleHeap;
+class HeapRootVisitor;
+class JSGlobalData;
+class JSValue;
+class MarkStack;
+class TypeCounter;
+typedef MarkStack SlotVisitor;
+
+class WeakHandleOwner {
+public:
+    virtual ~WeakHandleOwner();
+    virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&);
+    virtual void finalize(Handle<Unknown>, void* context);
+};
+
+class HandleHeap {
+public:
+    static HandleHeap* heapFor(HandleSlot);
+
+    HandleHeap(JSGlobalData*);
+    
+    JSGlobalData* globalData();
+
+    HandleSlot allocate();
+    void deallocate(HandleSlot);
+
+    void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);
+    HandleSlot copyWeak(HandleSlot);
+
+    void markStrongHandles(HeapRootVisitor&);
+    void markWeakHandles(HeapRootVisitor&);
+    void finalizeWeakHandles();
+
+    void writeBarrier(HandleSlot, const JSValue&);
+
+#if !ASSERT_DISABLED
+    bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
+    bool hasFinalizer(HandleSlot);
+#endif
+
+    unsigned protectedGlobalObjectCount();
+    void protectedObjectTypeCounts(TypeCounter&);
+
+private:
+    class Node {
+    public:
+        Node(WTF::SentinelTag);
+        Node(HandleHeap*);
+        
+        HandleSlot slot();
+        HandleHeap* handleHeap();
+
+        void makeWeak(WeakHandleOwner*, void* context);
+        bool isWeak();
+        
+        WeakHandleOwner* weakOwner();
+        void* weakOwnerContext();
+
+        void setPrev(Node*);
+        Node* prev();
+
+        void setNext(Node*);
+        Node* next();
+
+    private:
+        WeakHandleOwner* emptyWeakOwner();
+
+        JSValue m_value;
+        HandleHeap* m_handleHeap;
+        WeakHandleOwner* m_weakOwner;
+        void* m_weakOwnerContext;
+        Node* m_prev;
+        Node* m_next;
+    };
+
+    static HandleSlot toHandle(Node*);
+    static Node* toNode(HandleSlot);
+
+    void grow();
+    
+#if !ASSERT_DISABLED
+    bool isValidWeakNode(Node*);
+#endif
+
+    JSGlobalData* m_globalData;
+    BlockStack<Node> m_blockStack;
+
+    SentinelLinkedList<Node> m_strongList;
+    SentinelLinkedList<Node> m_weakList;
+    SentinelLinkedList<Node> m_immediateList;
+    SinglyLinkedList<Node> m_freeList;
+    Node* m_nextToFinalize;
+};
+
+inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
+{
+    return toNode(handle)->handleHeap();
+}
+
+inline JSGlobalData* HandleHeap::globalData()
+{
+    return m_globalData;
+}
+
+inline HandleSlot HandleHeap::toHandle(Node* node)
+{
+    return reinterpret_cast<HandleSlot>(node);
+}
+
+inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle)
+{
+    return reinterpret_cast<Node*>(handle);
+}
+
+inline HandleSlot HandleHeap::allocate()
+{
+    if (m_freeList.isEmpty())
+        grow();
+
+    Node* node = m_freeList.pop();
+    new (node) Node(this);
+    m_immediateList.push(node);
+    return toHandle(node);
+}
+
+inline void HandleHeap::deallocate(HandleSlot handle)
+{
+    Node* node = toNode(handle);
+    if (node == m_nextToFinalize) {
+        m_nextToFinalize = node->next();
+        ASSERT(m_nextToFinalize->next());
+    }
+
+    SentinelLinkedList<Node>::remove(node);
+    m_freeList.push(node);
+}
+
+inline HandleSlot HandleHeap::copyWeak(HandleSlot other)
+{
+    Node* node = toNode(allocate());
+    node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext());
+    writeBarrier(node->slot(), *other);
+    *node->slot() = *other;
+    return toHandle(node);
+}
+
+inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)
+{
+    Node* node = toNode(handle);
+    node->makeWeak(weakOwner, context);
+
+    SentinelLinkedList<Node>::remove(node);
+    if (!*handle || !handle->isCell()) {
+        m_immediateList.push(node);
+        return;
+    }
+
+    m_weakList.push(node);
+}
+
+#if !ASSERT_DISABLED
+inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)
+{
+    return toNode(handle)->weakOwner() == weakOwner;
+}
+
+inline bool HandleHeap::hasFinalizer(HandleSlot handle)
+{
+    return toNode(handle)->weakOwner();
+}
+#endif
+
+inline HandleHeap::Node::Node(HandleHeap* handleHeap)
+    : m_handleHeap(handleHeap)
+    , m_weakOwner(0)
+    , m_weakOwnerContext(0)
+{
+}
+
+inline HandleHeap::Node::Node(WTF::SentinelTag)
+    : m_handleHeap(0)
+    , m_weakOwner(0)
+    , m_weakOwnerContext(0)
+{
+}
+
+inline HandleSlot HandleHeap::Node::slot()
+{
+    return &m_value;
+}
+
+inline HandleHeap* HandleHeap::Node::handleHeap()
+{
+    return m_handleHeap;
+}
+
+inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)
+{
+    m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();
+    m_weakOwnerContext = context;
+}
+
+inline bool HandleHeap::Node::isWeak()
+{
+    return m_weakOwner; // True for emptyWeakOwner().
+}
+
+inline WeakHandleOwner* HandleHeap::Node::weakOwner()
+{
+    return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().
+}
+
+inline void* HandleHeap::Node::weakOwnerContext()
+{
+    ASSERT(weakOwner());
+    return m_weakOwnerContext;
+}
+
+inline void HandleHeap::Node::setPrev(Node* prev)
+{
+    m_prev = prev;
+}
+
+inline HandleHeap::Node* HandleHeap::Node::prev()
+{
+    return m_prev;
+}
+
+inline void HandleHeap::Node::setNext(Node* next)
+{
+    m_next = next;
+}
+
+inline HandleHeap::Node* HandleHeap::Node::next()
+{
+    return m_next;
+}
+
+// Sentinel to indicate that a node is weak, but its owner has no meaningful
+// callbacks. This allows us to optimize by skipping such nodes.
+inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
+{
+    return reinterpret_cast<WeakHandleOwner*>(-1);
+}
+
+}
+
+#endif
diff --git a/heap/HandleStack.cpp b/heap/HandleStack.cpp
new file mode 100644 (file)
index 0000000..ada4f99
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+
+#include "HandleStack.h"
+
+#include "MarkStack.h"
+
+namespace JSC {
+
+HandleStack::HandleStack()
+#ifndef NDEBUG
+    : m_scopeDepth(0)
+#endif
+{
+    grow();
+}
+
+void HandleStack::mark(HeapRootVisitor& heapRootMarker)
+{
+    const Vector<HandleSlot>& blocks = m_blockStack.blocks();
+    size_t blockLength = m_blockStack.blockLength;
+
+    int end = blocks.size() - 1;
+    for (int i = 0; i < end; ++i) {
+        HandleSlot block = blocks[i];
+        heapRootMarker.mark(block, blockLength);
+    }
+    HandleSlot block = blocks[end];
+    heapRootMarker.mark(block, m_frame.m_next - block);
+}
+
+void HandleStack::grow()
+{
+    HandleSlot block = m_blockStack.grow();
+    m_frame.m_next = block;
+    m_frame.m_end = block + m_blockStack.blockLength;
+}
+
+}
diff --git a/heap/HandleStack.h b/heap/HandleStack.h
new file mode 100644 (file)
index 0000000..115784a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 HandleStack_h
+#define HandleStack_h
+
+#include "Assertions.h"
+#include "BlockStack.h"
+#include "Handle.h"
+
+#include <wtf/UnusedParam.h>
+
+namespace JSC {
+
+class LocalScope;
+class HeapRootVisitor;
+
+class HandleStack {
+public:
+    class Frame {
+    public:
+        HandleSlot m_next;
+        HandleSlot m_end;
+    };
+
+    HandleStack();
+    
+    void enterScope(Frame&);
+    void leaveScope(Frame&);
+
+    HandleSlot push();
+
+    void mark(HeapRootVisitor&);
+
+private:
+    void grow();
+    void zapTo(Frame&);
+    HandleSlot findFirstAfter(HandleSlot);
+
+#ifndef NDEBUG
+    size_t m_scopeDepth;
+#endif
+    BlockStack<JSValue> m_blockStack;
+    Frame m_frame;
+};
+
+inline void HandleStack::enterScope(Frame& lastFrame)
+{
+#ifndef NDEBUG
+    ++m_scopeDepth;
+#endif
+
+    lastFrame = m_frame;
+}
+
+
+
+inline void HandleStack::zapTo(Frame& lastFrame)
+{
+#ifdef NDEBUG
+    UNUSED_PARAM(lastFrame);
+#else
+    const Vector<HandleSlot>& blocks = m_blockStack.blocks();
+    
+    if (lastFrame.m_end != m_frame.m_end) { // Zapping to a frame in a different block.
+        int i = blocks.size() - 1;
+        for ( ; blocks[i] + m_blockStack.blockLength != lastFrame.m_end; --i) {
+            for (int j = m_blockStack.blockLength - 1; j >= 0; --j)
+                blocks[i][j] = JSValue();
+        }
+        
+        for (HandleSlot it = blocks[i] + m_blockStack.blockLength - 1; it != lastFrame.m_next - 1; --it)
+            *it = JSValue();
+        
+        return;
+    }
+    
+    for (HandleSlot it = m_frame.m_next - 1; it != lastFrame.m_next - 1; --it)
+        *it = JSValue();
+#endif
+}
+
+inline void HandleStack::leaveScope(Frame& lastFrame)
+{
+#ifndef NDEBUG
+    --m_scopeDepth;
+#endif
+
+    zapTo(lastFrame);
+
+    if (lastFrame.m_end != m_frame.m_end) // Popping to a frame in a different block.
+        m_blockStack.shrink(lastFrame.m_end);
+
+    m_frame = lastFrame;
+}
+
+inline HandleSlot HandleStack::push()
+{
+    ASSERT(m_scopeDepth); // Creating a Local outside of a LocalScope is a memory leak.
+    if (m_frame.m_next == m_frame.m_end)
+        grow();
+    return m_frame.m_next++;
+}
+
+}
+
+#endif
diff --git a/heap/HandleTypes.h b/heap/HandleTypes.h
new file mode 100644 (file)
index 0000000..780ab85
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 HandleTypes_h
+#define HandleTypes_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+typedef enum { } Unknown;
+typedef JSValue* HandleSlot;
+
+template<typename T> struct HandleTypes {
+    typedef T* ExternalType;
+    static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast<ExternalType>(slot->asCell()) : 0; }
+    static JSValue toJSValue(T* cell) { return reinterpret_cast<JSCell*>(cell); }
+    template<typename U> static void validateUpcast() { T* temp; temp = (U*)0; }
+};
+
+template<> struct HandleTypes<Unknown> {
+    typedef JSValue ExternalType;
+    static ExternalType getFromSlot(HandleSlot slot) { return slot ? *slot : JSValue(); }
+    static JSValue toJSValue(const JSValue& v) { return v; }
+    template<typename U> static void validateUpcast() { }
+};
+
+} // namespace JSC
+
+#endif // HandleTypes_h
diff --git a/heap/Heap.cpp b/heap/Heap.cpp
new file mode 100644 (file)
index 0000000..e93bfb4
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "Heap.h"
+
+#include "CodeBlock.h"
+#include "ConservativeRoots.h"
+#include "GCActivityCallback.h"
+#include "Interpreter.h"
+#include "JSGlobalData.h"
+#include "JSGlobalObject.h"
+#include "JSLock.h"
+#include "JSONObject.h"
+#include "Tracing.h"
+#include <algorithm>
+
+#define COLLECT_ON_EVERY_SLOW_ALLOCATION 0
+
+using namespace std;
+
+namespace JSC {
+
+const size_t minBytesPerCycle = 512 * 1024;
+
+Heap::Heap(JSGlobalData* globalData)
+    : m_operationInProgress(NoOperation)
+    , m_markedSpace(globalData)
+    , m_markListSet(0)
+    , m_activityCallback(DefaultGCActivityCallback::create(this))
+    , m_globalData(globalData)
+    , m_machineThreads(this)
+    , m_markStack(globalData->jsArrayVPtr)
+    , m_handleHeap(globalData)
+    , m_extraCost(0)
+{
+    m_markedSpace.setHighWaterMark(minBytesPerCycle);
+    (*m_activityCallback)();
+}
+
+Heap::~Heap()
+{
+    // The destroy function must already have been called, so assert this.
+    ASSERT(!m_globalData);
+}
+
+void Heap::destroy()
+{
+    JSLock lock(SilenceAssertionsOnly);
+
+    if (!m_globalData)
+        return;
+
+    ASSERT(!m_globalData->dynamicGlobalObject);
+    ASSERT(m_operationInProgress == NoOperation);
+    
+    // The global object is not GC protected at this point, so sweeping may delete it
+    // (and thus the global data) before other objects that may use the global data.
+    RefPtr<JSGlobalData> protect(m_globalData);
+
+#if ENABLE(JIT)
+    m_globalData->jitStubs->clearHostFunctionStubs();
+#endif
+
+    delete m_markListSet;
+    m_markListSet = 0;
+    m_markedSpace.clearMarks();
+    m_handleHeap.finalizeWeakHandles();
+    m_markedSpace.destroy();
+
+    m_globalData = 0;
+}
+
+void Heap::reportExtraMemoryCostSlowCase(size_t cost)
+{
+    // Our frequency of garbage collection tries to balance memory use against speed
+    // by collecting based on the number of newly created values. However, for values
+    // that hold on to a great deal of memory that's not in the form of other JS values,
+    // that is not good enough - in some cases a lot of those objects can pile up and
+    // use crazy amounts of memory without a GC happening. So we track these extra
+    // memory costs. Only unusually large objects are noted, and we only keep track
+    // of this extra cost until the next GC. In garbage collected languages, most values
+    // are either very short lived temporaries, or have extremely long lifetimes. So
+    // if a large value survives one garbage collection, there is not much point to
+    // collecting more frequently as long as it stays alive.
+
+    if (m_extraCost > maxExtraCost && m_extraCost > m_markedSpace.highWaterMark() / 2)
+        collectAllGarbage();
+    m_extraCost += cost;
+}
+
+void* Heap::allocateSlowCase(size_t bytes)
+{
+    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
+    ASSERT(JSLock::lockCount() > 0);
+    ASSERT(JSLock::currentThreadIsHoldingLock());
+    ASSERT(bytes <= MarkedSpace::maxCellSize);
+    ASSERT(m_operationInProgress == NoOperation);
+
+#if COLLECT_ON_EVERY_SLOW_ALLOCATION
+    collectAllGarbage();
+    ASSERT(m_operationInProgress == NoOperation);
+#endif
+
+    reset(DoNotSweep);
+
+    m_operationInProgress = Allocation;
+    void* result = m_markedSpace.allocate(bytes);
+    m_operationInProgress = NoOperation;
+
+    ASSERT(result);
+    return result;
+}
+
+void Heap::protect(JSValue k)
+{
+    ASSERT(k);
+    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
+
+    if (!k.isCell())
+        return;
+
+    m_protectedValues.add(k.asCell());
+}
+
+bool Heap::unprotect(JSValue k)
+{
+    ASSERT(k);
+    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
+
+    if (!k.isCell())
+        return false;
+
+    return m_protectedValues.remove(k.asCell());
+}
+
+void Heap::markProtectedObjects(HeapRootVisitor& heapRootMarker)
+{
+    ProtectCountSet::iterator end = m_protectedValues.end();
+    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+        heapRootMarker.mark(&it->first);
+}
+
+void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
+{
+    m_tempSortingVectors.append(tempVector);
+}
+
+void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
+{
+    ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
+    m_tempSortingVectors.removeLast();
+}
+    
+void Heap::markTempSortVectors(HeapRootVisitor& heapRootMarker)
+{
+    typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
+
+    VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
+    for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
+        Vector<ValueStringPair>* tempSortingVector = *it;
+
+        Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
+        for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
+            if (vectorIt->first)
+                heapRootMarker.mark(&vectorIt->first);
+        }
+    }
+}
+
+inline RegisterFile& Heap::registerFile()
+{
+    return m_globalData->interpreter->registerFile();
+}
+
+void Heap::getConservativeRegisterRoots(HashSet<JSCell*>& roots)
+{
+#ifndef NDEBUG
+    if (m_globalData->isSharedInstance()) {
+        ASSERT(JSLock::lockCount() > 0);
+        ASSERT(JSLock::currentThreadIsHoldingLock());
+    }
+#endif
+    if (m_operationInProgress != NoOperation)
+        CRASH();
+    m_operationInProgress = Collection;
+    ConservativeRoots registerFileRoots(this);
+    registerFile().gatherConservativeRoots(registerFileRoots);
+    size_t registerFileRootCount = registerFileRoots.size();
+    JSCell** registerRoots = registerFileRoots.roots();
+    for (size_t i = 0; i < registerFileRootCount; i++) {
+        setMarked(registerRoots[i]);
+        roots.add(registerRoots[i]);
+    }
+    m_operationInProgress = NoOperation;
+}
+
+void Heap::markRoots()
+{
+#ifndef NDEBUG
+    if (m_globalData->isSharedInstance()) {
+        ASSERT(JSLock::lockCount() > 0);
+        ASSERT(JSLock::currentThreadIsHoldingLock());
+    }
+#endif
+
+    void* dummy;
+
+    ASSERT(m_operationInProgress == NoOperation);
+    if (m_operationInProgress != NoOperation)
+        CRASH();
+
+    m_operationInProgress = Collection;
+
+    MarkStack& visitor = m_markStack;
+    HeapRootVisitor heapRootMarker(visitor);
+    
+    // We gather conservative roots before clearing mark bits because
+    // conservative gathering uses the mark bits from our last mark pass to
+    // determine whether a reference is valid.
+    ConservativeRoots machineThreadRoots(this);
+    m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);
+
+    ConservativeRoots registerFileRoots(this);
+    registerFile().gatherConservativeRoots(registerFileRoots);
+
+    m_markedSpace.clearMarks();
+
+    visitor.append(machineThreadRoots);
+    visitor.drain();
+
+    visitor.append(registerFileRoots);
+    visitor.drain();
+
+    markProtectedObjects(heapRootMarker);
+    visitor.drain();
+    
+    markTempSortVectors(heapRootMarker);
+    visitor.drain();
+
+    if (m_markListSet && m_markListSet->size())
+        MarkedArgumentBuffer::markLists(heapRootMarker, *m_markListSet);
+    if (m_globalData->exception)
+        heapRootMarker.mark(&m_globalData->exception);
+    visitor.drain();
+
+    m_handleHeap.markStrongHandles(heapRootMarker);
+    visitor.drain();
+
+    m_handleStack.mark(heapRootMarker);
+    visitor.drain();
+
+    // Mark the small strings cache as late as possible, since it will clear
+    // itself if nothing else has marked it.
+    // FIXME: Change the small strings cache to use Weak<T>.
+    m_globalData->smallStrings.visitChildren(heapRootMarker);
+    visitor.drain();
+    
+    // Weak handles must be marked last, because their owners use the set of
+    // opaque roots to determine reachability.
+    int lastOpaqueRootCount;
+    do {
+        lastOpaqueRootCount = visitor.opaqueRootCount();
+        m_handleHeap.markWeakHandles(heapRootMarker);
+        visitor.drain();
+    // If the set of opaque roots has grown, more weak handles may have become reachable.
+    } while (lastOpaqueRootCount != visitor.opaqueRootCount());
+
+    visitor.reset();
+
+    m_operationInProgress = NoOperation;
+}
+
+size_t Heap::objectCount() const
+{
+    return m_markedSpace.objectCount();
+}
+
+size_t Heap::size() const
+{
+    return m_markedSpace.size();
+}
+
+size_t Heap::capacity() const
+{
+    return m_markedSpace.capacity();
+}
+
+size_t Heap::globalObjectCount()
+{
+    return m_globalData->globalObjectCount;
+}
+
+size_t Heap::protectedGlobalObjectCount()
+{
+    size_t count = m_handleHeap.protectedGlobalObjectCount();
+
+    ProtectCountSet::iterator end = m_protectedValues.end();
+    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
+        if (it->first->isObject() && asObject(it->first)->isGlobalObject())
+            count++;
+    }
+
+    return count;
+}
+
+size_t Heap::protectedObjectCount()
+{
+    return m_protectedValues.size();
+}
+
+class TypeCounter {
+public:
+    TypeCounter();
+    void operator()(JSCell*);
+    PassOwnPtr<TypeCountSet> take();
+    
+private:
+    const char* typeName(JSCell*);
+    OwnPtr<TypeCountSet> m_typeCountSet;
+    HashSet<JSCell*> m_cells;
+};
+
+inline TypeCounter::TypeCounter()
+    : m_typeCountSet(adoptPtr(new TypeCountSet))
+{
+}
+
+inline const char* TypeCounter::typeName(JSCell* cell)
+{
+    if (cell->isString())
+        return "string";
+    if (cell->isGetterSetter())
+        return "Getter-Setter";
+    if (cell->isAPIValueWrapper())
+        return "API wrapper";
+    if (cell->isPropertyNameIterator())
+        return "For-in iterator";
+    if (const ClassInfo* info = cell->classInfo())
+        return info->className;
+    if (!cell->isObject())
+        return "[empty cell]";
+    return "Object";
+}
+
+inline void TypeCounter::operator()(JSCell* cell)
+{
+    if (!m_cells.add(cell).second)
+        return;
+    m_typeCountSet->add(typeName(cell));
+}
+
+inline PassOwnPtr<TypeCountSet> TypeCounter::take()
+{
+    return m_typeCountSet.release();
+}
+
+PassOwnPtr<TypeCountSet> Heap::protectedObjectTypeCounts()
+{
+    TypeCounter typeCounter;
+
+    ProtectCountSet::iterator end = m_protectedValues.end();
+    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+        typeCounter(it->first);
+    m_handleHeap.protectedObjectTypeCounts(typeCounter);
+
+    return typeCounter.take();
+}
+
+void HandleHeap::protectedObjectTypeCounts(TypeCounter& typeCounter)
+{
+    Node* end = m_strongList.end();
+    for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+        JSValue value = *node->slot();
+        if (value && value.isCell())
+            typeCounter(value.asCell());
+    }
+}
+
+PassOwnPtr<TypeCountSet> Heap::objectTypeCounts()
+{
+    TypeCounter typeCounter;
+    forEach(typeCounter);
+    return typeCounter.take();
+}
+
+void Heap::collectAllGarbage()
+{
+    m_markStack.setShouldUnlinkCalls(true);
+    reset(DoSweep);
+    m_markStack.setShouldUnlinkCalls(false);
+}
+
+void Heap::reset(SweepToggle sweepToggle)
+{
+    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
+    JAVASCRIPTCORE_GC_BEGIN();
+
+    markRoots();
+    m_handleHeap.finalizeWeakHandles();
+
+    JAVASCRIPTCORE_GC_MARKED();
+
+    m_markedSpace.reset();
+    m_extraCost = 0;
+
+#if ENABLE(JSC_ZOMBIES)
+    sweepToggle = DoSweep;
+#endif
+
+    if (sweepToggle == DoSweep) {
+        m_markedSpace.sweep();
+        m_markedSpace.shrink();
+    }
+
+    // To avoid pathological GC churn in large heaps, we set the allocation high
+    // water mark to be proportional to the current size of the heap. The exact
+    // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size :
+    // new bytes allocated) proportion, and seems to work well in benchmarks.
+    size_t proportionalBytes = 2 * m_markedSpace.size();
+    m_markedSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle));
+
+    JAVASCRIPTCORE_GC_END();
+
+    (*m_activityCallback)();
+}
+
+void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
+{
+    m_activityCallback = activityCallback;
+}
+
+GCActivityCallback* Heap::activityCallback()
+{
+    return m_activityCallback.get();
+}
+
+} // namespace JSC
diff --git a/heap/Heap.h b/heap/Heap.h
new file mode 100644 (file)
index 0000000..feba1cf
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef Heap_h
+#define Heap_h
+
+#include "HandleHeap.h"
+#include "HandleStack.h"
+#include "MarkStack.h"
+#include "MarkedSpace.h"
+#include <wtf/Forward.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/HashSet.h>
+
+namespace JSC {
+
+    class GCActivityCallback;
+    class GlobalCodeBlock;
+    class HeapRootVisitor;
+    class JSCell;
+    class JSGlobalData;
+    class JSValue;
+    class LiveObjectIterator;
+    class MarkStack;
+    class MarkedArgumentBuffer;
+    class RegisterFile;
+    class UString;
+    class WeakGCHandlePool;
+    typedef MarkStack SlotVisitor;
+
+    typedef std::pair<JSValue, UString> ValueStringPair;
+    typedef HashCountedSet<JSCell*> ProtectCountSet;
+    typedef HashCountedSet<const char*> TypeCountSet;
+
+    enum OperationInProgress { NoOperation, Allocation, Collection };
+
+    class Heap {
+        WTF_MAKE_NONCOPYABLE(Heap);
+    public:
+        static Heap* heap(JSValue); // 0 for immediate values
+        static Heap* heap(JSCell*);
+
+        static bool isMarked(const JSCell*);
+        static bool testAndSetMarked(const JSCell*);
+        static void setMarked(JSCell*);
+
+        static void writeBarrier(const JSCell*, JSValue);
+        static void writeBarrier(const JSCell*, JSCell*);
+
+        Heap(JSGlobalData*);
+        ~Heap();
+        void destroy(); // JSGlobalData must call destroy() before ~Heap().
+
+        JSGlobalData* globalData() const { return m_globalData; }
+        MarkedSpace& markedSpace() { return m_markedSpace; }
+        MachineThreads& machineThreads() { return m_machineThreads; }
+
+        GCActivityCallback* activityCallback();
+        void setActivityCallback(PassOwnPtr<GCActivityCallback>);
+
+        // true if an allocation or collection is in progress
+        inline bool isBusy();
+
+        void* allocate(size_t);
+        void collectAllGarbage();
+
+        void reportExtraMemoryCost(size_t cost);
+
+        void protect(JSValue);
+        bool unprotect(JSValue); // True when the protect count drops to 0.
+
+        bool contains(void*);
+
+        size_t size() const;
+        size_t capacity() const;
+        size_t objectCount() const;
+        size_t globalObjectCount();
+        size_t protectedObjectCount();
+        size_t protectedGlobalObjectCount();
+        PassOwnPtr<TypeCountSet> protectedObjectTypeCounts();
+        PassOwnPtr<TypeCountSet> objectTypeCounts();
+
+        void pushTempSortVector(Vector<ValueStringPair>*);
+        void popTempSortVector(Vector<ValueStringPair>*);
+    
+        HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
+        
+        template <typename Functor> void forEach(Functor&);
+        
+        HandleSlot allocateGlobalHandle() { return m_handleHeap.allocate(); }
+        HandleSlot allocateLocalHandle() { return m_handleStack.push(); }
+
+        HandleStack* handleStack() { return &m_handleStack; }
+        void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
+
+    private:
+        friend class JSGlobalData;
+
+        static const size_t minExtraCost = 256;
+        static const size_t maxExtraCost = 1024 * 1024;
+
+        void* allocateSlowCase(size_t);
+        void reportExtraMemoryCostSlowCase(size_t);
+
+        void markRoots();
+        void markProtectedObjects(HeapRootVisitor&);
+        void markTempSortVectors(HeapRootVisitor&);
+
+        enum SweepToggle { DoNotSweep, DoSweep };
+        void reset(SweepToggle);
+
+        RegisterFile& registerFile();
+
+        OperationInProgress m_operationInProgress;
+        MarkedSpace m_markedSpace;
+
+        ProtectCountSet m_protectedValues;
+        Vector<Vector<ValueStringPair>* > m_tempSortingVectors;
+
+        HashSet<MarkedArgumentBuffer*>* m_markListSet;
+
+        OwnPtr<GCActivityCallback> m_activityCallback;
+
+        JSGlobalData* m_globalData;
+        
+        MachineThreads m_machineThreads;
+        MarkStack m_markStack;
+        HandleHeap m_handleHeap;
+        HandleStack m_handleStack;
+
+        size_t m_extraCost;
+    };
+
+    bool Heap::isBusy()
+    {
+        return m_operationInProgress != NoOperation;
+    }
+
+    inline bool Heap::isMarked(const JSCell* cell)
+    {
+        return MarkedSpace::isMarked(cell);
+    }
+
+    inline bool Heap::testAndSetMarked(const JSCell* cell)
+    {
+        return MarkedSpace::testAndSetMarked(cell);
+    }
+
+    inline void Heap::setMarked(JSCell* cell)
+    {
+        MarkedSpace::setMarked(cell);
+    }
+
+    inline void Heap::writeBarrier(const JSCell*, JSValue)
+    {
+    }
+
+    inline void Heap::writeBarrier(const JSCell*, JSCell*)
+    {
+    }
+
+    inline bool Heap::contains(void* p)
+    {
+        return m_markedSpace.contains(p);
+    }
+
+    inline void Heap::reportExtraMemoryCost(size_t cost)
+    {
+        if (cost > minExtraCost) 
+            reportExtraMemoryCostSlowCase(cost);
+    }
+
+    template <typename Functor> inline void Heap::forEach(Functor& functor)
+    {
+        m_markedSpace.forEach(functor);
+    }
+
+} // namespace JSC
+
+#endif // Heap_h
diff --git a/heap/Local.h b/heap/Local.h
new file mode 100644 (file)
index 0000000..ac7d136
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 Local_h
+#define Local_h
+
+#include "Handle.h"
+#include "JSGlobalData.h"
+
+/*
+    A strongly referenced handle whose lifetime is temporary, limited to a given
+    LocalScope. Use Locals for local values on the stack. It is an error to
+    create a Local outside of any LocalScope.
+*/
+
+namespace JSC {
+
+template <typename T> class Local : public Handle<T> {
+    friend class LocalScope;
+    using Handle<T>::slot;
+
+public:
+    typedef typename Handle<T>::ExternalType ExternalType;
+
+    Local(JSGlobalData&, ExternalType = ExternalType());
+    Local(JSGlobalData&, Handle<T>);
+    Local(const Local<T>&); // Adopting constructor. Used to return a Local to a calling function.
+
+    Local& operator=(ExternalType);
+    Local& operator=(Handle<T>);
+
+private:
+    Local(HandleSlot, ExternalType); // Used by LocalScope::release() to move a Local to a containing scope.
+    void set(ExternalType);
+};
+
+template <typename T> inline Local<T>::Local(JSGlobalData& globalData, ExternalType value)
+    : Handle<T>(globalData.allocateLocalHandle())
+{
+    set(value);
+}
+
+template <typename T> inline Local<T>::Local(JSGlobalData& globalData, Handle<T> other)
+    : Handle<T>(globalData.allocateLocalHandle())
+{
+    set(other.get());
+}
+
+template <typename T> inline Local<T>::Local(const Local<T>& other)
+    : Handle<T>(other.slot())
+{
+    const_cast<Local<T>&>(other).setSlot(0); // Prevent accidental sharing.
+}
+
+template <typename T> inline Local<T>::Local(HandleSlot slot, ExternalType value)
+    : Handle<T>(slot, value)
+{
+}
+
+template <typename T> inline Local<T>& Local<T>::operator=(ExternalType value)
+{
+    set(value);
+    return *this;
+}
+
+template <typename T> inline Local<T>& Local<T>::operator=(Handle<T> other)
+{
+    set(other.get());
+    return *this;
+}
+
+template <typename T> inline void Local<T>::set(ExternalType externalType)
+{
+    ASSERT(slot());
+    ASSERT(!HandleTypes<T>::toJSValue(externalType) || !HandleTypes<T>::toJSValue(externalType).isCell() || Heap::isMarked(HandleTypes<T>::toJSValue(externalType).asCell()));
+    *slot() = externalType;
+}
+
+
+template <typename T, unsigned inlineCapacity = 0> class LocalStack {
+    typedef typename Handle<T>::ExternalType ExternalType;
+public:
+    LocalStack(JSGlobalData& globalData)
+        : m_globalData(&globalData)
+        , m_count(0)
+    {
+    }
+
+    ExternalType peek() const
+    {
+        ASSERT(m_count > 0);
+        return m_stack[m_count - 1].get();
+    }
+
+    ExternalType pop()
+    {
+        ASSERT(m_count > 0);
+        return m_stack[--m_count].get();
+    }
+
+    void push(ExternalType value)
+    {
+        if (m_count == m_stack.size())
+            m_stack.append(Local<T>(*m_globalData, value));
+        else
+            m_stack[m_count] = value;
+        m_count++;
+    }
+
+    bool isEmpty() const { return !m_count; }
+    unsigned size() const { return m_count; }
+
+private:
+    RefPtr<JSGlobalData> m_globalData;
+    Vector<Local<T>, inlineCapacity> m_stack;
+    unsigned m_count;
+};
+
+}
+
+namespace WTF {
+
+template<typename T> struct VectorTraits<JSC::Local<T> > : SimpleClassVectorTraits {
+    static const bool needsDestruction = false;
+    static const bool canInitializeWithMemset = false;
+    static const bool canCompareWithMemcmp = false;
+};
+
+}
+
+#endif
diff --git a/heap/LocalScope.h b/heap/LocalScope.h
new file mode 100644 (file)
index 0000000..cd27b32
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 LocalScope_h
+#define LocalScope_h
+
+#include "HandleStack.h"
+#include "Local.h"
+
+namespace JSC {
+/*  
+    A LocalScope is a temporary scope in which Locals are allocated. When a
+    LocalScope goes out of scope, all the Locals created in it are destroyed.
+
+    LocalScope is similar in concept to NSAutoreleasePool.
+*/
+
+class JSGlobalData;
+
+class LocalScope {
+public:
+    explicit LocalScope(JSGlobalData&);
+    ~LocalScope();
+    
+    template <typename T> Local<T> release(Local<T>); // Destroys all other locals in the scope.
+
+private:
+    HandleStack* m_handleStack;
+    HandleStack::Frame m_lastFrame;
+};
+
+inline LocalScope::LocalScope(JSGlobalData& globalData)
+    : m_handleStack(globalData.heap.handleStack())
+{
+    m_handleStack->enterScope(m_lastFrame);
+}
+
+inline LocalScope::~LocalScope()
+{
+    m_handleStack->leaveScope(m_lastFrame);
+}
+
+template <typename T> Local<T> LocalScope::release(Local<T> local)
+{
+    typename Local<T>::ExternalType ptr = local.get();
+
+    m_handleStack->leaveScope(m_lastFrame);
+    HandleSlot slot = m_handleStack->push();
+    m_handleStack->enterScope(m_lastFrame);
+
+    return Local<T>(slot, ptr);
+}
+
+}
+
+#endif
diff --git a/heap/MachineStackMarker.cpp b/heap/MachineStackMarker.cpp
new file mode 100644 (file)
index 0000000..73a3db6
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *  Copyright (C) 2009 Acision BV. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "MachineStackMarker.h"
+
+#include "ConservativeRoots.h"
+#include "Heap.h"
+#include "JSArray.h"
+#include "JSGlobalData.h"
+#include <setjmp.h>
+#include <stdlib.h>
+#include <wtf/StdLibExtras.h>
+
+#if USE(PTHREAD_BASED_QT) && !defined(WTF_USE_PTHREADS)
+#define WTF_USE_PTHREADS 1
+#endif
+
+#if OS(DARWIN)
+
+#include <mach/mach_init.h>
+#include <mach/mach_port.h>
+#include <mach/task.h>
+#include <mach/thread_act.h>
+#include <mach/vm_map.h>
+
+#elif OS(WINDOWS)
+
+#include <windows.h>
+#include <malloc.h>
+
+#elif OS(HAIKU)
+
+#include <OS.h>
+
+#elif OS(UNIX)
+
+#include <stdlib.h>
+#if !OS(HAIKU)
+#include <sys/mman.h>
+#endif
+#include <unistd.h>
+
+#if OS(SOLARIS)
+#include <thread.h>
+#else
+#include <pthread.h>
+#endif
+
+#if HAVE(PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
+#if OS(QNX)
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <stdio.h>
+#include <errno.h>
+#endif
+
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+#include <signal.h>
+#ifndef SA_RESTART
+#error MachineThreads requires SA_RESTART
+#endif
+#endif
+
+#endif
+
+using namespace WTF;
+
+namespace JSC {
+
+static inline void swapIfBackwards(void*& begin, void*& end)
+{
+#if OS(WINCE)
+    if (begin <= end)
+        return;
+    std::swap(begin, end);
+#else
+UNUSED_PARAM(begin);
+UNUSED_PARAM(end);
+#endif
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+#if OS(DARWIN)
+typedef mach_port_t PlatformThread;
+#elif OS(WINDOWS)
+typedef HANDLE PlatformThread;
+#elif USE(PTHREADS)
+typedef pthread_t PlatformThread;
+static const int SigThreadSuspendResume = SIGUSR2;
+
+static void pthreadSignalHandlerSuspendResume(int signo)
+{
+    sigset_t signalSet;
+    sigemptyset(&signalSet);
+    sigaddset(&signalSet, SigThreadSuspendResume);
+    sigsuspend(&signalSet);
+}
+#endif
+
+class MachineThreads::Thread {
+public:
+    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
+        : posixThread(pthread)
+        , platformThread(platThread)
+        , stackBase(base)
+    {
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+        struct sigaction action;
+        action.sa_handler = pthreadSignalHandlerSuspendResume;
+        sigemptyset(&action.sa_mask);
+        action.sa_flags = SA_RESTART;
+        sigaction(SigThreadSuspendResume, &action, 0);
+
+        sigset_t mask;
+        sigemptyset(&mask);
+        sigaddset(&mask, SigThreadSuspendResume);
+        pthread_sigmask(SIG_UNBLOCK, &mask, 0);
+#endif
+    }
+
+    Thread* next;
+    pthread_t posixThread;
+    PlatformThread platformThread;
+    void* stackBase;
+};
+
+#endif
+
+MachineThreads::MachineThreads(Heap* heap)
+    : m_heap(heap)
+#if ENABLE(JSC_MULTIPLE_THREADS)
+    , m_registeredThreads(0)
+    , m_threadSpecific(0)
+#endif
+{
+}
+
+MachineThreads::~MachineThreads()
+{
+#if ENABLE(JSC_MULTIPLE_THREADS)
+    if (m_threadSpecific) {
+        int error = pthread_key_delete(m_threadSpecific);
+        ASSERT_UNUSED(error, !error);
+    }
+
+    MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
+    for (Thread* t = m_registeredThreads; t;) {
+        Thread* next = t->next;
+        delete t;
+        t = next;
+    }
+#endif
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline PlatformThread getCurrentPlatformThread()
+{
+#if OS(DARWIN)
+    return pthread_mach_thread_np(pthread_self());
+#elif OS(WINDOWS)
+    return pthread_getw32threadhandle_np(pthread_self());
+#elif USE(PTHREADS)
+    return pthread_self();
+#endif
+}
+
+void MachineThreads::makeUsableFromMultipleThreads()
+{
+    if (m_threadSpecific)
+        return;
+
+    int error = pthread_key_create(&m_threadSpecific, removeThread);
+    if (error)
+        CRASH();
+}
+
+void MachineThreads::addCurrentThread()
+{
+    ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread());
+
+    if (!m_threadSpecific || pthread_getspecific(m_threadSpecific))
+        return;
+
+    pthread_setspecific(m_threadSpecific, this);
+    Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin());
+
+    MutexLocker lock(m_registeredThreadsMutex);
+
+    thread->next = m_registeredThreads;
+    m_registeredThreads = thread;
+}
+
+void MachineThreads::removeThread(void* p)
+{
+    if (p)
+        static_cast<MachineThreads*>(p)->removeCurrentThread();
+}
+
+void MachineThreads::removeCurrentThread()
+{
+    pthread_t currentPosixThread = pthread_self();
+
+    MutexLocker lock(m_registeredThreadsMutex);
+
+    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
+        Thread* t = m_registeredThreads;
+        m_registeredThreads = m_registeredThreads->next;
+        delete t;
+    } else {
+        Thread* last = m_registeredThreads;
+        Thread* t;
+        for (t = m_registeredThreads->next; t; t = t->next) {
+            if (pthread_equal(t->posixThread, currentPosixThread)) {
+                last->next = t->next;
+                break;
+            }
+            last = t;
+        }
+        ASSERT(t); // If t is NULL, we never found ourselves in the list.
+        delete t;
+    }
+}
+
+#endif
+
+#if COMPILER(GCC)
+#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
+#else
+#define REGISTER_BUFFER_ALIGNMENT
+#endif
+
+void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, void* stackCurrent)
+{
+    // setjmp forces volatile registers onto the stack
+    jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
+#if COMPILER(MSVC)
+#pragma warning(push)
+#pragma warning(disable: 4611)
+#endif
+    setjmp(registers);
+#if COMPILER(MSVC)
+#pragma warning(pop)
+#endif
+
+    void* registersBegin = &registers;
+    void* registersEnd = reinterpret_cast<void*>(roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(&registers + 1)));
+    swapIfBackwards(registersBegin, registersEnd);
+    conservativeRoots.add(registersBegin, registersEnd);
+
+    void* stackBegin = stackCurrent;
+    void* stackEnd = m_heap->globalData()->stack().origin();
+    swapIfBackwards(stackBegin, stackEnd);
+    conservativeRoots.add(stackBegin, stackEnd);
+}
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+static inline void suspendThread(const PlatformThread& platformThread)
+{
+#if OS(DARWIN)
+    thread_suspend(platformThread);
+#elif OS(WINDOWS)
+    SuspendThread(platformThread);
+#elif USE(PTHREADS)
+    pthread_kill(platformThread, SigThreadSuspendResume);
+#else
+#error Need a way to suspend threads on this platform
+#endif
+}
+
+static inline void resumeThread(const PlatformThread& platformThread)
+{
+#if OS(DARWIN)
+    thread_resume(platformThread);
+#elif OS(WINDOWS)
+    ResumeThread(platformThread);
+#elif USE(PTHREADS)
+    pthread_kill(platformThread, SigThreadSuspendResume);
+#else
+#error Need a way to resume threads on this platform
+#endif
+}
+
+typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
+
+#if OS(DARWIN)
+
+#if CPU(X86)
+typedef i386_thread_state_t PlatformThreadRegisters;
+#elif CPU(X86_64)
+typedef x86_thread_state64_t PlatformThreadRegisters;
+#elif CPU(PPC)
+typedef ppc_thread_state_t PlatformThreadRegisters;
+#elif CPU(PPC64)
+typedef ppc_thread_state64_t PlatformThreadRegisters;
+#elif CPU(ARM)
+typedef arm_thread_state_t PlatformThreadRegisters;
+#else
+#error Unknown Architecture
+#endif
+
+#elif OS(WINDOWS)
+typedef CONTEXT PlatformThreadRegisters;
+#elif USE(PTHREADS)
+typedef pthread_attr_t PlatformThreadRegisters;
+#else
+#error Need a thread register struct for this platform
+#endif
+
+static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
+{
+#if OS(DARWIN)
+
+#if CPU(X86)
+    unsigned user_count = sizeof(regs)/sizeof(int);
+    thread_state_flavor_t flavor = i386_THREAD_STATE;
+#elif CPU(X86_64)
+    unsigned user_count = x86_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = x86_THREAD_STATE64;
+#elif CPU(PPC) 
+    unsigned user_count = PPC_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = PPC_THREAD_STATE;
+#elif CPU(PPC64)
+    unsigned user_count = PPC_THREAD_STATE64_COUNT;
+    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
+#elif CPU(ARM)
+    unsigned user_count = ARM_THREAD_STATE_COUNT;
+    thread_state_flavor_t flavor = ARM_THREAD_STATE;
+#else
+#error Unknown Architecture
+#endif
+
+    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
+    if (result != KERN_SUCCESS) {
+        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
+                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
+        CRASH();
+    }
+    return user_count * sizeof(usword_t);
+// end OS(DARWIN)
+
+#elif OS(WINDOWS)
+    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+    GetThreadContext(platformThread, &regs);
+    return sizeof(CONTEXT);
+#elif USE(PTHREADS)
+    pthread_attr_init(&regs);
+#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
+    // e.g. on FreeBSD 5.4, neundorf@kde.org
+    pthread_attr_get_np(platformThread, &regs);
+#else
+    // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
+    pthread_getattr_np(platformThread, &regs);
+#endif
+    return 0;
+#else
+#error Need a way to get thread registers on this platform
+#endif
+}
+
+static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
+{
+#if OS(DARWIN)
+
+#if __DARWIN_UNIX03
+
+#if CPU(X86)
+    return reinterpret_cast<void*>(regs.__esp);
+#elif CPU(X86_64)
+    return reinterpret_cast<void*>(regs.__rsp);
+#elif CPU(PPC) || CPU(PPC64)
+    return reinterpret_cast<void*>(regs.__r1);
+#elif CPU(ARM)
+    return reinterpret_cast<void*>(regs.__sp);
+#else
+#error Unknown Architecture
+#endif
+
+#else // !__DARWIN_UNIX03
+
+#if CPU(X86)
+    return reinterpret_cast<void*>(regs.esp);
+#elif CPU(X86_64)
+    return reinterpret_cast<void*>(regs.rsp);
+#elif CPU(PPC) || CPU(PPC64)
+    return reinterpret_cast<void*>(regs.r1);
+#else
+#error Unknown Architecture
+#endif
+
+#endif // __DARWIN_UNIX03
+
+// end OS(DARWIN)
+#elif CPU(X86) && OS(WINDOWS)
+    return reinterpret_cast<void*>((uintptr_t) regs.Esp);
+#elif CPU(X86_64) && OS(WINDOWS)
+    return reinterpret_cast<void*>((uintptr_t) regs.Rsp);
+#elif USE(PTHREADS)
+    void* stackBase = 0;
+    size_t stackSize = 0;
+    int rc = pthread_attr_getstack(&regs, &stackBase, &stackSize);
+    (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
+    ASSERT(stackBase);
+    return static_cast<char*>(stackBase) + stackSize;
+#else
+#error Need a way to get the stack pointer for another thread on this platform
+#endif
+}
+
+static void freePlatformThreadRegisters(PlatformThreadRegisters& regs)
+{
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+    pthread_attr_destroy(&regs);
+#else
+    UNUSED_PARAM(regs);
+#endif
+}
+
+void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread)
+{
+    suspendThread(thread->platformThread);
+
+    PlatformThreadRegisters regs;
+    size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
+
+    conservativeRoots.add(static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
+
+    void* stackPointer = otherThreadStackPointer(regs);
+    void* stackBase = thread->stackBase;
+    swapIfBackwards(stackPointer, stackBase);
+    conservativeRoots.add(stackPointer, stackBase);
+
+    resumeThread(thread->platformThread);
+
+    freePlatformThreadRegisters(regs);
+}
+
+#endif
+
+void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent)
+{
+    gatherFromCurrentThread(conservativeRoots, stackCurrent);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+
+    if (m_threadSpecific) {
+
+        MutexLocker lock(m_registeredThreadsMutex);
+
+#ifndef NDEBUG
+        // Forbid malloc during the gather phase. The gather phase suspends
+        // threads, so a malloc during gather would risk a deadlock with a
+        // thread that had been suspended while holding the malloc lock.
+        fastMallocForbid();
+#endif
+        // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
+        // and since this is a shared heap, they are real locks.
+        for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
+            if (!pthread_equal(thread->posixThread, pthread_self()))
+                gatherFromOtherThread(conservativeRoots, thread);
+        }
+#ifndef NDEBUG
+        fastMallocAllow();
+#endif
+    }
+#endif
+}
+
+} // namespace JSC
diff --git a/heap/MachineStackMarker.h b/heap/MachineStackMarker.h
new file mode 100644 (file)
index 0000000..c814ac5
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef MachineThreads_h
+#define MachineThreads_h
+
+#include <wtf/Noncopyable.h>
+#include <wtf/ThreadingPrimitives.h>
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#include <pthread.h>
+#endif
+
+namespace JSC {
+
+    class Heap;
+    class ConservativeRoots;
+
+    class MachineThreads {
+        WTF_MAKE_NONCOPYABLE(MachineThreads);
+    public:
+        MachineThreads(Heap*);
+        ~MachineThreads();
+
+        void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        void makeUsableFromMultipleThreads();
+        void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+#endif
+
+    private:
+        void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent);
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        class Thread;
+
+        static void removeThread(void*);
+        void removeCurrentThread();
+
+        void gatherFromOtherThread(ConservativeRoots&, Thread*);
+#endif
+
+        Heap* m_heap;
+
+#if ENABLE(JSC_MULTIPLE_THREADS)
+        Mutex m_registeredThreadsMutex;
+        Thread* m_registeredThreads;
+        pthread_key_t m_threadSpecific;
+#endif
+    };
+
+} // namespace JSC
+
+#endif // MachineThreads_h
diff --git a/heap/MarkStack.cpp b/heap/MarkStack.cpp
new file mode 100644 (file)
index 0000000..d3adfdc
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009, 2011 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. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+#include "ConservativeRoots.h"
+#include "Heap.h"
+#include "JSArray.h"
+#include "JSCell.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include "Structure.h"
+
+namespace JSC {
+
+size_t MarkStack::s_pageSize = 0;
+
+void MarkStack::reset()
+{
+    ASSERT(s_pageSize);
+    m_values.shrinkAllocation(s_pageSize);
+    m_markSets.shrinkAllocation(s_pageSize);
+    m_opaqueRoots.clear();
+}
+
+void MarkStack::append(ConservativeRoots& conservativeRoots)
+{
+    JSCell** roots = conservativeRoots.roots();
+    size_t size = conservativeRoots.size();
+    for (size_t i = 0; i < size; ++i)
+        internalAppend(roots[i]);
+}
+
+inline void MarkStack::visitChildren(JSCell* cell)
+{
+    ASSERT(Heap::isMarked(cell));
+    if (cell->structure()->typeInfo().type() < CompoundType) {
+        cell->JSCell::visitChildren(*this);
+        return;
+    }
+
+    if (!cell->structure()->typeInfo().overridesVisitChildren()) {
+        ASSERT(cell->isObject());
+#ifdef NDEBUG
+        asObject(cell)->visitChildrenDirect(*this);
+#else
+        ASSERT(!m_isCheckingForDefaultMarkViolation);
+        m_isCheckingForDefaultMarkViolation = true;
+        cell->visitChildren(*this);
+        ASSERT(m_isCheckingForDefaultMarkViolation);
+        m_isCheckingForDefaultMarkViolation = false;
+#endif
+        return;
+    }
+    if (cell->vptr() == m_jsArrayVPtr) {
+        asArray(cell)->visitChildrenDirect(*this);
+        return;
+    }
+    cell->visitChildren(*this);
+}
+
+void MarkStack::drain()
+{
+#if !ASSERT_DISABLED
+    ASSERT(!m_isDraining);
+    m_isDraining = true;
+#endif
+    while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
+        while (!m_markSets.isEmpty() && m_values.size() < 50) {
+            ASSERT(!m_markSets.isEmpty());
+            MarkSet& current = m_markSets.last();
+            ASSERT(current.m_values);
+            JSValue* end = current.m_end;
+            ASSERT(current.m_values);
+            ASSERT(current.m_values != end);
+        findNextUnmarkedNullValue:
+            ASSERT(current.m_values != end);
+            JSValue value = *current.m_values;
+            current.m_values++;
+
+            JSCell* cell;
+            if (!value || !value.isCell() || Heap::testAndSetMarked(cell = value.asCell())) {
+                if (current.m_values == end) {
+                    m_markSets.removeLast();
+                    continue;
+                }
+                goto findNextUnmarkedNullValue;
+            }
+
+            if (cell->structure()->typeInfo().type() < CompoundType) {
+                cell->JSCell::visitChildren(*this);
+                if (current.m_values == end) {
+                    m_markSets.removeLast();
+                    continue;
+                }
+                goto findNextUnmarkedNullValue;
+            }
+
+            if (current.m_values == end)
+                m_markSets.removeLast();
+
+            visitChildren(cell);
+        }
+        while (!m_values.isEmpty())
+            visitChildren(m_values.removeLast());
+    }
+#if !ASSERT_DISABLED
+    m_isDraining = false;
+#endif
+}
+
+#if ENABLE(GC_VALIDATION)
+void MarkStack::validateSet(JSValue* values, size_t count)
+{
+    for (size_t i = 0; i < count; i++) {
+        if (values[i])
+            validateValue(values[i]);
+    }
+}
+
+void MarkStack::validateValue(JSValue value)
+{
+    if (!value)
+        CRASH();
+    if (!value.isCell())
+        return;
+    JSCell* cell = value.asCell();
+    if (!cell)
+        CRASH();
+
+    if (!cell->structure())
+        CRASH();
+
+    // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
+    // I hate this sentence.
+    if (cell->structure()->structure()->JSCell::classInfo() != cell->structure()->JSCell::classInfo())
+        CRASH();
+}
+#endif
+
+} // namespace JSC
diff --git a/heap/MarkStack.h b/heap/MarkStack.h
new file mode 100644 (file)
index 0000000..f269fd2
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2009, 2011 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 MarkStack_h
+#define MarkStack_h
+
+#include "HandleTypes.h"
+#include "JSValue.h"
+#include "Register.h"
+#include <wtf/HashSet.h>
+#include <wtf/Vector.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OSAllocator.h>
+
+namespace JSC {
+
+    class ConservativeRoots;
+    class JSGlobalData;
+    class Register;
+    template<typename T> class WriteBarrierBase;
+    template<typename T> class JITWriteBarrier;
+    
+    enum MarkSetProperties { MayContainNullValues, NoNullValues };
+    
+    class MarkStack {
+        WTF_MAKE_NONCOPYABLE(MarkStack);
+    public:
+        MarkStack(void* jsArrayVPtr)
+            : m_jsArrayVPtr(jsArrayVPtr)
+            , m_shouldUnlinkCalls(false)
+#if !ASSERT_DISABLED
+            , m_isCheckingForDefaultMarkViolation(false)
+            , m_isDraining(false)
+#endif
+        {
+        }
+
+        ~MarkStack()
+        {
+            ASSERT(m_markSets.isEmpty());
+            ASSERT(m_values.isEmpty());
+        }
+
+        template<typename T> inline void append(JITWriteBarrier<T>*);
+        template<typename T> inline void append(WriteBarrierBase<T>*);
+        inline void appendValues(WriteBarrierBase<Unknown>*, size_t count, MarkSetProperties = NoNullValues);
+        
+        void append(ConservativeRoots&);
+
+        bool addOpaqueRoot(void* root) { return m_opaqueRoots.add(root).second; }
+        bool containsOpaqueRoot(void* root) { return m_opaqueRoots.contains(root); }
+        int opaqueRootCount() { return m_opaqueRoots.size(); }
+
+        void drain();
+        void reset();
+
+        bool shouldUnlinkCalls() const { return m_shouldUnlinkCalls; }
+        void setShouldUnlinkCalls(bool shouldUnlinkCalls) { m_shouldUnlinkCalls = shouldUnlinkCalls; }
+
+    private:
+        friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly.
+
+#if ENABLE(GC_VALIDATION)
+        static void validateSet(JSValue*, size_t);
+        static void validateValue(JSValue);
+#endif
+
+        void append(JSValue*);
+        void append(JSValue*, size_t count);
+        void append(JSCell**);
+
+        void internalAppend(JSCell*);
+        void internalAppend(JSValue);
+        void visitChildren(JSCell*);
+
+        struct MarkSet {
+            MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties)
+                : m_values(values)
+                , m_end(end)
+                , m_properties(properties)
+            {
+                ASSERT(values);
+            }
+            JSValue* m_values;
+            JSValue* m_end;
+            MarkSetProperties m_properties;
+        };
+
+        static void* allocateStack(size_t size) { return OSAllocator::reserveAndCommit(size); }
+        static void releaseStack(void* addr, size_t size) { OSAllocator::decommitAndRelease(addr, size); }
+
+        static void initializePagesize();
+        static size_t pageSize()
+        {
+            if (!s_pageSize)
+                initializePagesize();
+            return s_pageSize;
+        }
+
+        template<typename T> struct MarkStackArray {
+            MarkStackArray()
+                : m_top(0)
+                , m_allocated(MarkStack::pageSize())
+                , m_capacity(m_allocated / sizeof(T))
+            {
+                m_data = reinterpret_cast<T*>(allocateStack(m_allocated));
+            }
+
+            ~MarkStackArray()
+            {
+                releaseStack(m_data, m_allocated);
+            }
+
+            void expand()
+            {
+                size_t oldAllocation = m_allocated;
+                m_allocated *= 2;
+                m_capacity = m_allocated / sizeof(T);
+                void* newData = allocateStack(m_allocated);
+                memcpy(newData, m_data, oldAllocation);
+                releaseStack(m_data, oldAllocation);
+                m_data = reinterpret_cast<T*>(newData);
+            }
+
+            inline void append(const T& v)
+            {
+                if (m_top == m_capacity)
+                    expand();
+                m_data[m_top++] = v;
+            }
+
+            inline T removeLast()
+            {
+                ASSERT(m_top);
+                return m_data[--m_top];
+            }
+            
+            inline T& last()
+            {
+                ASSERT(m_top);
+                return m_data[m_top - 1];
+            }
+
+            inline bool isEmpty()
+            {
+                return m_top == 0;
+            }
+
+            inline size_t size() { return m_top; }
+
+            inline void shrinkAllocation(size_t size)
+            {
+                ASSERT(size <= m_allocated);
+                ASSERT(0 == (size % MarkStack::pageSize()));
+                if (size == m_allocated)
+                    return;
+#if OS(WINDOWS) || OS(SYMBIAN) || PLATFORM(BREWMP)
+                // We cannot release a part of a region with VirtualFree.  To get around this,
+                // we'll release the entire region and reallocate the size that we want.
+                releaseStack(m_data, m_allocated);
+                m_data = reinterpret_cast<T*>(allocateStack(size));
+#else
+                releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
+#endif
+                m_allocated = size;
+                m_capacity = m_allocated / sizeof(T);
+            }
+
+        private:
+            size_t m_top;
+            size_t m_allocated;
+            size_t m_capacity;
+            T* m_data;
+        };
+
+        void* m_jsArrayVPtr;
+        MarkStackArray<MarkSet> m_markSets;
+        MarkStackArray<JSCell*> m_values;
+        static size_t s_pageSize;
+        HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
+        bool m_shouldUnlinkCalls;
+
+#if !ASSERT_DISABLED
+    public:
+        bool m_isCheckingForDefaultMarkViolation;
+        bool m_isDraining;
+#endif
+    };
+
+    typedef MarkStack SlotVisitor;
+
+    inline void MarkStack::append(JSValue* slot, size_t count)
+    {
+        if (!count)
+            return;
+#if ENABLE(GC_VALIDATION)
+        validateSet(slot, count);
+#endif
+        m_markSets.append(MarkSet(slot, slot + count, NoNullValues));
+    }
+    
+    ALWAYS_INLINE void MarkStack::append(JSValue* value)
+    {
+        ASSERT(value);
+        internalAppend(*value);
+    }
+
+    ALWAYS_INLINE void MarkStack::append(JSCell** value)
+    {
+        ASSERT(value);
+        internalAppend(*value);
+    }
+
+    ALWAYS_INLINE void MarkStack::internalAppend(JSValue value)
+    {
+        ASSERT(value);
+#if ENABLE(GC_VALIDATION)
+        validateValue(value);
+#endif
+        if (value.isCell())
+            internalAppend(value.asCell());
+    }
+
+    // Privileged class for marking JSValues directly. It is only safe to use
+    // this class to mark direct heap roots that are marked during every GC pass.
+    // All other references should be wrapped in WriteBarriers and marked through
+    // the MarkStack.
+    class HeapRootVisitor {
+    private:
+        friend class Heap;
+        HeapRootVisitor(SlotVisitor&);
+        
+    public:
+        void mark(JSValue*);
+        void mark(JSValue*, size_t);
+        void mark(JSString**);
+        void mark(JSCell**);
+        
+        SlotVisitor& visitor();
+
+    private:
+        SlotVisitor& m_visitor;
+    };
+
+    inline HeapRootVisitor::HeapRootVisitor(SlotVisitor& visitor)
+        : m_visitor(visitor)
+    {
+    }
+
+    inline void HeapRootVisitor::mark(JSValue* slot)
+    {
+        m_visitor.append(slot);
+    }
+
+    inline void HeapRootVisitor::mark(JSValue* slot, size_t count)
+    {
+        m_visitor.append(slot, count);
+    }
+
+    inline void HeapRootVisitor::mark(JSString** slot)
+    {
+        m_visitor.append(reinterpret_cast<JSCell**>(slot));
+    }
+
+    inline void HeapRootVisitor::mark(JSCell** slot)
+    {
+        m_visitor.append(slot);
+    }
+
+    inline SlotVisitor& HeapRootVisitor::visitor()
+    {
+        return m_visitor;
+    }
+
+} // namespace JSC
+
+#endif
diff --git a/heap/MarkStackPosix.cpp b/heap/MarkStackPosix.cpp
new file mode 100644 (file)
index 0000000..2a5b298
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 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. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+#if OS(UNIX) && !OS(SYMBIAN)
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    MarkStack::s_pageSize = getpagesize();
+}
+
+}
+
+#endif
diff --git a/heap/MarkStackSymbian.cpp b/heap/MarkStackSymbian.cpp
new file mode 100644 (file)
index 0000000..a3893d7
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "MarkStack.h"
+
+#if OS(SYMBIAN)
+
+#include <e32hal.h>
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    TInt page_size;
+    UserHal::PageSizeInBytes(page_size);
+    MarkStack::s_pageSize = page_size;
+}
+
+}
+
+#endif
diff --git a/heap/MarkStackWin.cpp b/heap/MarkStackWin.cpp
new file mode 100644 (file)
index 0000000..2d2a1b3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 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. 
+ */
+
+#include "config.h"
+#include "MarkStack.h"
+
+#if OS(WINDOWS)
+
+#include "windows.h"
+
+namespace JSC {
+
+void MarkStack::initializePagesize()
+{
+    SYSTEM_INFO system_info;
+    GetSystemInfo(&system_info);
+    MarkStack::s_pageSize = system_info.dwPageSize;
+}
+
+}
+
+#endif
diff --git a/heap/MarkedBlock.cpp b/heap/MarkedBlock.cpp
new file mode 100644 (file)
index 0000000..f1f630c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "MarkedBlock.h"
+
+#include "JSCell.h"
+#include "JSObject.h"
+#include "JSZombie.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+MarkedBlock* MarkedBlock::create(JSGlobalData* globalData, size_t cellSize)
+{
+    PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, blockSize, OSAllocator::JSGCHeapPages);
+    if (!static_cast<bool>(allocation))
+        CRASH();
+    return new (allocation.base()) MarkedBlock(allocation, globalData, cellSize);
+}
+
+void MarkedBlock::destroy(MarkedBlock* block)
+{
+    for (size_t i = block->firstAtom(); i < block->m_endAtom; i += block->m_atomsPerCell)
+        reinterpret_cast<JSCell*>(&block->atoms()[i])->~JSCell();
+    block->m_allocation.deallocate();
+}
+
+MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData* globalData, size_t cellSize)
+    : m_nextAtom(firstAtom())
+    , m_allocation(allocation)
+    , m_heap(&globalData->heap)
+    , m_prev(0)
+    , m_next(0)
+{
+    m_atomsPerCell = (cellSize + atomSize - 1) / atomSize;
+    m_endAtom = atomsPerBlock - m_atomsPerCell + 1;
+
+    Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get();
+    for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell)
+        new (&atoms()[i]) JSCell(*globalData, dummyMarkableCellStructure, JSCell::CreatingEarlyCell);
+}
+
+void MarkedBlock::sweep()
+{
+    Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get();
+
+    for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
+        if (m_marks.get(i))
+            continue;
+
+        JSCell* cell = reinterpret_cast<JSCell*>(&atoms()[i]);
+#if ENABLE(JSC_ZOMBIES)
+        if (cell->structure() && cell->structure() != dummyMarkableCellStructure && !cell->isZombie()) {
+            const ClassInfo* info = cell->classInfo();
+            cell->~JSCell();
+            new (cell) JSZombie(*m_heap->globalData(), info, m_heap->globalData()->zombieStructure.get());
+            m_marks.set(i);
+        }
+#else
+        cell->~JSCell();
+        new (cell) JSCell(*m_heap->globalData(), dummyMarkableCellStructure);
+#endif
+    }
+}
+
+} // namespace JSC
diff --git a/heap/MarkedBlock.h b/heap/MarkedBlock.h
new file mode 100644 (file)
index 0000000..c567502
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef MarkedBlock_h
+#define MarkedBlock_h
+
+#include <wtf/Bitmap.h>
+#include <wtf/PageAllocationAligned.h>
+#include <wtf/StdLibExtras.h>
+
+namespace JSC {
+
+    class Heap;
+    class JSCell;
+    class JSGlobalData;
+
+    typedef uintptr_t Bits;
+
+    static const size_t KB = 1024;
+
+    class MarkedBlock {
+    public:
+        static const size_t atomSize = sizeof(double); // Ensures natural alignment for all built-in types.
+
+        static MarkedBlock* create(JSGlobalData*, size_t cellSize);
+        static void destroy(MarkedBlock*);
+
+        static bool isAtomAligned(const void*);
+        static MarkedBlock* blockFor(const void*);
+        static size_t firstAtom();
+        
+        Heap* heap() const;
+
+        void setPrev(MarkedBlock*);
+        void setNext(MarkedBlock*);
+        MarkedBlock* prev() const;
+        MarkedBlock* next() const;
+        
+        void* allocate();
+        void reset();
+        void sweep();
+        
+        bool isEmpty();
+
+        void clearMarks();
+        size_t markCount();
+
+        size_t cellSize();
+
+        size_t size();
+        size_t capacity();
+
+        bool contains(const void*);
+        size_t atomNumber(const void*);
+        bool isMarked(const void*);
+        bool testAndSetMarked(const void*);
+        void setMarked(const void*);
+        
+        template <typename Functor> void forEach(Functor&);
+
+    private:
+        static const size_t blockSize = 16 * KB;
+        static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.
+
+        static const size_t atomMask = ~(atomSize - 1); // atomSize must be a power of two.
+        
+        static const size_t atomsPerBlock = blockSize / atomSize;
+
+        typedef char Atom[atomSize];
+
+        MarkedBlock(const PageAllocationAligned&, JSGlobalData*, size_t cellSize);
+        Atom* atoms();
+
+        size_t m_nextAtom;
+        size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom.
+        size_t m_atomsPerCell;
+        WTF::Bitmap<blockSize / atomSize> m_marks;
+        PageAllocationAligned m_allocation;
+        Heap* m_heap;
+        MarkedBlock* m_prev;
+        MarkedBlock* m_next;
+    };
+
+    inline size_t MarkedBlock::firstAtom()
+    {
+        return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize;
+    }
+
+    inline MarkedBlock::Atom* MarkedBlock::atoms()
+    {
+        return reinterpret_cast<Atom*>(this);
+    }
+
+    inline bool MarkedBlock::isAtomAligned(const void* p)
+    {
+        return !((intptr_t)(p) & ~atomMask);
+    }
+
+    inline MarkedBlock* MarkedBlock::blockFor(const void* p)
+    {
+        return reinterpret_cast<MarkedBlock*>(reinterpret_cast<uintptr_t>(p) & blockMask);
+    }
+
+    inline Heap* MarkedBlock::heap() const
+    {
+        return m_heap;
+    }
+
+    inline void MarkedBlock::setPrev(MarkedBlock* prev)
+    {
+        m_prev = prev;
+    }
+
+    inline void MarkedBlock::setNext(MarkedBlock* next)
+    {
+        m_next = next;
+    }
+
+    inline MarkedBlock* MarkedBlock::prev() const
+    {
+        return m_prev;
+    }
+
+    inline MarkedBlock* MarkedBlock::next() const
+    {
+        return m_next;
+    }
+
+    inline void MarkedBlock::reset()
+    {
+        m_nextAtom = firstAtom();
+    }
+
+    inline bool MarkedBlock::isEmpty()
+    {
+        return m_marks.isEmpty();
+    }
+
+    inline void MarkedBlock::clearMarks()
+    {
+        m_marks.clearAll();
+    }
+    
+    inline size_t MarkedBlock::markCount()
+    {
+        return m_marks.count();
+    }
+
+    inline size_t MarkedBlock::cellSize()
+    {
+        return m_atomsPerCell * atomSize;
+    }
+
+    inline size_t MarkedBlock::size()
+    {
+        return markCount() * cellSize();
+    }
+
+    inline size_t MarkedBlock::capacity()
+    {
+        return m_allocation.size();
+    }
+
+    inline bool MarkedBlock::contains(const void* p)
+    {
+        ASSERT(p && isAtomAligned(p) && atomNumber(p) < atomsPerBlock);
+
+        // Even though we physically contain p, we only logically contain p if p
+        // points to a live cell. (Claiming to contain a dead cell would trick the
+        // conservative garbage collector into resurrecting the cell in a zombie state.)
+        return isMarked(p);
+    }
+
+    inline size_t MarkedBlock::atomNumber(const void* p)
+    {
+        return (reinterpret_cast<uintptr_t>(p) - reinterpret_cast<uintptr_t>(this)) / atomSize;
+    }
+
+    inline bool MarkedBlock::isMarked(const void* p)
+    {
+        return m_marks.get(atomNumber(p));
+    }
+
+    inline bool MarkedBlock::testAndSetMarked(const void* p)
+    {
+        return m_marks.testAndSet(atomNumber(p));
+    }
+
+    inline void MarkedBlock::setMarked(const void* p)
+    {
+        m_marks.set(atomNumber(p));
+    }
+
+    template <typename Functor> inline void MarkedBlock::forEach(Functor& functor)
+    {
+        for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
+            if (!m_marks.get(i))
+                continue;
+            functor(reinterpret_cast<JSCell*>(&atoms()[i]));
+        }
+    }
+
+} // namespace JSC
+
+#endif // MarkedSpace_h
diff --git a/heap/MarkedSpace.cpp b/heap/MarkedSpace.cpp
new file mode 100644 (file)
index 0000000..77f6e52
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "MarkedSpace.h"
+
+#include "JSGlobalObject.h"
+#include "JSCell.h"
+#include "JSGlobalData.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+
+namespace JSC {
+
+class Structure;
+
+MarkedSpace::MarkedSpace(JSGlobalData* globalData)
+    : m_waterMark(0)
+    , m_highWaterMark(0)
+    , m_globalData(globalData)
+{
+    for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
+        sizeClassFor(cellSize).cellSize = cellSize;
+
+    for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
+        sizeClassFor(cellSize).cellSize = cellSize;
+}
+
+void MarkedSpace::destroy()
+{
+    clearMarks();
+    shrink();
+    ASSERT(!size());
+}
+
+MarkedBlock* MarkedSpace::allocateBlock(SizeClass& sizeClass)
+{
+    MarkedBlock* block = MarkedBlock::create(globalData(), sizeClass.cellSize);
+    sizeClass.blockList.append(block);
+    sizeClass.nextBlock = block;
+    m_blocks.add(block);
+
+    return block;
+}
+
+void MarkedSpace::freeBlocks(DoublyLinkedList<MarkedBlock>& blocks)
+{
+    MarkedBlock* next;
+    for (MarkedBlock* block = blocks.head(); block; block = next) {
+        next = block->next();
+
+        blocks.remove(block);
+        m_blocks.remove(block);
+        MarkedBlock::destroy(block);
+    }
+}
+
+void* MarkedSpace::allocateFromSizeClass(SizeClass& sizeClass)
+{
+    for (MarkedBlock*& block = sizeClass.nextBlock ; block; block = block->next()) {
+        if (void* result = block->allocate())
+            return result;
+
+        m_waterMark += block->capacity();
+    }
+
+    if (m_waterMark < m_highWaterMark)
+        return allocateBlock(sizeClass)->allocate();
+
+    return 0;
+}
+
+void MarkedSpace::shrink()
+{
+    // We record a temporary list of empties to avoid modifying m_blocks while iterating it.
+    DoublyLinkedList<MarkedBlock> empties;
+
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it) {
+        MarkedBlock* block = *it;
+        if (block->isEmpty()) {
+            SizeClass& sizeClass = sizeClassFor(block->cellSize());
+            sizeClass.blockList.remove(block);
+            sizeClass.nextBlock = sizeClass.blockList.head();
+            empties.append(block);
+        }
+    }
+    
+    freeBlocks(empties);
+    ASSERT(empties.isEmpty());
+}
+
+void MarkedSpace::clearMarks()
+{
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+        (*it)->clearMarks();
+}
+
+void MarkedSpace::sweep()
+{
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+        (*it)->sweep();
+}
+
+size_t MarkedSpace::objectCount() const
+{
+    size_t result = 0;
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+        result += (*it)->markCount();
+    return result;
+}
+
+size_t MarkedSpace::size() const
+{
+    size_t result = 0;
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+        result += (*it)->size();
+    return result;
+}
+
+size_t MarkedSpace::capacity() const
+{
+    size_t result = 0;
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+        result += (*it)->capacity();
+    return result;
+}
+
+void MarkedSpace::reset()
+{
+    m_waterMark = 0;
+
+    for (size_t cellSize = preciseStep; cellSize < preciseCutoff; cellSize += preciseStep)
+        sizeClassFor(cellSize).reset();
+
+    for (size_t cellSize = impreciseStep; cellSize < impreciseCutoff; cellSize += impreciseStep)
+        sizeClassFor(cellSize).reset();
+
+    BlockIterator end = m_blocks.end();
+    for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+        (*it)->reset();
+}
+
+} // namespace JSC
diff --git a/heap/MarkedSpace.h b/heap/MarkedSpace.h
new file mode 100644 (file)
index 0000000..a49e5f0
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef MarkedSpace_h
+#define MarkedSpace_h
+
+#include "MachineStackMarker.h"
+#include "MarkedBlock.h"
+#include "PageAllocationAligned.h"
+#include <wtf/Bitmap.h>
+#include <wtf/DoublyLinkedList.h>
+#include <wtf/FixedArray.h>
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+
+#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) < MarkedSpace::maxCellSize, class_fits_in_cell)
+
+namespace JSC {
+
+    class Heap;
+    class JSCell;
+    class JSGlobalData;
+    class LiveObjectIterator;
+    class MarkStack;
+    class WeakGCHandle;
+    typedef MarkStack SlotVisitor;
+
+    class MarkedSpace {
+        WTF_MAKE_NONCOPYABLE(MarkedSpace);
+    public:
+        // Currently public for use in assertions.
+        static const size_t maxCellSize = 1024;
+
+        static Heap* heap(JSCell*);
+
+        static bool isMarked(const JSCell*);
+        static bool testAndSetMarked(const JSCell*);
+        static void setMarked(const JSCell*);
+
+        MarkedSpace(JSGlobalData*);
+        void destroy();
+
+        JSGlobalData* globalData();
+
+        size_t highWaterMark();
+        void setHighWaterMark(size_t);
+
+        void* allocate(size_t);
+
+        void clearMarks();
+        void markRoots();
+        void reset();
+        void sweep();
+        void shrink();
+
+        size_t size() const;
+        size_t capacity() const;
+        size_t objectCount() const;
+
+        bool contains(const void*);
+
+        template<typename Functor> void forEach(Functor&);
+
+    private:
+        // [ 8, 16... 128 )
+        static const size_t preciseStep = MarkedBlock::atomSize;
+        static const size_t preciseCutoff = 128;
+        static const size_t preciseCount = preciseCutoff / preciseStep - 1;
+
+        // [ 128, 256... 1024 )
+        static const size_t impreciseStep = preciseCutoff;
+        static const size_t impreciseCutoff = maxCellSize;
+        static const size_t impreciseCount = impreciseCutoff / impreciseStep - 1;
+
+        typedef HashSet<MarkedBlock*>::iterator BlockIterator;
+
+        struct SizeClass {
+            SizeClass();
+            void reset();
+
+            MarkedBlock* nextBlock;
+            DoublyLinkedList<MarkedBlock> blockList;
+            size_t cellSize;
+        };
+
+        MarkedBlock* allocateBlock(SizeClass&);
+        void freeBlocks(DoublyLinkedList<MarkedBlock>&);
+
+        SizeClass& sizeClassFor(size_t);
+        void* allocateFromSizeClass(SizeClass&);
+
+        void clearMarks(MarkedBlock*);
+
+        SizeClass m_preciseSizeClasses[preciseCount];
+        SizeClass m_impreciseSizeClasses[impreciseCount];
+        HashSet<MarkedBlock*> m_blocks;
+        size_t m_waterMark;
+        size_t m_highWaterMark;
+        JSGlobalData* m_globalData;
+    };
+
+    inline Heap* MarkedSpace::heap(JSCell* cell)
+    {
+        return MarkedBlock::blockFor(cell)->heap();
+    }
+
+    inline bool MarkedSpace::isMarked(const JSCell* cell)
+    {
+        return MarkedBlock::blockFor(cell)->isMarked(cell);
+    }
+
+    inline bool MarkedSpace::testAndSetMarked(const JSCell* cell)
+    {
+        return MarkedBlock::blockFor(cell)->testAndSetMarked(cell);
+    }
+
+    inline void MarkedSpace::setMarked(const JSCell* cell)
+    {
+        MarkedBlock::blockFor(cell)->setMarked(cell);
+    }
+
+    inline bool MarkedSpace::contains(const void* x)
+    {
+        if (!MarkedBlock::isAtomAligned(x))
+            return false;
+
+        MarkedBlock* block = MarkedBlock::blockFor(x);
+        if (!block || !m_blocks.contains(block))
+            return false;
+
+        return block->contains(x);
+    }
+
+    template <typename Functor> inline void MarkedSpace::forEach(Functor& functor)
+    {
+        BlockIterator end = m_blocks.end();
+        for (BlockIterator it = m_blocks.begin(); it != end; ++it)
+            (*it)->forEach(functor);
+    }
+
+    inline JSGlobalData* MarkedSpace::globalData()
+    {
+        return m_globalData;
+    }
+
+    inline size_t MarkedSpace::highWaterMark()
+    {
+        return m_highWaterMark;
+    }
+
+    inline void MarkedSpace::setHighWaterMark(size_t highWaterMark)
+    {
+        m_highWaterMark = highWaterMark;
+    }
+
+    inline MarkedSpace::SizeClass::SizeClass()
+        : nextBlock(0)
+        , cellSize(0)
+    {
+    }
+
+    inline void MarkedSpace::SizeClass::reset()
+    {
+        nextBlock = blockList.head();
+    }
+
+} // namespace JSC
+
+#endif // MarkedSpace_h
diff --git a/heap/Strong.h b/heap/Strong.h
new file mode 100644 (file)
index 0000000..9f2aa05
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 Strong_h
+#define Strong_h
+
+#include "Assertions.h"
+#include "Handle.h"
+#include "HandleHeap.h"
+
+namespace JSC {
+
+class JSGlobalData;
+HandleSlot allocateGlobalHandle(JSGlobalData&);
+
+// A strongly referenced handle that prevents the object it points to from being garbage collected.
+template <typename T> class Strong : public Handle<T> {
+    using Handle<T>::slot;
+    using Handle<T>::setSlot;
+
+public:
+    typedef typename Handle<T>::ExternalType ExternalType;
+    
+    Strong()
+        : Handle<T>()
+    {
+    }
+    
+    Strong(JSGlobalData& globalData, ExternalType value = ExternalType())
+        : Handle<T>(allocateGlobalHandle(globalData))
+    {
+        set(value);
+    }
+
+    Strong(JSGlobalData& globalData, Handle<T> handle)
+        : Handle<T>(allocateGlobalHandle(globalData))
+    {
+        set(handle.get());
+    }
+    
+    Strong(const Strong& other)
+        : Handle<T>()
+    {
+        if (!other.slot())
+            return;
+        setSlot(HandleHeap::heapFor(other.slot())->allocate());
+        set(other.get());
+    }
+
+    template <typename U> Strong(const Strong<U>& other)
+        : Handle<T>()
+    {
+        if (!other.slot())
+            return;
+        setSlot(HandleHeap::heapFor(other.slot())->allocate());
+        set(other.get());
+    }
+    
+    enum HashTableDeletedValueTag { HashTableDeletedValue };
+    bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
+    Strong(HashTableDeletedValueTag)
+        : Handle<T>(hashTableDeletedValue())
+    {
+    }
+
+    ~Strong()
+    {
+        clear();
+    }
+
+    void swap(Strong& other)
+    {
+        Handle<T>::swap(other);
+    }
+
+    void set(JSGlobalData& globalData, ExternalType value)
+    {
+        if (!slot())
+            setSlot(allocateGlobalHandle(globalData));
+        set(value);
+    }
+
+    template <typename U> Strong& operator=(const Strong<U>& other)
+    {
+        if (!other.slot()) {
+            clear();
+            return *this;
+        }
+
+        set(*HandleHeap::heapFor(other.slot())->globalData(), other.get());
+        return *this;
+    }
+    
+    Strong& operator=(const Strong& other)
+    {
+        if (!other.slot()) {
+            clear();
+            return *this;
+        }
+
+        set(*HandleHeap::heapFor(other.slot())->globalData(), other.get());
+        return *this;
+    }
+
+    void clear()
+    {
+        if (!slot())
+            return;
+        HandleHeap::heapFor(slot())->deallocate(slot());
+        setSlot(0);
+    }
+
+private:
+    static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
+
+    void set(ExternalType externalType)
+    {
+        ASSERT(slot());
+        JSValue value = HandleTypes<T>::toJSValue(externalType);
+        HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
+        *slot() = value;
+    }
+};
+
+template<class T> inline void swap(Strong<T>& a, Strong<T>& b)
+{
+    a.swap(b);
+}
+
+} // namespace JSC
+
+namespace WTF {
+
+template<typename T> struct VectorTraits<JSC::Strong<T> > : SimpleClassVectorTraits {
+    static const bool canCompareWithMemcmp = false;
+};
+
+template<typename P> struct HashTraits<JSC::Strong<P> > : SimpleClassHashTraits<JSC::Strong<P> > { };
+
+}
+
+#endif // Strong_h
diff --git a/heap/Weak.h b/heap/Weak.h
new file mode 100644 (file)
index 0000000..a235a57
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 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. AND ITS CONTRIBUTORS ``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 ITS 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 Weak_h
+#define Weak_h
+
+#include "Assertions.h"
+#include "Handle.h"
+#include "HandleHeap.h"
+#include "JSGlobalData.h"
+
+namespace JSC {
+
+// A weakly referenced handle that becomes 0 when the value it points to is garbage collected.
+template <typename T> class Weak : public Handle<T> {
+    using Handle<T>::slot;
+    using Handle<T>::setSlot;
+
+public:
+    typedef typename Handle<T>::ExternalType ExternalType;
+
+    Weak()
+        : Handle<T>()
+    {
+    }
+
+    Weak(JSGlobalData& globalData, ExternalType value = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0)
+        : Handle<T>(globalData.allocateGlobalHandle())
+    {
+        HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
+        set(value);
+    }
+
+    enum AdoptTag { Adopt };
+    template<typename U> Weak(AdoptTag, Handle<U> handle)
+        : Handle<T>(handle.slot())
+    {
+        validateCell(get());
+    }
+    
+    Weak(const Weak& other)
+        : Handle<T>()
+    {
+        if (!other.slot())
+            return;
+        setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
+    }
+
+    template <typename U> Weak(const Weak<U>& other)
+        : Handle<T>()
+    {
+        if (!other.slot())
+            return;
+        setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
+    }
+    
+    enum HashTableDeletedValueTag { HashTableDeletedValue };
+    bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); }
+    Weak(HashTableDeletedValueTag)
+        : Handle<T>(hashTableDeletedValue())
+    {
+    }
+
+    ~Weak()
+    {
+        clear();
+    }
+
+    void swap(Weak& other)
+    {
+        Handle<T>::swap(other);
+    }
+
+    ExternalType get() const { return  HandleTypes<T>::getFromSlot(slot()); }
+    
+    void clear()
+    {
+        if (!slot())
+            return;
+        HandleHeap::heapFor(slot())->deallocate(slot());
+        setSlot(0);
+    }
+    
+    void set(JSGlobalData& globalData, ExternalType value, WeakHandleOwner* weakOwner = 0, void* context = 0)
+    {
+        if (!slot()) {
+            setSlot(globalData.allocateGlobalHandle());
+            HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context);
+        }
+        ASSERT(HandleHeap::heapFor(slot())->hasWeakOwner(slot(), weakOwner));
+        set(value);
+    }
+
+    template <typename U> Weak& operator=(const Weak<U>& other)
+    {
+        clear();
+        if (other.slot())
+            setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
+        return *this;
+    }
+
+    Weak& operator=(const Weak& other)
+    {
+        clear();
+        if (other.slot())
+            setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
+        return *this;
+    }
+    
+    HandleSlot leakHandle()
+    {
+        ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot()));
+        HandleSlot result = slot();
+        setSlot(0);
+        return result;
+    }
+
+private:
+    static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
+
+    void set(ExternalType externalType)
+    {
+        ASSERT(slot());
+        JSValue value = HandleTypes<T>::toJSValue(externalType);
+        ASSERT(!value || !value.isCell() || Heap::isMarked(value.asCell()));
+        HandleHeap::heapFor(slot())->writeBarrier(slot(), value);
+        *slot() = value;
+    }
+};
+
+template<class T> inline void swap(Weak<T>& a, Weak<T>& b)
+{
+    a.swap(b);
+}
+
+} // namespace JSC
+
+namespace WTF {
+
+template<typename T> struct VectorTraits<JSC::Weak<T> > : SimpleClassVectorTraits {
+    static const bool canCompareWithMemcmp = false;
+};
+
+template<typename P> struct HashTraits<JSC::Weak<P> > : SimpleClassHashTraits<JSC::Weak<P> > { };
+
+}
+
+#endif // Weak_h
index eb48a03d67a55ac1ee249fc251b244c2ba245e5f..04f2210755730040c7e6441dcdc1717337594a6f 100644 (file)
 #include "Interpreter.h"
 
 namespace JSC {
-    class CachedCall : public Noncopyable {
+    class CachedCall {
+        WTF_MAKE_NONCOPYABLE(CachedCall); WTF_MAKE_FAST_ALLOCATED;
     public:
-        CachedCall(CallFrame* callFrame, JSFunction* function, int argCount, JSValue* exception)
+        CachedCall(CallFrame* callFrame, JSFunction* function, int argCount)
             : m_valid(false)
             , m_interpreter(callFrame->interpreter())
-            , m_exception(exception)
-            , m_globalObjectScope(callFrame, function->scope().globalObject())
+            , m_globalObjectScope(callFrame->globalData(), function->scope()->globalObject.get())
         {
             ASSERT(!function->isHostFunction());
-            m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope().node(), exception);
-            m_valid = !*exception;
+            m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope());
+            m_valid = !callFrame->hadException();
         }
         
         JSValue call()
         { 
             ASSERT(m_valid);
-            return m_interpreter->execute(m_closure, m_exception);
+            return m_interpreter->execute(m_closure);
         }
         void setThis(JSValue v) { m_closure.setArgument(0, v); }
         void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); }
@@ -69,7 +69,6 @@ namespace JSC {
     private:
         bool m_valid;
         Interpreter* m_interpreter;
-        JSValue* m_exception;
         DynamicGlobalObjectScope m_globalObjectScope;
         CallFrameClosure m_closure;
     };
index 972487565f5aacacb25898c190e49a88fc32cedc..5819875150b0f8327a9f683e4927693eaba9392d 100644 (file)
 
 namespace JSC {
 
-JSValue CallFrame::thisValue()
-{
-    return this[codeBlock()->thisRegister()].jsValue();
-}
-
 #ifndef NDEBUG
 void CallFrame::dumpCaller()
 {
@@ -45,8 +40,14 @@ void CallFrame::dumpCaller()
     JSValue function;
     
     interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
-    printf("Callpoint => %s:%d\n", urlString.ascii(), signedLineNumber);
+    printf("Callpoint => %s:%d\n", urlString.utf8().data(), signedLineNumber);
 }
+
+RegisterFile* CallFrame::registerFile()
+{
+    return &interpreter()->registerFile();
+}
+
 #endif
 
 }
index fff6ea707a398df27b61b0f758f071505bd26479..57b24ef8e3983c39e2d1a729867bae3e1ecc5150 100644 (file)
@@ -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, 2011 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
 #define CallFrame_h
 
 #include "JSGlobalData.h"
+#include "MacroAssemblerCodeRef.h"
 #include "RegisterFile.h"
-#include "ScopeChain.h"
 
 namespace JSC  {
 
     class Arguments;
     class JSActivation;
     class Interpreter;
+    class ScopeChainNode;
 
     // Represents the current state of script execution.
     // Passed as the first argument to most functions.
     class ExecState : private Register {
     public:
-        JSFunction* callee() const { return this[RegisterFile::Callee].function(); }
+        JSObject* callee() const { return this[RegisterFile::Callee].function(); }
         CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); }
         ScopeChainNode* scopeChain() const
         {
             ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain());
             return this[RegisterFile::ScopeChain].Register::scopeChain();
         }
-        int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); }
-
-        JSValue thisValue();
 
         // Global object in which execution began.
         JSGlobalObject* dynamicGlobalObject();
 
         // Global object in which the currently executing code was defined.
         // Differs from dynamicGlobalObject() during function calls across web browser frames.
-        JSGlobalObject* lexicalGlobalObject() const
-        {
-            return scopeChain()->globalObject;
-        }
+        inline JSGlobalObject* lexicalGlobalObject() const;
 
         // Differs from lexicalGlobalObject because this will have DOM window shell rather than
         // the actual DOM window, which can't be "this" for security reasons.
-        JSObject* globalThisValue() const
-        {
-            return scopeChain()->globalThis;
-        }
+        inline JSObject* globalThisValue() const;
 
-        // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&.
-        // We should make this more uniform and either use a reference everywhere
-        // or a pointer everywhere.
-        JSGlobalData& globalData() const
-        {
-            ASSERT(scopeChain()->globalData);
-            return *scopeChain()->globalData;
-        }
+        inline JSGlobalData& globalData() const;
 
         // Convenience functions for access to global data.
         // It takes a few memory references to get from a call frame to the global data
         // pointer, so these are inefficient, and should be used sparingly in new code.
         // But they're used in many places in legacy code, so they're not going away any time soon.
 
-        void setException(JSValue exception) { globalData().exception = exception; }
         void clearException() { globalData().exception = JSValue(); }
         JSValue exception() const { return globalData().exception; }
-        JSValue* exceptionSlot() { return &globalData().exception; }
         bool hadException() const { return globalData().exception; }
 
         const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
@@ -92,14 +75,24 @@ namespace JSC  {
 #ifndef NDEBUG
         void dumpCaller();
 #endif
-        static const HashTable* arrayTable(CallFrame* callFrame) { return callFrame->globalData().arrayTable; }
+        static const HashTable* arrayConstructorTable(CallFrame* callFrame) { return callFrame->globalData().arrayConstructorTable; }
+        static const HashTable* arrayPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().arrayPrototypeTable; }
+        static const HashTable* booleanPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().booleanPrototypeTable; }
         static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; }
+        static const HashTable* dateConstructorTable(CallFrame* callFrame) { return callFrame->globalData().dateConstructorTable; }
+        static const HashTable* errorPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().errorPrototypeTable; }
+        static const HashTable* globalObjectTable(CallFrame* callFrame) { return callFrame->globalData().globalObjectTable; }
         static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; }
         static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; }
-        static const HashTable* numberTable(CallFrame* callFrame) { return callFrame->globalData().numberTable; }
+        static const HashTable* numberConstructorTable(CallFrame* callFrame) { return callFrame->globalData().numberConstructorTable; }
+        static const HashTable* numberPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().numberPrototypeTable; }
+        static const HashTable* objectConstructorTable(CallFrame* callFrame) { return callFrame->globalData().objectConstructorTable; }
+        static const HashTable* objectPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().objectPrototypeTable; }
         static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; }
         static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; }
+        static const HashTable* regExpPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().regExpPrototypeTable; }
         static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; }
+        static const HashTable* stringConstructorTable(CallFrame* callFrame) { return callFrame->globalData().stringConstructorTable; }
 
         static CallFrame* create(Register* callFrameBase) { return static_cast<CallFrame*>(callFrameBase); }
         Register* registers() { return this; }
@@ -107,7 +100,6 @@ namespace JSC  {
         CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
 
         CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); }
-        Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); }
 #if ENABLE(JIT)
         ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); }
 #endif
@@ -115,42 +107,57 @@ namespace JSC  {
         Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); }
 #endif
 
-        void setCalleeArguments(JSValue arguments) { static_cast<Register*>(this)[RegisterFile::OptionalCalleeArguments] = arguments; }
         void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; }
         void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; }
 
         ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain,
-            CallFrame* callerFrame, int returnValueRegister, int argc, JSFunction* function)
+            CallFrame* callerFrame, int argc, JSObject* callee)
         {
             ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller.
+            ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->registerFile()->end() >= this);
 
             setCodeBlock(codeBlock);
             setScopeChain(scopeChain);
             setCallerFrame(callerFrame);
-            static_cast<Register*>(this)[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
-            static_cast<Register*>(this)[RegisterFile::ReturnValueRegister] = Register::withInt(returnValueRegister);
-            setArgumentCount(argc); // original argument count (for the sake of the "arguments" object)
-            setCallee(function);
-            setCalleeArguments(JSValue());
+            setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
+            setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object)
+            setCallee(callee);
         }
 
         // Read a register from the codeframe (or constant from the CodeBlock).
         inline Register& r(int);
+        // Read a register for a non-constant 
+        inline Register& uncheckedR(int);
+
+        // Access to arguments.
+        int hostThisRegister() { return -RegisterFile::CallFrameHeaderSize - argumentCountIncludingThis(); }
+        JSValue hostThisValue() { return this[hostThisRegister()].jsValue(); }
+        size_t argumentCount() const { return argumentCountIncludingThis() - 1; }
+        size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].i(); }
+        JSValue argument(int argumentNumber)
+        {
+            int argumentIndex = -RegisterFile::CallFrameHeaderSize - this[RegisterFile::ArgumentCount].i() + argumentNumber + 1;
+            if (argumentIndex >= -RegisterFile::CallFrameHeaderSize)
+                return jsUndefined();
+            return this[argumentIndex].jsValue();
+        }
 
         static CallFrame* noCaller() { return reinterpret_cast<CallFrame*>(HostCallFrameFlag); }
-        int returnValueRegister() const { return this[RegisterFile::ReturnValueRegister].i(); }
 
         bool hasHostCallFrameFlag() const { return reinterpret_cast<intptr_t>(this) & HostCallFrameFlag; }
         CallFrame* addHostCallFrameFlag() const { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) | HostCallFrameFlag); }
         CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); }
 
-    private:
-        void setArgumentCount(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); }
-        void setCallee(JSFunction* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = callee; }
+        void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); }
+        void setCallee(JSObject* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = Register::withCallee(callee); }
         void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; }
+        void setReturnPC(void* value) { static_cast<Register*>(this)[RegisterFile::ReturnPC] = (Instruction*)value; }
 
+    private:
         static const intptr_t HostCallFrameFlag = 1;
-
+#ifndef NDEBUG
+        RegisterFile* registerFile();
+#endif
         ExecState();
         ~ExecState();
     };
index a301060d26b56d3aefaa3cad8e378a0c085013c0..b4b7efd45baa8019ff86ac2f62422716e60aa636 100644 (file)
@@ -46,10 +46,10 @@ struct CallFrameClosure {
         else
             newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams - providedParams] = value;
     }
+
     void resetCallFrame()
     {
         newCallFrame->setScopeChain(scopeChain);
-        newCallFrame->setCalleeArguments(JSValue());
         for (int i = providedParams; i < expectedParams; ++i)
             newCallFrame[i - RegisterFile::CallFrameHeaderSize - expectedParams] = jsUndefined();
     }
index 9821c510be84a8dd792d3d4a01252e7ab8a10e43..1514933f90b332b38941d7dcb955ac4c7536726d 100644 (file)
 #include "CallFrame.h"
 #include "CallFrameClosure.h"
 #include "CodeBlock.h"
-#include "Collector.h"
+#include "Heap.h"
 #include "Debugger.h"
 #include "DebuggerCallFrame.h"
+#include "ErrorInstance.h"
 #include "EvalCodeCache.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
-#include "GlobalEvalFunction.h"
 #include "JSActivation.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
@@ -59,6 +59,8 @@
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
+#include "StrictEvalActivation.h"
+#include "UStringConcatenate.h"
 #include <limits.h>
 #include <stdio.h>
 #include <wtf/Threading.h>
 using namespace std;
 
 namespace JSC {
-    
-#if ENABLE(JIT)
-    static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr pc)
-    {
-        return codeBlock->getBytecodeIndex(callFrame, ReturnAddressPtr(pc));
-    }
-#endif
-#if ENABLE(INTERPRETER)
-    static ALWAYS_INLINE unsigned bytecodeOffsetForPC(CallFrame* callFrame, CodeBlock* codeBlock, Instruction* pc)
-    {
-        UNUSED_PARAM(callFrame);
-        return pc - codeBlock->instructions().begin();
-    }
-#endif
 
 // Returns the depth of the scope chain within a given call frame.
-static int depth(CodeBlock* codeBlock, ScopeChain& sc)
+static int depth(CodeBlock* codeBlock, ScopeChainNode* sc)
 {
     if (!codeBlock->needsFullScopeChain())
         return 0;
-    return sc.localDepth();
+    return sc->localDepth();
 }
 
 #if ENABLE(INTERPRETER) 
@@ -114,18 +102,18 @@ NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, J
     CodeBlock* codeBlock = callFrame->codeBlock();
     Identifier& ident = codeBlock->identifier(property);
     do {
-        JSObject* o = *iter;
+        JSObject* o = iter->get();
         PropertySlot slot(o);
         if (o->getPropertySlot(callFrame, ident, slot)) {
             JSValue result = slot.getValue(callFrame, ident);
             exceptionValue = callFrame->globalData().exception;
             if (exceptionValue)
                 return false;
-            callFrame->r(dst) = JSValue(result);
+            callFrame->uncheckedR(dst) = JSValue(result);
             return true;
         }
     } while (++iter != end);
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
@@ -135,90 +123,100 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP
 
     int dst = vPC[1].u.operand;
     int property = vPC[2].u.operand;
-    int skip = vPC[3].u.operand + codeBlock->needsFullScopeChain();
+    int skip = vPC[3].u.operand;
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator end = scopeChain->end();
     ASSERT(iter != end);
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
     while (skip--) {
         ++iter;
         ASSERT(iter != end);
     }
     Identifier& ident = codeBlock->identifier(property);
     do {
-        JSObject* o = *iter;
+        JSObject* o = iter->get();
         PropertySlot slot(o);
         if (o->getPropertySlot(callFrame, ident, slot)) {
             JSValue result = slot.getValue(callFrame, ident);
             exceptionValue = callFrame->globalData().exception;
             if (exceptionValue)
                 return false;
-            callFrame->r(dst) = JSValue(result);
+            ASSERT(result);
+            callFrame->uncheckedR(dst) = JSValue(result);
             return true;
         }
     } while (++iter != end);
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
 NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
     int dst = vPC[1].u.operand;
-    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    JSGlobalObject* globalObject = codeBlock->globalObject();
     ASSERT(globalObject->isGlobalObject());
-    int property = vPC[3].u.operand;
-    Structure* structure = vPC[4].u.structure;
-    int offset = vPC[5].u.operand;
+    int property = vPC[2].u.operand;
+    Structure* structure = vPC[3].u.structure.get();
+    int offset = vPC[4].u.operand;
 
     if (structure == globalObject->structure()) {
-        callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
+        callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
         return true;
     }
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
     Identifier& ident = codeBlock->identifier(property);
     PropertySlot slot(globalObject);
     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
         JSValue result = slot.getValue(callFrame, ident);
         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
-            if (vPC[4].u.structure)
-                vPC[4].u.structure->deref();
-            globalObject->structure()->ref();
-            vPC[4] = globalObject->structure();
-            vPC[5] = slot.cachedOffset();
-            callFrame->r(dst) = JSValue(result);
+            vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
+            vPC[4] = slot.cachedOffset();
+            callFrame->uncheckedR(dst) = JSValue(result);
             return true;
         }
 
         exceptionValue = callFrame->globalData().exception;
         if (exceptionValue)
             return false;
-        callFrame->r(dst) = JSValue(result);
+        callFrame->uncheckedR(dst) = JSValue(result);
         return true;
     }
 
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
 NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
 {
     int dst = vPC[1].u.operand;
-    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
-    ASSERT(globalObject->isGlobalObject());
-    int property = vPC[3].u.operand;
-    Structure* structure = vPC[4].u.structure;
-    int offset = vPC[5].u.operand;
     CodeBlock* codeBlock = callFrame->codeBlock();
-    int skip = vPC[6].u.operand + codeBlock->needsFullScopeChain();
+    JSGlobalObject* globalObject = codeBlock->globalObject();
+    ASSERT(globalObject->isGlobalObject());
+    int property = vPC[2].u.operand;
+    Structure* structure = vPC[3].u.structure.get();
+    int offset = vPC[4].u.operand;
+    int skip = vPC[5].u.operand;
     
     ScopeChainNode* scopeChain = callFrame->scopeChain();
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator end = scopeChain->end();
     ASSERT(iter != end);
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
     while (skip--) {
-        JSObject* o = *iter;
+        JSObject* o = iter->get();
         if (o->hasCustomProperties()) {
             Identifier& ident = codeBlock->identifier(property);
             do {
@@ -228,22 +226,24 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
                     exceptionValue = callFrame->globalData().exception;
                     if (exceptionValue)
                         return false;
-                    callFrame->r(dst) = JSValue(result);
+                    ASSERT(result);
+                    callFrame->uncheckedR(dst) = JSValue(result);
                     return true;
                 }
                 if (iter == end)
                     break;
-                o = *iter;
+                o = iter->get();
                 ++iter;
             } while (true);
-            exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+            exceptionValue = createUndefinedVariableError(callFrame, ident);
             return false;
         }
         ++iter;
     }
     
     if (structure == globalObject->structure()) {
-        callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
+        callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
+        ASSERT(callFrame->uncheckedR(dst).jsValue());
         return true;
     }
 
@@ -252,23 +252,22 @@ NEVER_INLINE bool Interpreter::resolveGlobalDynamic(CallFrame* callFrame, Instru
     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
         JSValue result = slot.getValue(callFrame, ident);
         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
-            if (vPC[4].u.structure)
-                vPC[4].u.structure->deref();
-            globalObject->structure()->ref();
-            vPC[4] = globalObject->structure();
-            vPC[5] = slot.cachedOffset();
-            callFrame->r(dst) = JSValue(result);
+            vPC[3].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
+            vPC[4] = slot.cachedOffset();
+            ASSERT(result);
+            callFrame->uncheckedR(dst) = JSValue(result);
             return true;
         }
         
         exceptionValue = callFrame->globalData().exception;
         if (exceptionValue)
             return false;
-        callFrame->r(dst) = JSValue(result);
+        ASSERT(result);
+        callFrame->uncheckedR(dst) = JSValue(result);
         return true;
     }
     
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
@@ -276,7 +275,14 @@ NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vP
 {
     int dst = vPC[1].u.operand;
     int property = vPC[2].u.operand;
-    callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain()));
+    bool isStrictPut = vPC[3].u.operand;
+    Identifier ident = callFrame->codeBlock()->identifier(property);
+    JSValue result = JSC::resolveBase(callFrame, ident, callFrame->scopeChain(), isStrictPut);
+    if (result) {
+        callFrame->uncheckedR(dst) = result;
+        ASSERT(callFrame->uncheckedR(dst).jsValue());
+    } else
+        callFrame->globalData().exception = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
 }
 
 NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue)
@@ -297,21 +303,21 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst
     Identifier& ident = codeBlock->identifier(property);
     JSObject* base;
     do {
-        base = *iter;
+        base = iter->get();
         PropertySlot slot(base);
         if (base->getPropertySlot(callFrame, ident, slot)) {
             JSValue result = slot.getValue(callFrame, ident);
             exceptionValue = callFrame->globalData().exception;
             if (exceptionValue)
                 return false;
-            callFrame->r(propDst) = JSValue(result);
-            callFrame->r(baseDst) = JSValue(base);
+            callFrame->uncheckedR(propDst) = JSValue(result);
+            callFrame->uncheckedR(baseDst) = JSValue(base);
             return true;
         }
         ++iter;
     } while (iter != end);
 
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
@@ -355,24 +361,24 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC
 }
 
 #if ENABLE(INTERPRETER)
-static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
+static NEVER_INLINE bool isInvalidParamForIn(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
 {
     if (value.isObject())
         return false;
-    exceptionData = createInvalidParamError(callFrame, "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionData = createInvalidParamError(callFrame, "in" , value);
     return true;
 }
 
-static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, CodeBlock* codeBlock, const Instruction* vPC, JSValue value, JSValue& exceptionData)
+static NEVER_INLINE bool isInvalidParamForInstanceOf(CallFrame* callFrame, JSValue value, JSValue& exceptionData)
 {
     if (value.isObject() && asObject(value)->structure()->typeInfo().implementsHasInstance())
         return false;
-    exceptionData = createInvalidParamError(callFrame, "instanceof" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionData = createInvalidParamError(callFrame, "instanceof" , value);
     return true;
 }
 #endif
 
-NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue)
+NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset)
 {
     if (argc < 2)
         return jsUndefined();
@@ -385,28 +391,34 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r
     UString programSource = asString(program)->value(callFrame);
     if (callFrame->hadException())
         return JSValue();
-
-    LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON);
-    if (JSValue parsedObject = preparser.tryLiteralParse())
-        return parsedObject;
+    
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    if (!codeBlock->isStrictMode()) {
+        // FIXME: We can use the preparser in strict mode, we just need additional logic
+        // to prevent duplicates.
+        LiteralParser preparser(callFrame, programSource.characters(), programSource.length(), LiteralParser::NonStrictJSON);
+        if (JSValue parsedObject = preparser.tryLiteralParse())
+            return parsedObject;
+    }
 
     ScopeChainNode* scopeChain = callFrame->scopeChain();
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
+    JSValue exceptionValue;
+    EvalExecutable* eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->ownerExecutable(), codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
 
-    JSValue result = jsUndefined();
-    if (eval)
-        result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->thisValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
+    ASSERT(!eval == exceptionValue);
+    if (UNLIKELY(!eval))
+        return throwError(callFrame, exceptionValue);
 
-    return result;
+    return callFrame->globalData().interpreter->execute(eval, callFrame, callFrame->uncheckedR(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
 }
 
-Interpreter::Interpreter()
+Interpreter::Interpreter(JSGlobalData& globalData)
     : m_sampleEntryDepth(0)
     , m_reentryDepth(0)
+    , m_registerFile(globalData)
 {
 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
-    privateExecute(InitializeAndReturn, 0, 0, 0);
+    privateExecute(InitializeAndReturn, 0, 0);
 
     for (int i = 0; i < numOpcodeIDs; ++i)
         m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
@@ -433,7 +445,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
     printf("-----------------------------------------------------------------------------\n");
 
     CodeBlock* codeBlock = callFrame->codeBlock();
-    RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData()->interpreter->registerFile();
+    RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData().interpreter->registerFile();
     const Register* it;
     const Register* end;
     JSValue v;
@@ -477,10 +489,8 @@ void Interpreter::dumpRegisters(CallFrame* callFrame)
     printf("[ScopeChain]               | %10p | %p \n", it, (*it).scopeChain()); ++it;
     printf("[CallerRegisters]          | %10p | %d \n", it, (*it).i()); ++it;
     printf("[ReturnPC]                 | %10p | %p \n", it, (*it).vPC()); ++it;
-    printf("[ReturnValueRegister]      | %10p | %d \n", it, (*it).i()); ++it;
     printf("[ArgumentCount]            | %10p | %d \n", it, (*it).i()); ++it;
     printf("[Callee]                   | %10p | %p \n", it, (*it).function()); ++it;
-    printf("[OptionalCalleeArguments]  | %10p | %p \n", it, (*it).arguments()); ++it;
     printf("-----------------------------------------------------------------------------\n");
 
     int registerCount = 0;
@@ -542,135 +552,167 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
             debugger->didExecuteProgram(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->lastLine());
     }
 
-    if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
-        if (callFrame->callee())
-            profiler->didExecute(callFrame, callFrame->callee());
-        else
-            profiler->didExecute(callFrame, codeBlock->ownerExecutable()->sourceURL(), codeBlock->ownerExecutable()->lineNo());
-    }
-
     // If this call frame created an activation or an 'arguments' object, tear it off.
     if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) {
-        while (!scopeChain->object->inherits(&JSActivation::info))
+        if (!callFrame->uncheckedR(oldCodeBlock->activationRegister()).jsValue()) {
+            oldCodeBlock->createActivation(callFrame);
+            scopeChain = callFrame->scopeChain();
+        }
+        while (!scopeChain->object->inherits(&JSActivation::s_info))
             scopeChain = scopeChain->pop();
-        static_cast<JSActivation*>(scopeChain->object)->copyRegisters(callFrame->optionalCalleeArguments());
-    } else if (Arguments* arguments = callFrame->optionalCalleeArguments()) {
-        if (!arguments->isTornOff())
-            arguments->copyRegisters();
-    }
 
-    if (oldCodeBlock->needsFullScopeChain())
-        scopeChain->deref();
+        callFrame->setScopeChain(scopeChain);
+        JSActivation* activation = asActivation(scopeChain->object.get());
+        activation->copyRegisters(*scopeChain->globalData);
+        if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue()) {
+            if (!oldCodeBlock->isStrictMode())
+                asArguments(arguments)->setActivation(callFrame->globalData(), activation);
+        }
+    } else if (oldCodeBlock->usesArguments() && !oldCodeBlock->isStrictMode()) {
+        if (JSValue arguments = callFrame->uncheckedR(unmodifiedArgumentsRegister(oldCodeBlock->argumentsRegister())).jsValue())
+            asArguments(arguments)->copyRegisters(callFrame->globalData());
+    }
 
-    ExecState* callerFrame = callFrame->callerFrame();
+    CallFrame* callerFrame = callFrame->callerFrame();
     if (callerFrame->hasHostCallFrameFlag())
         return false;
 
     codeBlock = callerFrame->codeBlock();
-#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
+    
+    // Because of how the JIT records call site->bytecode offset
+    // information the JIT reports the bytecodeOffset for the returnPC
+    // to be at the beginning of the opcode that has caused the call.
+    // In the interpreter we have an actual return address, which is
+    // the beginning of next instruction to execute. To get an offset
+    // inside the call instruction that triggered the exception we
+    // have to subtract 1.
+#if ENABLE(JIT) && ENABLE(INTERPRETER)
     if (callerFrame->globalData().canUseJIT())
-#endif
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, codeBlock, callFrame->returnPC());
-#if ENABLE(INTERPRETER)
+        bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
     else
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, codeBlock, callFrame->returnVPC());
-#endif
+        bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
+#elif ENABLE(JIT)
+    bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
 #else
-    bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+    bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #endif
+
     callFrame = callerFrame;
     return true;
 }
 
-NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset, bool explicitThrow)
+static void appendSourceToError(CallFrame* callFrame, ErrorInstance* exception, unsigned bytecodeOffset)
 {
-    // Set up the exception object
+    exception->clearAppendSourceToMessage();
+
+    if (!callFrame->codeBlock()->hasExpressionInfo())
+        return;
+
+    int startOffset = 0;
+    int endOffset = 0;
+    int divotPoint = 0;
+
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    codeBlock->expressionRangeForBytecodeOffset(bytecodeOffset, divotPoint, startOffset, endOffset);
+
+    int expressionStart = divotPoint - startOffset;
+    int expressionStop = divotPoint + endOffset;
+
+    if (!expressionStop || expressionStart > codeBlock->source()->length())
+        return;
+
+    JSGlobalData* globalData = &callFrame->globalData();
+    JSValue jsMessage = exception->getDirect(*globalData, globalData->propertyNames->message);
+    if (!jsMessage || !jsMessage.isString())
+        return;
+
+    UString message = asString(jsMessage)->value(callFrame);
+
+    if (expressionStart < expressionStop)
+        message =  makeUString(message, " (evaluating '", codeBlock->source()->getRange(expressionStart, expressionStop), "')");
+    else {
+        // No range information, so give a few characters of context
+        const UChar* data = codeBlock->source()->data();
+        int dataLength = codeBlock->source()->length();
+        int start = expressionStart;
+        int stop = expressionStart;
+        // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
+        // then strip whitespace.
+        while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
+            start--;
+        while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
+            start++;
+        while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
+            stop++;
+        while (stop > expressionStart && isStrWhiteSpace(data[stop - 1]))
+            stop--;
+        message = makeUString(message, " (near '...", codeBlock->source()->getRange(start, stop), "...')");
+    }
+
+    exception->putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
+}
 
+NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
+{
     CodeBlock* codeBlock = callFrame->codeBlock();
+    bool isInterrupt = false;
+
+    // Set up the exception object
     if (exceptionValue.isObject()) {
         JSObject* exception = asObject(exceptionValue);
-        if (exception->isNotAnObjectErrorStub()) {
-            exception = createNotAnObjectError(callFrame, static_cast<JSNotAnObjectErrorStub*>(exception), bytecodeOffset, codeBlock);
-            exceptionValue = exception;
-        } else {
-            if (!exception->hasProperty(callFrame, Identifier(callFrame, "line")) && 
-                !exception->hasProperty(callFrame, Identifier(callFrame, "sourceId")) && 
-                !exception->hasProperty(callFrame, Identifier(callFrame, "sourceURL")) && 
-                !exception->hasProperty(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName)) && 
-                !exception->hasProperty(callFrame, Identifier(callFrame, expressionCaretOffsetPropertyName)) && 
-                !exception->hasProperty(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName))) {
-                if (explicitThrow) {
-                    int startOffset = 0;
-                    int endOffset = 0;
-                    int divotPoint = 0;
-                    int line = codeBlock->expressionRangeForBytecodeOffset(callFrame, bytecodeOffset, divotPoint, startOffset, endOffset);
-                    exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, line), ReadOnly | DontDelete);
-                    
-                    // We only hit this path for error messages and throw statements, which don't have a specific failure position
-                    // So we just give the full range of the error/throw statement.
-                    exception->putWithAttributes(callFrame, Identifier(callFrame, expressionBeginOffsetPropertyName), jsNumber(callFrame, divotPoint - startOffset), ReadOnly | DontDelete);
-                    exception->putWithAttributes(callFrame, Identifier(callFrame, expressionEndOffsetPropertyName), jsNumber(callFrame, divotPoint + endOffset), ReadOnly | DontDelete);
-                } else
-                    exception->putWithAttributes(callFrame, Identifier(callFrame, "line"), jsNumber(callFrame, codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)), ReadOnly | DontDelete);
-                exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete);
-                exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete);
-            }
 
-            ComplType exceptionType = exception->exceptionType();
-            if (exceptionType == Interrupted || exceptionType == Terminated) {
-                while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
-                    // Don't need handler checks or anything, we just want to unroll all the JS callframes possible.
-                }
-                return 0;
-            }
+        if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage())
+            appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset);
+
+        // Using hasExpressionInfo to imply we are interested in rich exception info.
+        if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) {
+            ASSERT(codeBlock->hasLineInfo());
+
+            // FIXME: should only really be adding these properties to VM generated exceptions,
+            // but the inspector currently requires these for all thrown objects.
+            addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
         }
+
+        ComplType exceptionType = exception->exceptionType();
+        isInterrupt = exceptionType == Interrupted || exceptionType == Terminated;
     }
 
     if (Debugger* debugger = callFrame->dynamicGlobalObject()->debugger()) {
         DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue);
         bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset);
-        debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), hasHandler);
-    }
-
-    // If we throw in the middle of a call instruction, we need to notify
-    // the profiler manually that the call instruction has returned, since
-    // we'll never reach the relevant op_profile_did_call.
-    if (Profiler* profiler = *Profiler::enabledProfilerReference()) {
-#if ENABLE(INTERPRETER)
-        if (!callFrame->globalData().canUseJIT()) {
-            // FIXME: Why 8? - work out what this magic value is, replace the constant with something more helpful.
-            if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode))
-                profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 1].u.operand).jsValue());
-            else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct))
-                profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 9].u.operand).jsValue());
-        }
-#if ENABLE(JIT)
-        else
-#endif
-#endif
-#if ENABLE(JIT)
-        {
-            int functionRegisterIndex;
-            if (codeBlock->functionRegisterForBytecodeOffset(bytecodeOffset, functionRegisterIndex))
-                profiler->didExecute(callFrame, callFrame->r(functionRegisterIndex).jsValue());
-        }
-#endif
+        debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), hasHandler);
     }
 
     // Calculate an exception handler vPC, unwinding call frames as necessary.
-
     HandlerInfo* handler = 0;
-    while (!(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
-        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock))
+    while (isInterrupt || !(handler = codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
+        if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
+            if (Profiler* profiler = *Profiler::enabledProfilerReference())
+                profiler->exceptionUnwind(callFrame);
             return 0;
+        }
     }
 
-    // Now unwind the scope chain within the exception handler's call frame.
+    if (Profiler* profiler = *Profiler::enabledProfilerReference())
+        profiler->exceptionUnwind(callFrame);
 
+    // Shrink the JS stack, in case stack overflow made it huge.
+    Register* highWaterMark = 0;
+    for (CallFrame* callerFrame = callFrame; callerFrame; callerFrame = callerFrame->callerFrame()->removeHostCallFrameFlag()) {
+        CodeBlock* codeBlock = callerFrame->codeBlock();
+        if (!codeBlock)
+            continue;
+        Register* callerHighWaterMark = callerFrame->registers() + codeBlock->m_numCalleeRegisters;
+        highWaterMark = max(highWaterMark, callerHighWaterMark);
+    }
+    m_registerFile.shrink(highWaterMark);
+
+    // Unwind the scope chain within the exception handler's call frame.
     ScopeChainNode* scopeChain = callFrame->scopeChain();
-    ScopeChain sc(scopeChain);
-    int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth;
+    int scopeDelta = 0;
+    if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode 
+        || callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
+        scopeDelta = depth(codeBlock, scopeChain) - handler->scopeDepth;
     ASSERT(scopeDelta >= 0);
     while (scopeDelta--)
         scopeChain = scopeChain->pop();
@@ -679,42 +721,139 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
     return handler;
 }
 
-JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
+static inline JSValue checkedReturn(JSValue returnValue)
+{
+    ASSERT(returnValue);
+    return returnValue;
+}
+
+static inline JSObject* checkedReturn(JSObject* returnValue)
+{
+    ASSERT(returnValue);
+    return returnValue;
+}
+
+JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
 {
     ASSERT(!scopeChain->globalData->exception);
+    ASSERT(!callFrame->globalData().isCollectorBusy());
+    if (callFrame->globalData().isCollectorBusy())
+        return jsNull();
 
-    if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
-        if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
-            *exception = createStackOverflowError(callFrame);
-            return jsNull();
+    if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+        return checkedReturn(throwStackOverflowError(callFrame));
+
+    DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
+    LiteralParser literalParser(callFrame, program->source().data(), program->source().length(), LiteralParser::JSONP);
+    Vector<LiteralParser::JSONPData> JSONPData;
+    if (literalParser.tryJSONPParse(JSONPData, scopeChain->globalObject->supportsRichSourceInfo())) {
+        JSGlobalObject* globalObject = scopeChain->globalObject.get();
+        JSValue result;
+        for (unsigned entry = 0; entry < JSONPData.size(); entry++) {
+            Vector<LiteralParser::JSONPPathEntry> JSONPPath;
+            JSONPPath.swap(JSONPData[entry].m_path);
+            JSValue JSONPValue = JSONPData[entry].m_value.get();
+            if (JSONPPath.size() == 1 && JSONPPath[0].m_type == LiteralParser::JSONPPathEntryTypeDeclare) {
+                if (globalObject->hasProperty(callFrame, JSONPPath[0].m_pathEntryName)) {
+                    PutPropertySlot slot;
+                    globalObject->put(callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, slot);
+                } else
+                    globalObject->putWithAttributes(callFrame, JSONPPath[0].m_pathEntryName, JSONPValue, DontEnum | DontDelete);
+                // var declarations return undefined
+                result = jsUndefined();
+                continue;
+            }
+            JSValue baseObject(globalObject);
+            for (unsigned i = 0; i < JSONPPath.size() - 1; i++) {
+                ASSERT(JSONPPath[i].m_type != LiteralParser::JSONPPathEntryTypeDeclare);
+                switch (JSONPPath[i].m_type) {
+                case LiteralParser::JSONPPathEntryTypeDot: {
+                    if (i == 0) {
+                        PropertySlot slot(globalObject);
+                        if (!globalObject->getPropertySlot(callFrame, JSONPPath[i].m_pathEntryName, slot)) {
+                            if (entry)
+                                return throwError(callFrame, createUndefinedVariableError(globalObject->globalExec(), JSONPPath[i].m_pathEntryName));
+                            goto failedJSONP;
+                        }
+                        baseObject = slot.getValue(callFrame, JSONPPath[i].m_pathEntryName);
+                    } else
+                        baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathEntryName);
+                    if (callFrame->hadException())
+                        return jsUndefined();
+                    continue;
+                }
+                case LiteralParser::JSONPPathEntryTypeLookup: {
+                    baseObject = baseObject.get(callFrame, JSONPPath[i].m_pathIndex);
+                    if (callFrame->hadException())
+                        return jsUndefined();
+                    continue;
+                }
+                default:
+                    ASSERT_NOT_REACHED();
+                    return jsUndefined();
+                }
+            }
+            PutPropertySlot slot;
+            switch (JSONPPath.last().m_type) {
+            case LiteralParser::JSONPPathEntryTypeCall: {
+                JSValue function = baseObject.get(callFrame, JSONPPath.last().m_pathEntryName);
+                if (callFrame->hadException())
+                    return jsUndefined();
+                CallData callData;
+                CallType callType = getCallData(function, callData);
+                if (callType == CallTypeNone)
+                    return throwError(callFrame, createNotAFunctionError(callFrame, function));
+                MarkedArgumentBuffer jsonArg;
+                jsonArg.append(JSONPValue);
+                JSValue thisValue = JSONPPath.size() == 1 ? jsUndefined(): baseObject;
+                JSONPValue = JSC::call(callFrame, function, callType, callData, thisValue, jsonArg);
+                if (callFrame->hadException())
+                    return jsUndefined();
+                break;
+            }
+            case LiteralParser::JSONPPathEntryTypeDot: {
+                baseObject.put(callFrame, JSONPPath.last().m_pathEntryName, JSONPValue, slot);
+                if (callFrame->hadException())
+                    return jsUndefined();
+                break;
+            }
+            case LiteralParser::JSONPPathEntryTypeLookup: {
+                baseObject.put(callFrame, JSONPPath.last().m_pathIndex, JSONPValue);
+                if (callFrame->hadException())
+                    return jsUndefined();
+                break;
+            }
+            default:
+                ASSERT_NOT_REACHED();
+                    return jsUndefined();
+            }
+            result = JSONPValue;
         }
+        return result;
     }
-
-    CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain);
+failedJSONP:
+    JSObject* error = program->compile(callFrame, scopeChain);
+    if (error)
+        return checkedReturn(throwError(callFrame, error));
+    CodeBlock* codeBlock = &program->generatedBytecode();
 
     Register* oldEnd = m_registerFile.end();
     Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
-    if (!m_registerFile.grow(newEnd)) {
-        *exception = createStackOverflowError(callFrame);
-        return jsNull();
-    }
-
-    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
+    if (!m_registerFile.grow(newEnd))
+        return checkedReturn(throwStackOverflowError(callFrame));
 
     JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
     JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
     globalObject->copyGlobalsTo(m_registerFile);
 
     CallFrame* newCallFrame = CallFrame::create(oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize);
-    newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
-    newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), 0, 0, 0);
-
-    if (codeBlock->needsFullScopeChain())
-        scopeChain->ref();
+    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
+    newCallFrame->init(codeBlock, 0, scopeChain, CallFrame::noCaller(), codeBlock->m_numParameters, 0);
+    newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo());
+        (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo());
 
     JSValue result;
     {
@@ -722,17 +861,11 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
 
         m_reentryDepth++;  
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
         if (callFrame->globalData().canUseJIT())
-#endif
-            result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
-#if ENABLE(INTERPRETER)
+            result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
         else
 #endif
-#endif
-#if ENABLE(INTERPRETER)
-            result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
-#endif
+            result = privateExecute(Normal, &m_registerFile, newCallFrame);
 
         m_reentryDepth--;
     }
@@ -745,46 +878,84 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
 
     m_registerFile.shrink(oldEnd);
 
-    return result;
+    return checkedReturn(result);
 }
 
-JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* callFrame, JSFunction* function, JSObject* thisObj, const ArgList& args, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
-    ASSERT(!scopeChain->globalData->exception);
+    ASSERT(!callFrame->hadException());
+    ASSERT(!callFrame->globalData().isCollectorBusy());
+    if (callFrame->globalData().isCollectorBusy())
+        return jsNull();
 
-    if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
-        if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
-            *exception = createStackOverflowError(callFrame);
-            return jsNull();
-        }
-    }
+    if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+        return checkedReturn(throwStackOverflowError(callFrame));
 
     Register* oldEnd = m_registerFile.end();
-    int argc = 1 + args.size(); // implicit "this" parameter
+    int argCount = 1 + args.size(); // implicit "this" parameter
+    size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
 
-    if (!m_registerFile.grow(oldEnd + argc)) {
-        *exception = createStackOverflowError(callFrame);
-        return jsNull();
-    }
-
-    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
+    if (!m_registerFile.grow(oldEnd + registerOffset))
+        return checkedReturn(throwStackOverflowError(callFrame));
 
     CallFrame* newCallFrame = CallFrame::create(oldEnd);
     size_t dst = 0;
-    newCallFrame->r(0) = JSValue(thisObj);
+    newCallFrame->uncheckedR(0) = thisValue;
     ArgList::const_iterator end = args.end();
     for (ArgList::const_iterator it = args.begin(); it != end; ++it)
-        newCallFrame->r(++dst) = *it;
+        newCallFrame->uncheckedR(++dst) = *it;
+
+    if (callType == CallTypeJS) {
+        ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
+
+        DynamicGlobalObjectScope globalObjectScope(*callDataScopeChain->globalData, callDataScopeChain->globalObject.get());
+
+        JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
+        if (UNLIKELY(!!compileError)) {
+            m_registerFile.shrink(oldEnd);
+            return checkedReturn(throwError(callFrame, compileError));
+        }
+
+        CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
+        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+        if (UNLIKELY(!newCallFrame)) {
+            m_registerFile.shrink(oldEnd);
+            return checkedReturn(throwStackOverflowError(callFrame));
+        }
+
+        newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
+
+        Profiler** profiler = Profiler::enabledProfilerReference();
+        if (*profiler)
+            (*profiler)->willExecute(callFrame, function);
+
+        JSValue result;
+        {
+            SamplingTool::CallRecord callRecord(m_sampler.get());
+
+            m_reentryDepth++;  
+#if ENABLE(JIT)
+            if (callFrame->globalData().canUseJIT())
+                result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
+            else
+#endif
+                result = privateExecute(Normal, &m_registerFile, newCallFrame);
+            m_reentryDepth--;
+        }
+
+        if (*profiler)
+            (*profiler)->didExecute(callFrame, function);
 
-    CodeBlock* codeBlock = &functionExecutable->bytecode(callFrame, scopeChain);
-    newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
-    if (UNLIKELY(!newCallFrame)) {
-        *exception = createStackOverflowError(callFrame);
         m_registerFile.shrink(oldEnd);
-        return jsNull();
+        return checkedReturn(result);
     }
-    // a 0 codeBlock indicates a built-in caller
-    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
+
+    ASSERT(callType == CallTypeHost);
+    ScopeChainNode* scopeChain = callFrame->scopeChain();
+    newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
+    newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
+
+    DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -792,38 +963,124 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame*
 
     JSValue result;
     {
-        SamplingTool::CallRecord callRecord(m_sampler.get());
+        SamplingTool::HostCallRecord callRecord(m_sampler.get());
+        result = JSValue::decode(callData.native.function(newCallFrame));
+    }
 
-        m_reentryDepth++;
+    if (*profiler)
+        (*profiler)->didExecute(callFrame, function);
+
+    m_registerFile.shrink(oldEnd);
+    return checkedReturn(result);
+}
+
+JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
+{
+    ASSERT(!callFrame->hadException());
+    ASSERT(!callFrame->globalData().isCollectorBusy());
+    // We throw in this case because we have to return something "valid" but we're
+    // already in an invalid state.
+    if (callFrame->globalData().isCollectorBusy())
+        return checkedReturn(throwStackOverflowError(callFrame));
+
+    if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+        return checkedReturn(throwStackOverflowError(callFrame));
+
+    Register* oldEnd = m_registerFile.end();
+    int argCount = 1 + args.size(); // implicit "this" parameter
+    size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
+
+    if (!m_registerFile.grow(oldEnd + registerOffset))
+        return checkedReturn(throwStackOverflowError(callFrame));
+
+    CallFrame* newCallFrame = CallFrame::create(oldEnd);
+    size_t dst = 0;
+    ArgList::const_iterator end = args.end();
+    for (ArgList::const_iterator it = args.begin(); it != end; ++it)
+        newCallFrame->uncheckedR(++dst) = *it;
+
+    if (constructType == ConstructTypeJS) {
+        ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
+
+        DynamicGlobalObjectScope globalObjectScope(*constructDataScopeChain->globalData, constructDataScopeChain->globalObject.get());
+
+        JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain);
+        if (UNLIKELY(!!compileError)) {
+            m_registerFile.shrink(oldEnd);
+            return checkedReturn(throwError(callFrame, compileError));
+        }
+
+        CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
+        newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
+        if (UNLIKELY(!newCallFrame)) {
+            m_registerFile.shrink(oldEnd);
+            return checkedReturn(throwStackOverflowError(callFrame));
+        }
+
+        newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
+
+        Profiler** profiler = Profiler::enabledProfilerReference();
+        if (*profiler)
+            (*profiler)->willExecute(callFrame, constructor);
+
+        JSValue result;
+        {
+            SamplingTool::CallRecord callRecord(m_sampler.get());
+
+            m_reentryDepth++;  
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
-        if (scopeChain->globalData->canUseJIT())
-#endif
-            result = functionExecutable->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
-#if ENABLE(INTERPRETER)
-        else
-#endif
-#endif
-#if ENABLE(INTERPRETER)
-        result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+            if (callFrame->globalData().canUseJIT())
+                result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
+            else
 #endif
-        m_reentryDepth--;
+                result = privateExecute(Normal, &m_registerFile, newCallFrame);
+            m_reentryDepth--;
+        }
+
+        if (*profiler)
+            (*profiler)->didExecute(callFrame, constructor);
+
+        m_registerFile.shrink(oldEnd);
+        if (callFrame->hadException())
+            return 0;
+        ASSERT(result.isObject());
+        return checkedReturn(asObject(result));
     }
 
+    ASSERT(constructType == ConstructTypeHost);
+    ScopeChainNode* scopeChain = callFrame->scopeChain();
+    newCallFrame = CallFrame::create(newCallFrame->registers() + registerOffset);
+    newCallFrame->init(0, 0, scopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
+
+    DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
+
+    Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->didExecute(callFrame, function);
+        (*profiler)->willExecute(callFrame, constructor);
+
+    JSValue result;
+    {
+        SamplingTool::HostCallRecord callRecord(m_sampler.get());
+        result = JSValue::decode(constructData.native.function(newCallFrame));
+    }
+
+    if (*profiler)
+        (*profiler)->didExecute(callFrame, constructor);
 
     m_registerFile.shrink(oldEnd);
-    return result;
+    if (callFrame->hadException())
+        return 0;
+    ASSERT(result.isObject());
+    return checkedReturn(asObject(result));
 }
 
-CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
+CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain)
 {
     ASSERT(!scopeChain->globalData->exception);
     
     if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
         if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
-            *exception = createStackOverflowError(callFrame);
+            throwStackOverflowError(callFrame);
             return CallFrameClosure();
         }
     }
@@ -832,36 +1089,40 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
     int argc = 1 + argCount; // implicit "this" parameter
     
     if (!m_registerFile.grow(oldEnd + argc)) {
-        *exception = createStackOverflowError(callFrame);
+        throwStackOverflowError(callFrame);
         return CallFrameClosure();
     }
 
     CallFrame* newCallFrame = CallFrame::create(oldEnd);
+    // We initialise |this| unnecessarily here for the sake of code clarity
     size_t dst = 0;
     for (int i = 0; i < argc; ++i)
-        newCallFrame->r(++dst) = jsUndefined();
+        newCallFrame->uncheckedR(dst++) = jsUndefined();
     
-    CodeBlock* codeBlock = &FunctionExecutable->bytecode(callFrame, scopeChain);
+    JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain);
+    if (error) {
+        throwError(callFrame, error);
+        m_registerFile.shrink(oldEnd);
+        return CallFrameClosure();
+    }
+    CodeBlock* codeBlock = &FunctionExecutable->generatedBytecodeForCall();
+
     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     if (UNLIKELY(!newCallFrame)) {
-        *exception = createStackOverflowError(callFrame);
+        throwStackOverflowError(callFrame);
         m_registerFile.shrink(oldEnd);
         return CallFrameClosure();
     }
-    // a 0 codeBlock indicates a built-in caller
-    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);  
-#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
-    if (callFrame->globalData().canUseJIT())
-#endif
-        FunctionExecutable->jitCode(newCallFrame, scopeChain);
-#endif
+    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);  
     CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
     return result;
 }
 
-JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception
+JSValue Interpreter::execute(CallFrameClosure& closure) 
 {
+    ASSERT(!closure.oldCallFrame->globalData().isCollectorBusy());
+    if (closure.oldCallFrame->globalData().isCollectorBusy())
+        return jsNull();
     closure.resetCallFrame();
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -876,20 +1137,20 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
 #if ENABLE(INTERPRETER)
         if (closure.newCallFrame->globalData().canUseJIT())
 #endif
-            result = closure.functionExecutable->generatedJITCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+            result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
 #if ENABLE(INTERPRETER)
         else
 #endif
 #endif
 #if ENABLE(INTERPRETER)
-            result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
+            result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
 #endif
         m_reentryDepth--;
     }
     
     if (*profiler)
         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
-    return result;
+    return checkedReturn(result);
 }
 
 void Interpreter::endRepeatCall(CallFrameClosure& closure)
@@ -897,40 +1158,51 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure)
     m_registerFile.shrink(closure.oldEnd);
 }
 
-JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain)
 {
-    return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
+    JSObject* compileError = eval->compile(callFrame, scopeChain);
+    if (UNLIKELY(!!compileError))
+        return checkedReturn(throwError(callFrame, compileError));
+    return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain);
 }
 
-JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain)
 {
     ASSERT(!scopeChain->globalData->exception);
+    ASSERT(!callFrame->globalData().isCollectorBusy());
+    if (callFrame->globalData().isCollectorBusy())
+        return jsNull();
 
-    if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
-        if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
-            *exception = createStackOverflowError(callFrame);
-            return jsNull();
-        }
-    }
+    DynamicGlobalObjectScope globalObjectScope(*scopeChain->globalData, scopeChain->globalObject.get());
 
-    DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
+    if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+        return checkedReturn(throwStackOverflowError(callFrame));
 
-    EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain);
+    JSObject* compileError = eval->compile(callFrame, scopeChain);
+    if (UNLIKELY(!!compileError))
+        return checkedReturn(throwError(callFrame, compileError));
+    EvalCodeBlock* codeBlock = &eval->generatedBytecode();
 
-    JSVariableObject* variableObject;
-    for (ScopeChainNode* node = scopeChain; ; node = node->next) {
+    JSObject* variableObject;
+    for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
         ASSERT(node);
         if (node->object->isVariableObject()) {
-            variableObject = static_cast<JSVariableObject*>(node->object);
+            variableObject = static_cast<JSVariableObject*>(node->object.get());
             break;
         }
     }
 
     unsigned numVariables = codeBlock->numVariables();
     int numFunctions = codeBlock->numberOfFunctionDecls();
+    bool pushedScope = false;
     if (numVariables || numFunctions) {
+        if (codeBlock->isStrictMode()) {
+            variableObject = new (callFrame) StrictEvalActivation(callFrame);
+            scopeChain = scopeChain->push(variableObject);
+            pushedScope = true;
+        }
         // Scope for BatchedTransitionOptimizer
-        BatchedTransitionOptimizer optimizer(variableObject);
+        BatchedTransitionOptimizer optimizer(callFrame->globalData(), variableObject);
 
         for (unsigned i = 0; i < numVariables; ++i) {
             const Identifier& ident = codeBlock->variable(i);
@@ -950,22 +1222,20 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
     Register* oldEnd = m_registerFile.end();
     Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
     if (!m_registerFile.grow(newEnd)) {
-        *exception = createStackOverflowError(callFrame);
-        return jsNull();
+        if (pushedScope)
+            scopeChain->pop();
+        return checkedReturn(throwStackOverflowError(callFrame));
     }
 
     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
 
-    // a 0 codeBlock indicates a built-in caller
-    newCallFrame->r(codeBlock->thisRegister()) = JSValue(thisObj);
-    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, 0, 0);
-
-    if (codeBlock->needsFullScopeChain())
-        scopeChain->ref();
+    ASSERT(codeBlock->m_numParameters == 1); // 1 parameter for 'this'.
+    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), codeBlock->m_numParameters, 0);
+    newCallFrame->uncheckedR(newCallFrame->hostThisRegister()) = JSValue(thisObj);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo());
+        (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
 
     JSValue result;
     {
@@ -977,13 +1247,13 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
 #if ENABLE(INTERPRETER)
         if (callFrame->globalData().canUseJIT())
 #endif
-            result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+            result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
 #if ENABLE(INTERPRETER)
         else
 #endif
 #endif
 #if ENABLE(INTERPRETER)
-            result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+            result = privateExecute(Normal, &m_registerFile, newCallFrame);
 #endif
         m_reentryDepth--;
     }
@@ -992,7 +1262,9 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
         (*profiler)->didExecute(callFrame, eval->sourceURL(), eval->lineNo());
 
     m_registerFile.shrink(oldEnd);
-    return result;
+    if (pushedScope)
+        scopeChain->pop();
+    return checkedReturn(result);
 }
 
 NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
@@ -1031,7 +1303,7 @@ NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFr
     Identifier& property = codeBlock->identifier(vPC[2].u.operand);
     JSValue value = callFrame->r(vPC[3].u.operand).jsValue();
     JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete);
-    callFrame->r(dst) = JSValue(scope);
+    callFrame->uncheckedR(dst) = JSValue(scope);
 
     return callFrame->scopeChain()->push(scope);
 }
@@ -1051,20 +1323,20 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock*
         return;
     }
     
-    JSCell* baseCell = asCell(baseValue);
+    JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
 
-    if (structure->isUncacheableDictionary()) {
+    if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
         vPC[0] = getOpcode(op_put_by_id_generic);
         return;
     }
 
     // Cache miss: record Structure to compare against next time.
-    Structure* lastStructure = vPC[4].u.structure;
+    Structure* lastStructure = vPC[4].u.structure.get();
     if (structure != lastStructure) {
         // First miss: record Structure to compare against next time.
         if (!lastStructure) {
-            vPC[4] = structure;
+            vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
             return;
         }
 
@@ -1090,24 +1362,27 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock*
 
         // put_by_id_transition checks the prototype chain for setters.
         normalizePrototypeChain(callFrame, baseCell);
-
+        JSCell* owner = codeBlock->ownerExecutable();
+        JSGlobalData& globalData = callFrame->globalData();
+        // Get the prototype here because the call to prototypeChain could cause a 
+        // GC allocation, which we don't want to happen while we're in the middle of 
+        // initializing the union.
+        StructureChain* prototypeChain = structure->prototypeChain(callFrame);
         vPC[0] = getOpcode(op_put_by_id_transition);
-        vPC[4] = structure->previousID();
-        vPC[5] = structure;
-        vPC[6] = structure->prototypeChain(callFrame);
+        vPC[4].u.structure.set(globalData, owner, structure->previousID());
+        vPC[5].u.structure.set(globalData, owner, structure);
+        vPC[6].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain);
+        ASSERT(vPC[6].u.structureChain);
         vPC[7] = slot.cachedOffset();
-        codeBlock->refStructures(vPC);
         return;
     }
 
     vPC[0] = getOpcode(op_put_by_id_replace);
     vPC[5] = slot.cachedOffset();
-    codeBlock->refStructures(vPC);
 }
 
-NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock* codeBlock, Instruction* vPC)
+NEVER_INLINE void Interpreter::uncachePutByID(CodeBlock*, Instruction* vPC)
 {
-    codeBlock->derefStructures(vPC);
     vPC[0] = getOpcode(op_put_by_id);
     vPC[4] = 0;
 }
@@ -1141,19 +1416,19 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         return;
     }
 
-    Structure* structure = asCell(baseValue)->structure();
+    Structure* structure = baseValue.asCell()->structure();
 
-    if (structure->isUncacheableDictionary()) {
+    if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
         vPC[0] = getOpcode(op_get_by_id_generic);
         return;
     }
 
     // Cache miss
-    Structure* lastStructure = vPC[4].u.structure;
+    Structure* lastStructure = vPC[4].u.structure.get();
     if (structure != lastStructure) {
         // First miss: record Structure to compare against next time.
         if (!lastStructure) {
-            vPC[4] = structure;
+            vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
             return;
         }
 
@@ -1179,8 +1454,6 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
             vPC[5] = slot.cachedOffset();
             break;
         }
-
-        codeBlock->refStructures(vPC);
         return;
     }
 
@@ -1198,8 +1471,8 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (baseObject->structure()->isDictionary()) {
-            baseObject->flattenDictionaryObject();
-            offset = baseObject->structure()->get(propertyName);
+            baseObject->flattenDictionaryObject(callFrame->globalData());
+            offset = baseObject->structure()->get(callFrame->globalData(), propertyName);
         }
 
         ASSERT(!baseObject->structure()->isUncacheableDictionary());
@@ -1218,9 +1491,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
             vPC[6] = offset;
             break;
         }
-        vPC[5] = baseObject->structure();
-
-        codeBlock->refStructures(vPC);
+        vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure());
         return;
     }
 
@@ -1246,22 +1517,20 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         vPC[7] = offset;
         break;
     }
-    vPC[4] = structure;
-    vPC[5] = structure->prototypeChain(callFrame);
+    vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
+    vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame));
     vPC[6] = count;
-    codeBlock->refStructures(vPC);
 }
 
-NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock* codeBlock, Instruction* vPC)
+NEVER_INLINE void Interpreter::uncacheGetByID(CodeBlock*, Instruction* vPC)
 {
-    codeBlock->derefStructures(vPC);
     vPC[0] = getOpcode(op_get_by_id);
     vPC[4] = 0;
 }
 
 #endif // ENABLE(INTERPRETER)
 
-JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
+JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame)
 {
     // One-time initialization of our address tables. We have to put this code
     // here because our labels are only in scope inside this function.
@@ -1269,7 +1538,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         #if ENABLE(COMPUTED_GOTO_INTERPRETER)
             #define LIST_OPCODE_LABEL(id, length) &&id,
                 static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) };
-                for (size_t i = 0; i < sizeof(labels) / sizeof(Opcode); ++i)
+                for (size_t i = 0; i < WTF_ARRAY_LENGTH(labels); ++i)
                     m_opcodeTable[i] = labels[i];
             #undef LIST_OPCODE_LABEL
         #endif // ENABLE(COMPUTED_GOTO_INTERPRETER)
@@ -1287,7 +1556,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #if !ENABLE(INTERPRETER)
     UNUSED_PARAM(registerFile);
     UNUSED_PARAM(callFrame);
-    UNUSED_PARAM(exception);
     return JSValue();
 #else
 
@@ -1295,9 +1563,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
     JSValue exceptionValue;
     HandlerInfo* handler = 0;
 
-    Instruction* vPC = callFrame->codeBlock()->instructions().begin();
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    Instruction* vPC = codeBlock->instructions().begin();
     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
     unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
+    JSValue functionReturnValue;
 
 #define CHECK_FOR_EXCEPTION() \
     do { \
@@ -1327,7 +1597,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #endif
 
 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
-    #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto *vPC->u.opcode
+    #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto *vPC->u.opcode
 #if ENABLE(OPCODE_STATS)
     #define DEFINE_OPCODE(opcode) opcode: OpcodeStats::recordInstruction(opcode);
 #else
@@ -1335,7 +1605,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #endif
     NEXT_INSTRUCTION();
 #else
-    #define NEXT_INSTRUCTION() SAMPLE(callFrame->codeBlock(), vPC); goto interpreterLoopStart
+    #define NEXT_INSTRUCTION() SAMPLE(codeBlock, vPC); goto interpreterLoopStart
 #if ENABLE(OPCODE_STATS)
     #define DEFINE_OPCODE(opcode) case opcode: OpcodeStats::recordInstruction(opcode);
 #else
@@ -1353,7 +1623,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            constructor, and puts the result in register dst.
         */
         int dst = vPC[1].u.operand;
-        callFrame->r(dst) = JSValue(constructEmptyObject(callFrame));
+        callFrame->uncheckedR(dst) = JSValue(constructEmptyObject(callFrame));
 
         vPC += OPCODE_LENGTH(op_new_object);
         NEXT_INSTRUCTION();
@@ -1370,11 +1640,27 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int firstArg = vPC[2].u.operand;
         int argCount = vPC[3].u.operand;
         ArgList args(callFrame->registers() + firstArg, argCount);
-        callFrame->r(dst) = JSValue(constructArray(callFrame, args));
+        callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, args));
 
         vPC += OPCODE_LENGTH(op_new_array);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_new_array_buffer) {
+        /* new_array_buffer dst(r) index(n) argCount(n)
+         
+         Constructs a new Array instance using the original
+         constructor, and puts the result in register dst.
+         The array be initialized with the values from constantBuffer[index]
+         */
+        int dst = vPC[1].u.operand;
+        int firstArg = vPC[2].u.operand;
+        int argCount = vPC[3].u.operand;
+        ArgList args(codeBlock->constantBuffer(firstArg), argCount);
+        callFrame->uncheckedR(dst) = JSValue(constructArray(callFrame, args));
+        
+        vPC += OPCODE_LENGTH(op_new_array);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_new_regexp) {
         /* new_regexp dst(r) regExp(re)
 
@@ -1383,8 +1669,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            register dst.
         */
         int dst = vPC[1].u.operand;
-        int regExp = vPC[2].u.operand;
-        callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject->regExpStructure(), callFrame->codeBlock()->regexp(regExp)));
+        RegExp* regExp = codeBlock->regexp(vPC[2].u.operand);
+        if (!regExp->isValid()) {
+            exceptionValue = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
+            goto vm_throw;
+        }
+        callFrame->uncheckedR(dst) = JSValue(new (globalData) RegExpObject(callFrame->lexicalGlobalObject(), callFrame->scopeChain()->globalObject->regExpStructure(), regExp));
 
         vPC += OPCODE_LENGTH(op_new_regexp);
         NEXT_INSTRUCTION();
@@ -1396,7 +1686,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = callFrame->r(src);
+        
+        callFrame->uncheckedR(dst) = callFrame->r(src);
 
         vPC += OPCODE_LENGTH(op_mov);
         NEXT_INSTRUCTION();
@@ -1412,11 +1703,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
-            callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
+            callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() == src2.asInt32());
         else {
             JSValue result = jsBoolean(JSValue::equalSlowCase(callFrame, src1, src2));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_eq);
@@ -1432,12 +1723,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
 
         if (src.isUndefinedOrNull()) {
-            callFrame->r(dst) = jsBoolean(true);
+            callFrame->uncheckedR(dst) = jsBoolean(true);
             vPC += OPCODE_LENGTH(op_eq_null);
             NEXT_INSTRUCTION();
         }
         
-        callFrame->r(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
+        callFrame->uncheckedR(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
         vPC += OPCODE_LENGTH(op_eq_null);
         NEXT_INSTRUCTION();
     }
@@ -1452,11 +1743,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
-            callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
+            callFrame->uncheckedR(dst) = jsBoolean(src1.asInt32() != src2.asInt32());
         else {
             JSValue result = jsBoolean(!JSValue::equalSlowCase(callFrame, src1, src2));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_neq);
@@ -1472,12 +1763,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
 
         if (src.isUndefinedOrNull()) {
-            callFrame->r(dst) = jsBoolean(false);
+            callFrame->uncheckedR(dst) = jsBoolean(false);
             vPC += OPCODE_LENGTH(op_neq_null);
             NEXT_INSTRUCTION();
         }
         
-        callFrame->r(dst) = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined());
+        callFrame->uncheckedR(dst) = jsBoolean(!src.isCell() || !src.asCell()->structure()->typeInfo().masqueradesAsUndefined());
         vPC += OPCODE_LENGTH(op_neq_null);
         NEXT_INSTRUCTION();
     }
@@ -1493,7 +1784,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         bool result = JSValue::strictEqual(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = jsBoolean(result);
+        callFrame->uncheckedR(dst) = jsBoolean(result);
 
         vPC += OPCODE_LENGTH(op_stricteq);
         NEXT_INSTRUCTION();
@@ -1510,7 +1801,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         bool result = !JSValue::strictEqual(callFrame, src1, src2);
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = jsBoolean(result);
+        callFrame->uncheckedR(dst) = jsBoolean(result);
 
         vPC += OPCODE_LENGTH(op_nstricteq);
         NEXT_INSTRUCTION();
@@ -1527,7 +1818,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         JSValue result = jsBoolean(jsLess(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_less);
         NEXT_INSTRUCTION();
@@ -1544,7 +1835,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2));
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_lesseq);
         NEXT_INSTRUCTION();
@@ -1558,11 +1849,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int srcDst = vPC[1].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() < INT_MAX)
-            callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
+            callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
         else {
-            JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
+            JSValue result = jsNumber(v.toNumber(callFrame) + 1);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(srcDst) = result;
+            callFrame->uncheckedR(srcDst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_pre_inc);
@@ -1577,11 +1868,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int srcDst = vPC[1].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() > INT_MIN)
-            callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
+            callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
         else {
-            JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
+            JSValue result = jsNumber(v.toNumber(callFrame) - 1);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(srcDst) = result;
+            callFrame->uncheckedR(srcDst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_pre_dec);
@@ -1598,13 +1889,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int srcDst = vPC[2].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() < INT_MAX) {
-            callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1);
-            callFrame->r(dst) = v;
+            callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() + 1);
+            callFrame->uncheckedR(dst) = v;
         } else {
             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() + 1);
-            callFrame->r(dst) = number;
+            callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() + 1);
+            callFrame->uncheckedR(dst) = number;
         }
 
         vPC += OPCODE_LENGTH(op_post_inc);
@@ -1621,13 +1912,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int srcDst = vPC[2].u.operand;
         JSValue v = callFrame->r(srcDst).jsValue();
         if (v.isInt32() && v.asInt32() > INT_MIN) {
-            callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1);
-            callFrame->r(dst) = v;
+            callFrame->uncheckedR(srcDst) = jsNumber(v.asInt32() - 1);
+            callFrame->uncheckedR(dst) = v;
         } else {
             JSValue number = callFrame->r(srcDst).jsValue().toJSNumber(callFrame);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(srcDst) = jsNumber(callFrame, number.uncheckedGetNumber() - 1);
-            callFrame->r(dst) = number;
+            callFrame->uncheckedR(srcDst) = jsNumber(number.uncheckedGetNumber() - 1);
+            callFrame->uncheckedR(dst) = number;
         }
 
         vPC += OPCODE_LENGTH(op_post_dec);
@@ -1645,11 +1936,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue srcVal = callFrame->r(src).jsValue();
 
         if (LIKELY(srcVal.isNumber()))
-            callFrame->r(dst) = callFrame->r(src);
+            callFrame->uncheckedR(dst) = callFrame->r(src);
         else {
             JSValue result = srcVal.toJSNumber(callFrame);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_to_jsnumber);
@@ -1664,11 +1955,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
         if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow
-            callFrame->r(dst) = jsNumber(callFrame, -src.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(-src.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, -src.toNumber(callFrame));
+            JSValue result = jsNumber(-src.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_negate);
@@ -1685,11 +1976,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
-            callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
         else {
             JSValue result = jsAdd(callFrame, src1, src2);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
         vPC += OPCODE_LENGTH(op_add);
         NEXT_INSTRUCTION();
@@ -1704,11 +1995,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
-                callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32());
+                callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+            JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_mul);
@@ -1725,9 +2016,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
 
-        JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
+        JSValue result = jsNumber(dividend.toNumber(callFrame) / divisor.toNumber(callFrame));
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_div);
         NEXT_INSTRUCTION();
@@ -1744,9 +2035,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue();
 
         if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) {
-            JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32());
+            JSValue result = jsNumber(dividend.asInt32() % divisor.asInt32());
             ASSERT(result);
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
             vPC += OPCODE_LENGTH(op_mod);
             NEXT_INSTRUCTION();
         }
@@ -1755,9 +2046,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         // order of argument evaluation is not guaranteed.
         double d1 = dividend.toNumber(callFrame);
         double d2 = divisor.toNumber(callFrame);
-        JSValue result = jsNumber(callFrame, fmod(d1, d2));
+        JSValue result = jsNumber(fmod(d1, d2));
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_mod);
         NEXT_INSTRUCTION();
     }
@@ -1772,11 +2063,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
-            callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+            JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
         vPC += OPCODE_LENGTH(op_sub);
         NEXT_INSTRUCTION();
@@ -1793,11 +2084,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
 
         if (val.isInt32() && shift.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f));
+            callFrame->uncheckedR(dst) = jsNumber(val.asInt32() << (shift.asInt32() & 0x1f));
         else {
-            JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+            JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_lshift);
@@ -1815,11 +2106,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
 
         if (val.isInt32() && shift.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
+            callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
         else {
-            JSValue result = jsNumber(callFrame, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+            JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_rshift);
@@ -1836,11 +2127,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue val = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue shift = callFrame->r(vPC[3].u.operand).jsValue();
         if (val.isUInt32() && shift.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f));
+            callFrame->uncheckedR(dst) = jsNumber(val.asInt32() >> (shift.asInt32() & 0x1f));
         else {
-            JSValue result = jsNumber(callFrame, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+            JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_urshift);
@@ -1857,11 +2148,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() & src2.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+            JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_bitand);
@@ -1878,11 +2169,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() ^ src2.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+            JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_bitxor);
@@ -1899,11 +2190,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
         JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
         if (src1.isInt32() && src2.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() | src2.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+            JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_bitor);
@@ -1918,11 +2209,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         JSValue src = callFrame->r(vPC[2].u.operand).jsValue();
         if (src.isInt32())
-            callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32());
+            callFrame->uncheckedR(dst) = jsNumber(~src.asInt32());
         else {
-            JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame));
+            JSValue result = jsNumber(~src.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
         vPC += OPCODE_LENGTH(op_bitnot);
         NEXT_INSTRUCTION();
@@ -1937,11 +2228,28 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int src = vPC[2].u.operand;
         JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame));
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_not);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_check_has_instance) {
+        /* check_has_instance constructor(r)
+
+           Check 'constructor' is an object with the internal property
+           [HasInstance] (i.e. is a function ... *shakes head sadly at
+           JSC API*). Raises an exception if register constructor is not
+           an valid parameter for instanceof.
+        */
+        int base = vPC[1].u.operand;
+        JSValue baseVal = callFrame->r(base).jsValue();
+
+        if (isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue))
+            goto vm_throw;
+
+        vPC += OPCODE_LENGTH(op_check_has_instance);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_instanceof) {
         /* instanceof dst(r) value(r) constructor(r) constructorProto(r)
 
@@ -1962,12 +2270,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         JSValue baseVal = callFrame->r(base).jsValue();
 
-        if (isInvalidParamForInstanceOf(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
-            goto vm_throw;
+        ASSERT(!isInvalidParamForInstanceOf(callFrame, baseVal, exceptionValue));
 
         bool result = asObject(baseVal)->hasInstance(callFrame, callFrame->r(value).jsValue(), callFrame->r(baseProto).jsValue());
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = jsBoolean(result);
+        callFrame->uncheckedR(dst) = jsBoolean(result);
 
         vPC += OPCODE_LENGTH(op_instanceof);
         NEXT_INSTRUCTION();
@@ -1980,7 +2287,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
+        callFrame->uncheckedR(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue()));
 
         vPC += OPCODE_LENGTH(op_typeof);
         NEXT_INSTRUCTION();
@@ -1995,7 +2302,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
         JSValue v = callFrame->r(src).jsValue();
-        callFrame->r(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
+        callFrame->uncheckedR(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined());
 
         vPC += OPCODE_LENGTH(op_is_undefined);
         NEXT_INSTRUCTION();
@@ -2009,7 +2316,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
+        callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean());
 
         vPC += OPCODE_LENGTH(op_is_boolean);
         NEXT_INSTRUCTION();
@@ -2023,7 +2330,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
+        callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber());
 
         vPC += OPCODE_LENGTH(op_is_number);
         NEXT_INSTRUCTION();
@@ -2037,7 +2344,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
+        callFrame->uncheckedR(dst) = jsBoolean(callFrame->r(src).jsValue().isString());
 
         vPC += OPCODE_LENGTH(op_is_string);
         NEXT_INSTRUCTION();
@@ -2051,7 +2358,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
+        callFrame->uncheckedR(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue()));
 
         vPC += OPCODE_LENGTH(op_is_object);
         NEXT_INSTRUCTION();
@@ -2065,7 +2372,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         */
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
-        callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
+        callFrame->uncheckedR(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue()));
 
         vPC += OPCODE_LENGTH(op_is_function);
         NEXT_INSTRUCTION();
@@ -2084,7 +2391,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int base = vPC[3].u.operand;
 
         JSValue baseVal = callFrame->r(base).jsValue();
-        if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue))
+        if (isInvalidParamForIn(callFrame, baseVal, exceptionValue))
             goto vm_throw;
 
         JSObject* baseObj = asObject(baseVal);
@@ -2093,11 +2400,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         uint32_t i;
         if (propName.getUInt32(i))
-            callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
+            callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, i));
         else {
             Identifier property(callFrame, propName.toString(callFrame));
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
+            callFrame->uncheckedR(dst) = jsBoolean(baseObj->hasProperty(callFrame, property));
         }
 
         vPC += OPCODE_LENGTH(op_in);
@@ -2169,11 +2476,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
            Gets the global var at global slot index and places it in register dst.
          */
         int dst = vPC[1].u.operand;
-        JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[2].u.jsCell);
+        JSGlobalObject* scope = codeBlock->globalObject();
         ASSERT(scope->isGlobalObject());
-        int index = vPC[3].u.operand;
+        int index = vPC[2].u.operand;
 
-        callFrame->r(dst) = scope->registerAt(index);
+        callFrame->uncheckedR(dst) = scope->registerAt(index).get();
         vPC += OPCODE_LENGTH(op_get_global_var);
         NEXT_INSTRUCTION();
     }
@@ -2182,12 +2489,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
          
            Puts value into global slot index.
          */
-        JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[1].u.jsCell);
+        JSGlobalObject* scope = codeBlock->globalObject();
         ASSERT(scope->isGlobalObject());
-        int index = vPC[2].u.operand;
-        int value = vPC[3].u.operand;
+        int index = vPC[1].u.operand;
+        int value = vPC[2].u.operand;
         
-        scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
+        scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
         vPC += OPCODE_LENGTH(op_put_global_var);
         NEXT_INSTRUCTION();
     }
@@ -2195,23 +2502,31 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         /* get_scoped_var dst(r) index(n) skip(n)
 
          Loads the contents of the index-th local from the scope skip nodes from
-         the top of the scope chain, and places it in register dst
+         the top of the scope chain, and places it in register dst.
          */
         int dst = vPC[1].u.operand;
         int index = vPC[2].u.operand;
-        int skip = vPC[3].u.operand + callFrame->codeBlock()->needsFullScopeChain();
+        int skip = vPC[3].u.operand;
 
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
         ASSERT(iter != end);
+        ASSERT(codeBlock == callFrame->codeBlock());
+        bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+        ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+            if (callFrame->r(codeBlock->activationRegister()).jsValue())
+                ++iter;
+        }
         while (skip--) {
             ++iter;
             ASSERT(iter != end);
         }
         ASSERT((*iter)->isVariableObject());
-        JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
-        callFrame->r(dst) = scope->registerAt(index);
+        JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
+        callFrame->uncheckedR(dst) = scope->registerAt(index).get();
+        ASSERT(callFrame->r(dst).jsValue());
         vPC += OPCODE_LENGTH(op_get_scoped_var);
         NEXT_INSTRUCTION();
     }
@@ -2220,37 +2535,67 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
          */
         int index = vPC[1].u.operand;
-        int skip = vPC[2].u.operand + callFrame->codeBlock()->needsFullScopeChain();
+        int skip = vPC[2].u.operand;
         int value = vPC[3].u.operand;
 
         ScopeChainNode* scopeChain = callFrame->scopeChain();
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator end = scopeChain->end();
+        ASSERT(codeBlock == callFrame->codeBlock());
         ASSERT(iter != end);
+        bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+        ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+            if (callFrame->r(codeBlock->activationRegister()).jsValue())
+                ++iter;
+        }
         while (skip--) {
             ++iter;
             ASSERT(iter != end);
         }
 
         ASSERT((*iter)->isVariableObject());
-        JSVariableObject* scope = static_cast<JSVariableObject*>(*iter);
-        scope->registerAt(index) = JSValue(callFrame->r(value).jsValue());
+        JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
+        ASSERT(callFrame->r(value).jsValue());
+        scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
         vPC += OPCODE_LENGTH(op_put_scoped_var);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_resolve_base) {
-        /* resolve_base dst(r) property(id)
+        /* resolve_base dst(r) property(id) isStrict(bool)
 
            Searches the scope chain for an object containing
            identifier property, and if one is found, writes it to
-           register dst. If none is found, the outermost scope (which
-           will be the global object) is stored in register dst.
+           register dst. If none is found and isStrict is false, the
+           outermost scope (which will be the global object) is
+           stored in register dst.
         */
         resolveBase(callFrame, vPC);
+        CHECK_FOR_EXCEPTION();
 
         vPC += OPCODE_LENGTH(op_resolve_base);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_ensure_property_exists) {
+        /* ensure_property_exists base(r) property(id)
+
+           Throws an exception if property does not exist on base
+         */
+        int base = vPC[1].u.operand;
+        int property = vPC[2].u.operand;
+        Identifier& ident = codeBlock->identifier(property);
+        
+        JSValue baseVal = callFrame->r(base).jsValue();
+        JSObject* baseObject = asObject(baseVal);
+        PropertySlot slot(baseVal);
+        if (!baseObject->getPropertySlot(callFrame, ident, slot)) {
+            exceptionValue = createErrorForInvalidGlobalAssignment(callFrame, ident.ustring());
+            goto vm_throw;
+        }
+
+        vPC += OPCODE_LENGTH(op_ensure_property_exists);
+        NEXT_INSTRUCTION();
+    }
     DEFINE_OPCODE(op_resolve_with_base) {
         /* resolve_with_base baseDst(r) propDst(r) property(id)
 
@@ -2279,7 +2624,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         int base = vPC[2].u.operand;
         int property = vPC[3].u.operand;
 
-        CodeBlock* codeBlock = callFrame->codeBlock();
         Identifier& ident = codeBlock->identifier(property);
         JSValue baseValue = callFrame->r(base).jsValue();
         PropertySlot slot(baseValue);
@@ -2288,7 +2632,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 
         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
 
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_id);
         NEXT_INSTRUCTION();
     }
@@ -2303,8 +2647,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
 
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
 
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(baseCell->isObject());
@@ -2312,15 +2656,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                 int dst = vPC[1].u.operand;
                 int offset = vPC[5].u.operand;
 
-                ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
-                callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
+                ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
+                callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
 
                 vPC += OPCODE_LENGTH(op_get_by_id_self);
                 NEXT_INSTRUCTION();
             }
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_get_by_id_proto) {
@@ -2334,21 +2678,21 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
 
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
 
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
-                Structure* prototypeStructure = vPC[5].u.structure;
+                Structure* prototypeStructure = vPC[5].u.structure.get();
 
                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
                     int dst = vPC[1].u.operand;
                     int offset = vPC[6].u.operand;
 
-                    ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
-                    ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
-                    callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset));
+                    ASSERT(protoObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
+                    ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset));
+                    callFrame->uncheckedR(dst) = JSValue(protoObject->getDirectOffset(offset));
 
                     vPC += OPCODE_LENGTH(op_get_by_id_proto);
                     NEXT_INSTRUCTION();
@@ -2356,7 +2700,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             }
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
@@ -2373,13 +2717,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
             
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
-                Structure* prototypeStructure = vPC[5].u.structure;
+                Structure* prototypeStructure = vPC[5].u.structure.get();
                 
                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
                     int dst = vPC[1].u.operand;
@@ -2390,15 +2734,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                         CallType callType = getter->getCallData(callData);
                         JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
                         CHECK_FOR_EXCEPTION();
-                        callFrame->r(dst) = result;
+                        callFrame->uncheckedR(dst) = result;
                     } else
-                        callFrame->r(dst) = jsUndefined();
+                        callFrame->uncheckedR(dst) = jsUndefined();
                     vPC += OPCODE_LENGTH(op_get_by_id_getter_proto);
                     NEXT_INSTRUCTION();
                 }
             }
         }
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
@@ -2418,29 +2762,29 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
             
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(structure->prototypeForLookup(callFrame).isObject());
                 JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
-                Structure* prototypeStructure = vPC[5].u.structure;
+                Structure* prototypeStructure = vPC[5].u.structure.get();
                 
                 if (LIKELY(protoObject->structure() == prototypeStructure)) {
                     int dst = vPC[1].u.operand;
                     int property = vPC[3].u.operand;
-                    Identifier& ident = callFrame->codeBlock()->identifier(property);
+                    Identifier& ident = codeBlock->identifier(property);
                     
                     PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc;
                     JSValue result = getter(callFrame, protoObject, ident);
                     CHECK_FOR_EXCEPTION();
-                    callFrame->r(dst) = result;
+                    callFrame->uncheckedR(dst) = result;
                     vPC += OPCODE_LENGTH(op_get_by_id_custom_proto);
                     NEXT_INSTRUCTION();
                 }
             }
         }
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
@@ -2488,6 +2832,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
         NEXT_INSTRUCTION();
     }
+#if USE(GCC_COMPUTED_GOTO_WORKAROUND)
+    goto *(&&skip_get_by_id_chain);
+#endif
     DEFINE_OPCODE(op_get_by_id_chain) {
         /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
 
@@ -2499,13 +2846,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
 
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
 
             if (LIKELY(baseCell->structure() == structure)) {
-                RefPtr<Structure>* it = vPC[5].u.structureChain->head();
+                WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
                 size_t count = vPC[6].u.operand;
-                RefPtr<Structure>* end = it + count;
+                WriteBarrier<Structure>* end = it + count;
 
                 while (true) {
                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
@@ -2517,9 +2864,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                         int dst = vPC[1].u.operand;
                         int offset = vPC[7].u.operand;
 
-                        ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
-                        ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
-                        callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset));
+                        ASSERT(baseObject->get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
+                        ASSERT(baseValue.get(callFrame, codeBlock->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset));
+                        callFrame->uncheckedR(dst) = JSValue(baseObject->getDirectOffset(offset));
 
                         vPC += OPCODE_LENGTH(op_get_by_id_chain);
                         NEXT_INSTRUCTION();
@@ -2531,10 +2878,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
             }
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
+    skip_get_by_id_chain:
     goto *(&&skip_id_getter_self);
 #endif
     DEFINE_OPCODE(op_get_by_id_getter_self) {
@@ -2548,8 +2896,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
             
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(baseCell->isObject());
@@ -2563,15 +2911,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
                     CallType callType = getter->getCallData(callData);
                     JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
                     CHECK_FOR_EXCEPTION();
-                    callFrame->r(dst) = result;
+                    callFrame->uncheckedR(dst) = result;
                 } else
-                    callFrame->r(dst) = jsUndefined();
+                    callFrame->uncheckedR(dst) = jsUndefined();
 
                 vPC += OPCODE_LENGTH(op_get_by_id_getter_self);
                 NEXT_INSTRUCTION();
             }
         }
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
@@ -2591,24 +2939,24 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
             
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(baseCell->isObject());
                 int dst = vPC[1].u.operand;
                 int property = vPC[3].u.operand;
-                Identifier& ident = callFrame->codeBlock()->identifier(property);
+                Identifier& ident = codeBlock->identifier(property);
 
                 PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc;
                 JSValue result = getter(callFrame, baseValue, ident);
                 CHECK_FOR_EXCEPTION();
-                callFrame->r(dst) = result;
+                callFrame->uncheckedR(dst) = result;
                 vPC += OPCODE_LENGTH(op_get_by_id_custom_self);
                 NEXT_INSTRUCTION();
             }
         }
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
@@ -2624,13 +2972,13 @@ skip_id_custom_self:
         int base = vPC[2].u.operand;
         int property = vPC[3].u.operand;
 
-        Identifier& ident = callFrame->codeBlock()->identifier(property);
+        Identifier& ident = codeBlock->identifier(property);
         JSValue baseValue = callFrame->r(base).jsValue();
         PropertySlot slot(baseValue);
         JSValue result = baseValue.get(callFrame, ident, slot);
         CHECK_FOR_EXCEPTION();
 
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_id_generic);
         NEXT_INSTRUCTION();
     }
@@ -2648,13 +2996,13 @@ skip_id_custom_self:
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
             
             if (LIKELY(baseCell->structure() == structure)) {
-                RefPtr<Structure>* it = vPC[5].u.structureChain->head();
+                WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
                 size_t count = vPC[6].u.operand;
-                RefPtr<Structure>* end = it + count;
+                WriteBarrier<Structure>* end = it + count;
                 
                 while (true) {
                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
@@ -2671,9 +3019,9 @@ skip_id_custom_self:
                             CallType callType = getter->getCallData(callData);
                             JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList());
                             CHECK_FOR_EXCEPTION();
-                            callFrame->r(dst) = result;
+                            callFrame->uncheckedR(dst) = result;
                         } else
-                            callFrame->r(dst) = jsUndefined();
+                            callFrame->uncheckedR(dst) = jsUndefined();
                         vPC += OPCODE_LENGTH(op_get_by_id_getter_chain);
                         NEXT_INSTRUCTION();
                     }
@@ -2683,7 +3031,7 @@ skip_id_custom_self:
                 }
             }
         }
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
@@ -2703,13 +3051,13 @@ skip_id_custom_self:
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
             
             if (LIKELY(baseCell->structure() == structure)) {
-                RefPtr<Structure>* it = vPC[5].u.structureChain->head();
+                WriteBarrier<Structure>* it = vPC[5].u.structureChain->head();
                 size_t count = vPC[6].u.operand;
-                RefPtr<Structure>* end = it + count;
+                WriteBarrier<Structure>* end = it + count;
                 
                 while (true) {
                     JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
@@ -2720,12 +3068,12 @@ skip_id_custom_self:
                     if (++it == end) {
                         int dst = vPC[1].u.operand;
                         int property = vPC[3].u.operand;
-                        Identifier& ident = callFrame->codeBlock()->identifier(property);
+                        Identifier& ident = codeBlock->identifier(property);
                         
                         PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc;
                         JSValue result = getter(callFrame, baseObject, ident);
                         CHECK_FOR_EXCEPTION();
-                        callFrame->r(dst) = result;
+                        callFrame->uncheckedR(dst) = result;
                         vPC += OPCODE_LENGTH(op_get_by_id_custom_chain);
                         NEXT_INSTRUCTION();
                     }
@@ -2735,11 +3083,12 @@ skip_id_custom_self:
                 }
             }
         }
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
 #if USE(GCC_COMPUTED_GOTO_WORKAROUND)
     skip_id_custom_chain:
+    goto *(&&skip_get_array_length);
 #endif
     DEFINE_OPCODE(op_get_array_length) {
         /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
@@ -2753,14 +3102,18 @@ skip_id_custom_self:
         JSValue baseValue = callFrame->r(base).jsValue();
         if (LIKELY(isJSArray(globalData, baseValue))) {
             int dst = vPC[1].u.operand;
-            callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length());
+            callFrame->uncheckedR(dst) = jsNumber(asArray(baseValue)->length());
             vPC += OPCODE_LENGTH(op_get_array_length);
             NEXT_INSTRUCTION();
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
+#if USE(GCC_COMPUTED_GOTO_WORKAROUND)
+    skip_get_array_length:
+    goto *(&&skip_get_string_length);
+#endif
     DEFINE_OPCODE(op_get_string_length) {
         /* op_get_string_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
 
@@ -2773,14 +3126,18 @@ skip_id_custom_self:
         JSValue baseValue = callFrame->r(base).jsValue();
         if (LIKELY(isJSString(globalData, baseValue))) {
             int dst = vPC[1].u.operand;
-            callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->length());
+            callFrame->uncheckedR(dst) = jsNumber(asString(baseValue)->length());
             vPC += OPCODE_LENGTH(op_get_string_length);
             NEXT_INSTRUCTION();
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
+#if USE(GCC_COMPUTED_GOTO_WORKAROUND)
+    skip_get_string_length:
+    goto *(&&skip_put_by_id);
+#endif
     DEFINE_OPCODE(op_put_by_id) {
         /* put_by_id base(r) property(id) value(r) nop(n) nop(n) nop(n) nop(n) direct(b)
 
@@ -2789,7 +3146,7 @@ skip_id_custom_self:
 
            Unlike many opcodes, this one does not write any output to
            the register file.
+
            The "direct" flag should only be set this put_by_id is to initialize
            an object literal.
         */
@@ -2799,10 +3156,9 @@ skip_id_custom_self:
         int value = vPC[3].u.operand;
         int direct = vPC[8].u.operand;
 
-        CodeBlock* codeBlock = callFrame->codeBlock();
         JSValue baseValue = callFrame->r(base).jsValue();
         Identifier& ident = codeBlock->identifier(property);
-        PutPropertySlot slot;
+        PutPropertySlot slot(codeBlock->isStrictMode());
         if (direct) {
             baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
             ASSERT(slot.base() == baseValue);
@@ -2815,6 +3171,9 @@ skip_id_custom_self:
         vPC += OPCODE_LENGTH(op_put_by_id);
         NEXT_INSTRUCTION();
     }
+#if USE(GCC_COMPUTED_GOTO_WORKAROUND)
+      skip_put_by_id:
+#endif
     DEFINE_OPCODE(op_put_by_id_transition) {
         /* op_put_by_id_transition base(r) property(id) value(r) oldStructure(sID) newStructure(sID) structureChain(chain) offset(n) direct(b)
          
@@ -2830,41 +3189,41 @@ skip_id_custom_self:
         JSValue baseValue = callFrame->r(base).jsValue();
         
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* oldStructure = vPC[4].u.structure;
-            Structure* newStructure = vPC[5].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* oldStructure = vPC[4].u.structure.get();
+            Structure* newStructure = vPC[5].u.structure.get();
             
             if (LIKELY(baseCell->structure() == oldStructure)) {
                 ASSERT(baseCell->isObject());
                 JSObject* baseObject = asObject(baseCell);
                 int direct = vPC[8].u.operand;
-
+                
                 if (!direct) {
-                    RefPtr<Structure>* it = vPC[6].u.structureChain->head();
+                    WriteBarrier<Structure>* it = vPC[6].u.structureChain->head();
 
                     JSValue proto = baseObject->structure()->prototypeForLookup(callFrame);
                     while (!proto.isNull()) {
                         if (UNLIKELY(asObject(proto)->structure() != (*it).get())) {
-                            uncachePutByID(callFrame->codeBlock(), vPC);
+                            uncachePutByID(codeBlock, vPC);
                             NEXT_INSTRUCTION();
                         }
                         ++it;
                         proto = asObject(proto)->structure()->prototypeForLookup(callFrame);
                     }
                 }
-                baseObject->transitionTo(newStructure);
+                baseObject->transitionTo(*globalData, newStructure);
 
                 int value = vPC[3].u.operand;
                 unsigned offset = vPC[7].u.operand;
-                ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
-                baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
+                ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
+                baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
 
                 vPC += OPCODE_LENGTH(op_put_by_id_transition);
                 NEXT_INSTRUCTION();
             }
         }
         
-        uncachePutByID(callFrame->codeBlock(), vPC);
+        uncachePutByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_id_replace) {
@@ -2882,8 +3241,8 @@ skip_id_custom_self:
         JSValue baseValue = callFrame->r(base).jsValue();
 
         if (LIKELY(baseValue.isCell())) {
-            JSCell* baseCell = asCell(baseValue);
-            Structure* structure = vPC[4].u.structure;
+            JSCell* baseCell = baseValue.asCell();
+            Structure* structure = vPC[4].u.structure.get();
 
             if (LIKELY(baseCell->structure() == structure)) {
                 ASSERT(baseCell->isObject());
@@ -2891,15 +3250,15 @@ skip_id_custom_self:
                 int value = vPC[3].u.operand;
                 unsigned offset = vPC[5].u.operand;
                 
-                ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset);
-                baseObject->putDirectOffset(offset, callFrame->r(value).jsValue());
+                ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(*globalData, codeBlock->identifier(vPC[2].u.operand))) == offset);
+                baseObject->putDirectOffset(callFrame->globalData(), offset, callFrame->r(value).jsValue());
 
                 vPC += OPCODE_LENGTH(op_put_by_id_replace);
                 NEXT_INSTRUCTION();
             }
         }
 
-        uncachePutByID(callFrame->codeBlock(), vPC);
+        uncachePutByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_put_by_id_generic) {
@@ -2917,8 +3276,8 @@ skip_id_custom_self:
         int direct = vPC[8].u.operand;
 
         JSValue baseValue = callFrame->r(base).jsValue();
-        Identifier& ident = callFrame->codeBlock()->identifier(property);
-        PutPropertySlot slot;
+        Identifier& ident = codeBlock->identifier(property);
+        PutPropertySlot slot(codeBlock->isStrictMode());
         if (direct) {
             baseValue.putDirect(callFrame, ident, callFrame->r(value).jsValue(), slot);
             ASSERT(slot.base() == baseValue);
@@ -2942,10 +3301,14 @@ skip_id_custom_self:
         int property = vPC[3].u.operand;
 
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame);
-        Identifier& ident = callFrame->codeBlock()->identifier(property);
-        JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident));
+        Identifier& ident = codeBlock->identifier(property);
+        bool result = baseObj->deleteProperty(callFrame, ident);
+        if (!result && codeBlock->isStrictMode()) {
+            exceptionValue = createTypeError(callFrame, "Unable to delete property.");
+            goto vm_throw;
+        }
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = jsBoolean(result);
         vPC += OPCODE_LENGTH(op_del_by_id);
         NEXT_INSTRUCTION();
     }
@@ -2965,17 +3328,59 @@ skip_id_custom_self:
         JSValue result;
         int offset = 0;
         if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) {
-            callFrame->r(dst) = asObject(baseValue)->getDirectOffset(offset);
+            callFrame->uncheckedR(dst) = JSValue(asObject(baseValue)->getDirectOffset(offset));
             vPC += OPCODE_LENGTH(op_get_by_pname);
             NEXT_INSTRUCTION();
         }
-        Identifier propertyName(callFrame, subscript.toString(callFrame));
-        result = baseValue.get(callFrame, propertyName);
+        {
+            Identifier propertyName(callFrame, subscript.toString(callFrame));
+            result = baseValue.get(callFrame, propertyName);
+        }
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_pname);
         NEXT_INSTRUCTION();
     }
+    DEFINE_OPCODE(op_get_arguments_length) {
+        int dst = vPC[1].u.operand;
+        int argumentsRegister = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
+        JSValue arguments = callFrame->r(argumentsRegister).jsValue();
+        if (arguments) {
+            Identifier& ident = codeBlock->identifier(property);
+            PropertySlot slot(arguments);
+            JSValue result = arguments.get(callFrame, ident, slot);
+            CHECK_FOR_EXCEPTION();
+            callFrame->uncheckedR(dst) = result;
+        } else
+            callFrame->uncheckedR(dst) = jsNumber(callFrame->argumentCount());
+
+        vPC += OPCODE_LENGTH(op_get_arguments_length);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_get_argument_by_val) {
+        int dst = vPC[1].u.operand;
+        int argumentsRegister = vPC[2].u.operand;
+        int property = vPC[3].u.operand;
+        JSValue arguments = callFrame->r(argumentsRegister).jsValue();
+        JSValue subscript = callFrame->r(property).jsValue();
+        if (!arguments && subscript.isUInt32() && subscript.asUInt32() < callFrame->argumentCount()) {
+            unsigned arg = subscript.asUInt32() + 1;
+            unsigned numParameters = callFrame->codeBlock()->m_numParameters;
+            if (arg < numParameters)
+                callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters);
+            else
+                callFrame->uncheckedR(dst) = callFrame->r(arg - RegisterFile::CallFrameHeaderSize - numParameters - callFrame->argumentCount() - 1);
+            vPC += OPCODE_LENGTH(op_get_argument_by_val);
+            NEXT_INSTRUCTION();
+        }
+        if (!arguments) {
+            Arguments* arguments = new (globalData) Arguments(callFrame);
+            callFrame->uncheckedR(argumentsRegister) = JSValue(arguments);
+            callFrame->uncheckedR(unmodifiedArgumentsRegister(argumentsRegister)) = JSValue(arguments);
+        }
+        // fallthrough
+    }
     DEFINE_OPCODE(op_get_by_val) {
         /* get_by_val dst(r) base(r) property(r)
 
@@ -3013,7 +3418,7 @@ skip_id_custom_self:
         }
 
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_val);
         NEXT_INSTRUCTION();
     }
@@ -3040,7 +3445,7 @@ skip_id_custom_self:
             if (isJSArray(globalData, baseValue)) {
                 JSArray* jsArray = asArray(baseValue);
                 if (jsArray->canSetIndex(i))
-                    jsArray->setIndex(i, callFrame->r(value).jsValue());
+                    jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue());
                 else
                     jsArray->JSArray::put(callFrame, i, callFrame->r(value).jsValue());
             } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
@@ -3058,7 +3463,7 @@ skip_id_custom_self:
         } else {
             Identifier property(callFrame, subscript.toString(callFrame));
             if (!globalData->exception) { // Don't put to an object if toString threw an exception.
-                PutPropertySlot slot;
+                PutPropertySlot slot(codeBlock->isStrictMode());
                 baseValue.put(callFrame, property, callFrame->r(value).jsValue(), slot);
             }
         }
@@ -3082,19 +3487,22 @@ skip_id_custom_self:
         JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw
 
         JSValue subscript = callFrame->r(property).jsValue();
-        JSValue result;
+        bool result;
         uint32_t i;
         if (subscript.getUInt32(i))
-            result = jsBoolean(baseObj->deleteProperty(callFrame, i));
+            result = baseObj->deleteProperty(callFrame, i);
         else {
             CHECK_FOR_EXCEPTION();
             Identifier property(callFrame, subscript.toString(callFrame));
             CHECK_FOR_EXCEPTION();
-            result = jsBoolean(baseObj->deleteProperty(callFrame, property));
+            result = baseObj->deleteProperty(callFrame, property);
+        }
+        if (!result && codeBlock->isStrictMode()) {
+            exceptionValue = createTypeError(callFrame, "Unable to delete property.");
+            goto vm_throw;
         }
-
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = jsBoolean(result);
         vPC += OPCODE_LENGTH(op_del_by_val);
         NEXT_INSTRUCTION();
     }
@@ -3265,10 +3673,9 @@ skip_id_custom_self:
            to ptr, using pointer equality.
          */
         int src = vPC[1].u.operand;
-        JSValue ptr = JSValue(vPC[2].u.jsCell);
         int target = vPC[3].u.operand;
         JSValue srcValue = callFrame->r(src).jsValue();
-        if (srcValue != ptr) {
+        if (srcValue != vPC[2].u.jsCell.get()) {
             vPC += target;
             NEXT_INSTRUCTION();
         }
@@ -3435,12 +3842,12 @@ skip_id_custom_self:
         int defaultOffset = vPC[2].u.operand;
         JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue();
         if (scrutinee.isInt32())
-            vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
+            vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset);
         else {
             double value;
             int32_t intValue;
             if (scrutinee.getNumber(value) && ((intValue = static_cast<int32_t>(value)) == value))
-                vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
+                vPC += codeBlock->immediateSwitchJumpTable(tableIndex).offsetForValue(intValue, defaultOffset);
             else
                 vPC += defaultOffset;
         }
@@ -3461,11 +3868,11 @@ skip_id_custom_self:
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else {
-            UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
+            StringImpl* value = asString(scrutinee)->value(callFrame).impl();
             if (value->length() != 1)
                 vPC += defaultOffset;
             else
-                vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->characters()[0], defaultOffset);
+                vPC += codeBlock->characterSwitchJumpTable(tableIndex).offsetForValue(value->characters()[0], defaultOffset);
         }
         NEXT_INSTRUCTION();
     }
@@ -3484,7 +3891,7 @@ skip_id_custom_self:
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else 
-            vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).rep(), defaultOffset);
+            vPC += codeBlock->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).impl(), defaultOffset);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_new_func) {
@@ -3497,8 +3904,10 @@ skip_id_custom_self:
         */
         int dst = vPC[1].u.operand;
         int func = vPC[2].u.operand;
-
-        callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
+        int shouldCheck = vPC[3].u.operand;
+        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
+        if (!shouldCheck || !callFrame->r(dst).jsValue())
+            callFrame->uncheckedR(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain()));
 
         vPC += OPCODE_LENGTH(op_new_func);
         NEXT_INSTRUCTION();
@@ -3513,8 +3922,9 @@ skip_id_custom_self:
         */
         int dst = vPC[1].u.operand;
         int funcIndex = vPC[2].u.operand;
-
-        FunctionExecutable* function = callFrame->codeBlock()->functionExpr(funcIndex);
+        
+        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
+        FunctionExecutable* function = codeBlock->functionExpr(funcIndex);
         JSFunction* func = function->make(callFrame, callFrame->scopeChain());
 
         /* 
@@ -3526,16 +3936,16 @@ skip_id_custom_self:
          */
         if (!function->name().isNull()) {
             JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
-            func->scope().push(functionScopeObject);
+            func->setScope(*globalData, func->scope()->push(functionScopeObject));
         }
 
-        callFrame->r(dst) = JSValue(func);
+        callFrame->uncheckedR(dst) = JSValue(func);
 
         vPC += OPCODE_LENGTH(op_new_func_exp);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_call_eval) {
-        /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
+        /* call_eval func(r) argCount(n) registerOffset(n)
 
            Call a function named "eval" with no explicit "this" value
            (which may therefore be the eval operator). If register
@@ -3546,23 +3956,23 @@ skip_id_custom_self:
            opcode). Otherwise, act exactly as the "call" opcode would.
          */
 
-        int dst = vPC[1].u.operand;
-        int func = vPC[2].u.operand;
-        int argCount = vPC[3].u.operand;
-        int registerOffset = vPC[4].u.operand;
-
+        int func = vPC[1].u.operand;
+        int argCount = vPC[2].u.operand;
+        int registerOffset = vPC[3].u.operand;
+        
+        ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue());
         JSValue funcVal = callFrame->r(func).jsValue();
 
         Register* newCallFrame = callFrame->registers() + registerOffset;
         Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
         JSValue thisValue = argv[0].jsValue();
-        JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
+        JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject.get();
 
         if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
-            JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
-            if (exceptionValue)
+            JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset);
+            if ((exceptionValue = globalData->exception))
                 goto vm_throw;
-            callFrame->r(dst) = result;
+            functionReturnValue = result;
 
             vPC += OPCODE_LENGTH(op_call_eval);
             NEXT_INSTRUCTION();
@@ -3573,7 +3983,7 @@ skip_id_custom_self:
         // fall through to op_call
     }
     DEFINE_OPCODE(op_call) {
-        /* call dst(r) func(r) argCount(n) registerOffset(n)
+        /* call func(r) argCount(n) registerOffset(n)
 
            Perform a function call.
            
@@ -3583,22 +3993,26 @@ skip_id_custom_self:
            dst is where op_ret should store its result.
          */
 
-        int dst = vPC[1].u.operand;
-        int func = vPC[2].u.operand;
-        int argCount = vPC[3].u.operand;
-        int registerOffset = vPC[4].u.operand;
+        int func = vPC[1].u.operand;
+        int argCount = vPC[2].u.operand;
+        int registerOffset = vPC[3].u.operand;
 
         JSValue v = callFrame->r(func).jsValue();
 
         CallData callData;
-        CallType callType = v.getCallData(callData);
+        CallType callType = getCallData(v, callData);
 
         if (callType == CallTypeJS) {
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
-            CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
 
-            CallFrame* previousCallFrame = callFrame;
+            JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
+            if (UNLIKELY(!!error)) {
+                exceptionValue = error;
+                goto vm_throw;
+            }
 
+            CallFrame* previousCallFrame = callFrame;
+            CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
             if (UNLIKELY(!callFrame)) {
                 callFrame = previousCallFrame;
@@ -3606,7 +4020,9 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
-            callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
+            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+            codeBlock = newCodeBlock;
+            ASSERT(codeBlock == callFrame->codeBlock());
             vPC = newCodeBlock->instructions().begin();
 
 #if ENABLE(OPCODE_STATS)
@@ -3619,24 +4035,21 @@ skip_id_custom_self:
         if (callType == CallTypeHost) {
             ScopeChainNode* scopeChain = callFrame->scopeChain();
             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
-            newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
-
-            Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
-            ArgList args(thisRegister + 1, argCount - 1);
+            if (!registerFile->grow(newCallFrame->registers())) {
+                exceptionValue = createStackOverflowError(callFrame);
+                goto vm_throw;
+            }
 
-            // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
-            JSValue thisValue = thisRegister->jsValue();
-            if (thisValue == jsNull())
-                thisValue = callFrame->globalThisValue();
+            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call), scopeChain, callFrame, argCount, asObject(v));
 
             JSValue returnValue;
             {
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
-                returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
+                returnValue = JSValue::decode(callData.native.function(newCallFrame));
             }
             CHECK_FOR_EXCEPTION();
 
-            callFrame->r(dst) = returnValue;
+            functionReturnValue = returnValue;
 
             vPC += OPCODE_LENGTH(op_call);
             NEXT_INSTRUCTION();
@@ -3644,7 +4057,7 @@ skip_id_custom_self:
 
         ASSERT(callType == CallTypeNone);
 
-        exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+        exceptionValue = createNotAFunctionError(callFrame, v);
         goto vm_throw;
     }
     DEFINE_OPCODE(op_load_varargs) {
@@ -3654,7 +4067,7 @@ skip_id_custom_self:
         JSValue arguments = callFrame->r(argsOffset).jsValue();
         uint32_t argCount = 0;
         if (!arguments) {
-            argCount = (uint32_t)(callFrame->argumentCount()) - 1;
+            argCount = (uint32_t)(callFrame->argumentCount());
             argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
             Register* newEnd = callFrame->registers() + sizeDelta;
@@ -3662,24 +4075,24 @@ skip_id_custom_self:
                 exceptionValue = createStackOverflowError(callFrame);
                 goto vm_throw;
             }
-            ASSERT(!callFrame->callee()->isHostFunction());
-            uint32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
-            uint32_t inplaceArgs = min(argCount, expectedParams);
-            uint32_t i = 0;
+            ASSERT(!asFunction(callFrame->callee())->isHostFunction());
+            int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
+            int32_t inplaceArgs = min(static_cast<int32_t>(argCount), expectedParams);
+            int32_t i = 0;
             Register* argStore = callFrame->registers() + argsOffset;
 
             // First step is to copy the "expected" parameters from their normal location relative to the callframe
             for (; i < inplaceArgs; i++)
                 argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams];
             // Then we copy any additional arguments that may be further up the stack ('-1' to account for 'this')
-            for (; i < argCount; i++)
-                argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - argCount - 1];
+            for (; i < static_cast<int32_t>(argCount); i++)
+                argStore[i] = callFrame->registers()[i - RegisterFile::CallFrameHeaderSize - expectedParams - static_cast<int32_t>(argCount) - 1];
         } else if (!arguments.isUndefinedOrNull()) {
             if (!arguments.isObject()) {
-                exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+                exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
                 goto vm_throw;
             }
-            if (asObject(arguments)->classInfo() == &Arguments::info) {
+            if (asObject(arguments)->classInfo() == &Arguments::s_info) {
                 Arguments* args = asArguments(arguments);
                 argCount = args->numProvidedArguments(callFrame);
                 argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
@@ -3701,7 +4114,7 @@ skip_id_custom_self:
                     goto vm_throw;
                 }
                 array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
-            } else if (asObject(arguments)->inherits(&JSArray::info)) {
+            } else if (asObject(arguments)->inherits(&JSArray::s_info)) {
                 JSObject* argObject = asObject(arguments);
                 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
                 argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
@@ -3717,17 +4130,17 @@ skip_id_custom_self:
                     CHECK_FOR_EXCEPTION();
                 }
             } else {
-                exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+                exceptionValue = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
                 goto vm_throw;
             }
         }
         CHECK_FOR_EXCEPTION();
-        callFrame->r(argCountDst) = Register::withInt(argCount + 1);
+        callFrame->uncheckedR(argCountDst) = Register::withInt(argCount + 1);
         vPC += OPCODE_LENGTH(op_load_varargs);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_call_varargs) {
-        /* call_varargs dst(r) func(r) argCountReg(r) baseRegisterOffset(n)
+        /* call_varargs func(r) argCountReg(r) baseRegisterOffset(n)
          
          Perform a function call with a dynamic set of arguments.
          
@@ -3738,31 +4151,37 @@ skip_id_custom_self:
          dst is where op_ret should store its result.
          */
         
-        int dst = vPC[1].u.operand;
-        int func = vPC[2].u.operand;
-        int argCountReg = vPC[3].u.operand;
-        int registerOffset = vPC[4].u.operand;
+        int func = vPC[1].u.operand;
+        int argCountReg = vPC[2].u.operand;
+        int registerOffset = vPC[3].u.operand;
         
         JSValue v = callFrame->r(func).jsValue();
         int argCount = callFrame->r(argCountReg).i();
         registerOffset += argCount;
         CallData callData;
-        CallType callType = v.getCallData(callData);
+        CallType callType = getCallData(v, callData);
         
         if (callType == CallTypeJS) {
             ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
-            CodeBlock* newCodeBlock = &callData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
-            
+
+            JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
+            if (UNLIKELY(!!error)) {
+                exceptionValue = error;
+                goto vm_throw;
+            }
+
             CallFrame* previousCallFrame = callFrame;
-            
+            CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
             if (UNLIKELY(!callFrame)) {
                 callFrame = previousCallFrame;
                 exceptionValue = createStackOverflowError(callFrame);
                 goto vm_throw;
             }
-            
-            callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
+
+            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+            codeBlock = newCodeBlock;
+            ASSERT(codeBlock == callFrame->codeBlock());
             vPC = newCodeBlock->instructions().begin();
             
 #if ENABLE(OPCODE_STATS)
@@ -3775,24 +4194,20 @@ skip_id_custom_self:
         if (callType == CallTypeHost) {
             ScopeChainNode* scopeChain = callFrame->scopeChain();
             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
-            newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
-            
-            Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
-            ArgList args(thisRegister + 1, argCount - 1);
-            
-            // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
-            JSValue thisValue = thisRegister->jsValue();
-            if (thisValue == jsNull())
-                thisValue = callFrame->globalThisValue();
+            if (!registerFile->grow(newCallFrame->registers())) {
+                exceptionValue = createStackOverflowError(callFrame);
+                goto vm_throw;
+            }
+            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_varargs), scopeChain, callFrame, argCount, asObject(v));
             
             JSValue returnValue;
             {
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
-                returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args);
+                returnValue = JSValue::decode(callData.native.function(newCallFrame));
             }
             CHECK_FOR_EXCEPTION();
             
-            callFrame->r(dst) = returnValue;
+            functionReturnValue = returnValue;
             
             vPC += OPCODE_LENGTH(op_call_varargs);
             NEXT_INSTRUCTION();
@@ -3800,52 +4215,99 @@ skip_id_custom_self:
         
         ASSERT(callType == CallTypeNone);
         
-        exceptionValue = createNotAFunctionError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+        exceptionValue = createNotAFunctionError(callFrame, v);
         goto vm_throw;
     }
     DEFINE_OPCODE(op_tear_off_activation) {
-        /* tear_off_activation activation(r)
+        /* tear_off_activation activation(r) arguments(r)
 
-           Copy all locals and parameters to new memory allocated on
-           the heap, and make the passed activation use this memory
-           in the future when looking up entries in the symbol table.
-           If there is an 'arguments' object, then it will also use
-           this memory for storing the named parameters, but not any
-           extra arguments.
+           Copy locals and named parameters from the register file to the heap.
+           Point the bindings in 'activation' and 'arguments' to this new backing
+           store. (Note that 'arguments' may not have been created. If created,
+           'arguments' already holds a copy of any extra / unnamed parameters.)
 
-           This opcode should only be used immediately before op_ret.
+           This opcode appears before op_ret in functions that require full scope chains.
         */
 
-        int src = vPC[1].u.operand;
-        ASSERT(callFrame->codeBlock()->needsFullScopeChain());
+        int activation = vPC[1].u.operand;
+        int arguments = vPC[2].u.operand;
+        ASSERT(codeBlock->needsFullScopeChain());
+        JSValue activationValue = callFrame->r(activation).jsValue();
+        if (activationValue) {
+            asActivation(activationValue)->copyRegisters(*globalData);
 
-        asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments());
+            if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
+                if (!codeBlock->isStrictMode())
+                    asArguments(argumentsValue)->setActivation(*globalData, asActivation(activationValue));
+            }
+        } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) {
+            if (!codeBlock->isStrictMode())
+                asArguments(argumentsValue)->copyRegisters(*globalData);
+        }
 
         vPC += OPCODE_LENGTH(op_tear_off_activation);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_tear_off_arguments) {
-        /* tear_off_arguments
+        /* tear_off_arguments arguments(r)
 
-           Copy all arguments to new memory allocated on the heap,
-           and make the 'arguments' object use this memory in the
-           future when looking up named parameters, but not any
-           extra arguments. If an activation object exists for the
-           current function context, then the tear_off_activation
-           opcode should be used instead.
+           Copy named parameters from the register file to the heap. Point the
+           bindings in 'arguments' to this new backing store. (Note that
+           'arguments' may not have been created. If created, 'arguments' already
+           holds a copy of any extra / unnamed parameters.)
 
-           This opcode should only be used immediately before op_ret.
+           This opcode appears before op_ret in functions that don't require full
+           scope chains, but do use 'arguments'.
         */
 
-        ASSERT(callFrame->codeBlock()->usesArguments() && !callFrame->codeBlock()->needsFullScopeChain());
+        int src1 = vPC[1].u.operand;
+        ASSERT(!codeBlock->needsFullScopeChain() && codeBlock->ownerExecutable()->usesArguments());
 
-        if (callFrame->optionalCalleeArguments())
-            callFrame->optionalCalleeArguments()->copyRegisters();
+        if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src1)).jsValue())
+            asArguments(arguments)->copyRegisters(*globalData);
 
         vPC += OPCODE_LENGTH(op_tear_off_arguments);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_ret) {
+        /* ret result(r)
+           
+           Return register result as the return value of the current
+           function call, writing it into functionReturnValue.
+           In addition, unwind one call frame and restore the scope
+           chain, code block instruction pointer and register base
+           to those of the calling function.
+        */
+
+        int result = vPC[1].u.operand;
+
+        JSValue returnValue = callFrame->r(result).jsValue();
+
+        vPC = callFrame->returnVPC();
+        callFrame = callFrame->callerFrame();
+        
+        if (callFrame->hasHostCallFrameFlag())
+            return returnValue;
+
+        functionReturnValue = returnValue;
+        codeBlock = callFrame->codeBlock();
+        ASSERT(codeBlock == callFrame->codeBlock());
+
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_call_put_result) {
+        /* op_call_put_result result(r)
+           
+           Move call result from functionReturnValue to caller's
+           expected return value register.
+        */
+
+        callFrame->uncheckedR(vPC[1].u.operand) = functionReturnValue;
+
+        vPC += OPCODE_LENGTH(op_call_put_result);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_ret_object_or_this) {
         /* ret result(r)
            
            Return register result as the return value of the current
@@ -3857,67 +4319,93 @@ skip_id_custom_self:
 
         int result = vPC[1].u.operand;
 
-        if (callFrame->codeBlock()->needsFullScopeChain())
-            callFrame->scopeChain()->deref();
-
         JSValue returnValue = callFrame->r(result).jsValue();
 
+        if (UNLIKELY(!returnValue.isObject()))
+            returnValue = callFrame->r(vPC[2].u.operand).jsValue();
+
         vPC = callFrame->returnVPC();
-        int dst = callFrame->returnValueRegister();
         callFrame = callFrame->callerFrame();
-        
+
         if (callFrame->hasHostCallFrameFlag())
             return returnValue;
 
-        callFrame->r(dst) = returnValue;
+        functionReturnValue = returnValue;
+        codeBlock = callFrame->codeBlock();
+        ASSERT(codeBlock == callFrame->codeBlock());
 
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_enter) {
         /* enter
 
-           Initializes local variables to undefined and fills constant
-           registers with their values. If the code block requires an
-           activation, enter_with_activation should be used instead.
+           Initializes local variables to undefined. If the code block requires
+           an activation, enter_with_activation is used instead.
 
-           This opcode should only be used at the beginning of a code
-           block.
+           This opcode appears only at the beginning of a code block.
         */
 
         size_t i = 0;
-        CodeBlock* codeBlock = callFrame->codeBlock();
-        
         for (size_t count = codeBlock->m_numVars; i < count; ++i)
-            callFrame->r(i) = jsUndefined();
+            callFrame->uncheckedR(i) = jsUndefined();
 
         vPC += OPCODE_LENGTH(op_enter);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_enter_with_activation) {
-        /* enter_with_activation dst(r)
+    DEFINE_OPCODE(op_create_activation) {
+        /* create_activation dst(r)
 
-           Initializes local variables to undefined, fills constant
-           registers with their values, creates an activation object,
-           and places the new activation both in dst and at the top
-           of the scope chain. If the code block does not require an
-           activation, enter should be used instead.
+           If the activation object for this callframe has not yet been created,
+           this creates it and writes it back to dst.
+        */
+
+        int activationReg = vPC[1].u.operand;
+        if (!callFrame->r(activationReg).jsValue()) {
+            JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
+            callFrame->r(activationReg) = JSValue(activation);
+            callFrame->setScopeChain(callFrame->scopeChain()->push(activation));
+        }
+        vPC += OPCODE_LENGTH(op_create_activation);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_get_callee) {
+        /* op_get_callee callee(r)
+
+           Move callee into a register.
+        */
+
+        callFrame->uncheckedR(vPC[1].u.operand) = JSValue(callFrame->callee());
+
+        vPC += OPCODE_LENGTH(op_get_callee);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_create_this) {
+        /* op_create_this this(r) proto(r)
+
+           Allocate an object as 'this', fr use in construction.
 
            This opcode should only be used at the beginning of a code
            block.
         */
 
-        size_t i = 0;
-        CodeBlock* codeBlock = callFrame->codeBlock();
+        int thisRegister = vPC[1].u.operand;
+        int protoRegister = vPC[2].u.operand;
 
-        for (size_t count = codeBlock->m_numVars; i < count; ++i)
-            callFrame->r(i) = jsUndefined();
+        JSFunction* constructor = asFunction(callFrame->callee());
+#if !ASSERT_DISABLED
+        ConstructData constructData;
+        ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
+#endif
 
-        int dst = vPC[1].u.operand;
-        JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable()));
-        callFrame->r(dst) = JSValue(activation);
-        callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation));
+        Structure* structure;
+        JSValue proto = callFrame->r(protoRegister).jsValue();
+        if (proto.isObject())
+            structure = asObject(proto)->inheritorID(callFrame->globalData());
+        else
+            structure = constructor->scope()->globalObject->emptyObjectStructure();
+        callFrame->uncheckedR(thisRegister) = constructEmptyObject(callFrame, structure);
 
-        vPC += OPCODE_LENGTH(op_enter_with_activation);
+        vPC += OPCODE_LENGTH(op_create_this);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_convert_this) {
@@ -3935,43 +4423,63 @@ skip_id_custom_self:
         int thisRegister = vPC[1].u.operand;
         JSValue thisVal = callFrame->r(thisRegister).jsValue();
         if (thisVal.needsThisConversion())
-            callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
+            callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toThisObject(callFrame));
 
         vPC += OPCODE_LENGTH(op_convert_this);
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_init_arguments) {
-        /* create_arguments
+    DEFINE_OPCODE(op_convert_this_strict) {
+        /* convert_this_strict this(r)
+         
+         Takes the value in the 'this' register, and converts it to
+         its "this" form if (and only if) "this" is an object with a
+         custom this conversion
+         
+         This opcode should only be used at the beginning of a code
+         block.
+         */
+        
+        int thisRegister = vPC[1].u.operand;
+        JSValue thisVal = callFrame->r(thisRegister).jsValue();
+        if (thisVal.isObject() && thisVal.needsThisConversion())
+            callFrame->uncheckedR(thisRegister) = JSValue(thisVal.toStrictThisObject(callFrame));
+        
+        vPC += OPCODE_LENGTH(op_convert_this_strict);
+        NEXT_INSTRUCTION();
+    }
+    DEFINE_OPCODE(op_init_lazy_reg) {
+        /* init_lazy_reg dst(r)
 
-           Initialises the arguments object reference to null to ensure
-           we can correctly detect that we need to create it later (or
-           avoid creating it altogether).
+           Initialises dst(r) to JSValue().
 
-           This opcode should only be used at the beginning of a code
-           block.
+           This opcode appears only at the beginning of a code block.
          */
-        callFrame->r(RegisterFile::ArgumentsRegister) = JSValue();
-        vPC += OPCODE_LENGTH(op_init_arguments);
+        int dst = vPC[1].u.operand;
+
+        callFrame->uncheckedR(dst) = JSValue();
+        vPC += OPCODE_LENGTH(op_init_lazy_reg);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_create_arguments) {
-        /* create_arguments
+        /* create_arguments dst(r)
 
            Creates the 'arguments' object and places it in both the
            'arguments' call frame slot and the local 'arguments'
            register, if it has not already been initialised.
          */
         
-         if (!callFrame->r(RegisterFile::ArgumentsRegister).jsValue()) {
-             Arguments* arguments = new (globalData) Arguments(callFrame);
-             callFrame->setCalleeArguments(arguments);
-             callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
-         }
+        int dst = vPC[1].u.operand;
+
+        if (!callFrame->r(dst).jsValue()) {
+            Arguments* arguments = new (globalData) Arguments(callFrame);
+            callFrame->uncheckedR(dst) = JSValue(arguments);
+            callFrame->uncheckedR(unmodifiedArgumentsRegister(dst)) = JSValue(arguments);
+        }
         vPC += OPCODE_LENGTH(op_create_arguments);
         NEXT_INSTRUCTION();
     }
     DEFINE_OPCODE(op_construct) {
-        /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
+        /* construct func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
 
            Invoke register "func" as a constructor. For JS
            functions, the calling convention is exactly as for the
@@ -3985,34 +4493,26 @@ skip_id_custom_self:
            caching of this lookup.
         */
 
-        int dst = vPC[1].u.operand;
-        int func = vPC[2].u.operand;
-        int argCount = vPC[3].u.operand;
-        int registerOffset = vPC[4].u.operand;
-        int proto = vPC[5].u.operand;
-        int thisRegister = vPC[6].u.operand;
+        int func = vPC[1].u.operand;
+        int argCount = vPC[2].u.operand;
+        int registerOffset = vPC[3].u.operand;
 
         JSValue v = callFrame->r(func).jsValue();
 
         ConstructData constructData;
-        ConstructType constructType = v.getConstructData(constructData);
+        ConstructType constructType = getConstructData(v, constructData);
 
         if (constructType == ConstructTypeJS) {
             ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
-            CodeBlock* newCodeBlock = &constructData.js.functionExecutable->bytecode(callFrame, callDataScopeChain);
-
-            Structure* structure;
-            JSValue prototype = callFrame->r(proto).jsValue();
-            if (prototype.isObject())
-                structure = asObject(prototype)->inheritorID();
-            else
-                structure = callDataScopeChain->globalObject->emptyObjectStructure();
-            JSObject* newObject = new (globalData) JSObject(structure);
 
-            callFrame->r(thisRegister) = JSValue(newObject); // "this" value
+            JSObject* error = constructData.js.functionExecutable->compileForConstruct(callFrame, callDataScopeChain);
+            if (UNLIKELY(!!error)) {
+                exceptionValue = error;
+                goto vm_throw;
+            }
 
             CallFrame* previousCallFrame = callFrame;
-
+            CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
             if (UNLIKELY(!callFrame)) {
                 callFrame = previousCallFrame;
@@ -4020,7 +4520,8 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
-            callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
+            callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+            codeBlock = newCodeBlock;
             vPC = newCodeBlock->instructions().begin();
 #if ENABLE(OPCODE_STATS)
             OpcodeStats::resetLastInstruction();
@@ -4030,19 +4531,21 @@ skip_id_custom_self:
         }
 
         if (constructType == ConstructTypeHost) {
-            ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
-
             ScopeChainNode* scopeChain = callFrame->scopeChain();
             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
-            newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
+            if (!registerFile->grow(newCallFrame->registers())) {
+                exceptionValue = createStackOverflowError(callFrame);
+                goto vm_throw;
+            }
+            newCallFrame->init(0, vPC + OPCODE_LENGTH(op_construct), scopeChain, callFrame, argCount, asObject(v));
 
             JSValue returnValue;
             {
                 SamplingTool::HostCallRecord callRecord(m_sampler.get());
-                returnValue = constructData.native.function(newCallFrame, asObject(v), args);
+                returnValue = JSValue::decode(constructData.native.function(newCallFrame));
             }
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = JSValue(returnValue);
+            functionReturnValue = returnValue;
 
             vPC += OPCODE_LENGTH(op_construct);
             NEXT_INSTRUCTION();
@@ -4050,34 +4553,23 @@ skip_id_custom_self:
 
         ASSERT(constructType == ConstructTypeNone);
 
-        exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+        exceptionValue = createNotAConstructorError(callFrame, v);
         goto vm_throw;
     }
-    DEFINE_OPCODE(op_construct_verify) {
-        /* construct_verify dst(r) override(r)
+    DEFINE_OPCODE(op_strcat) {
+        /* strcat dst(r) src(r) count(n)
 
-           Verifies that register dst holds an object. If not, moves
-           the object in register override to register dst.
+           Construct a new String instance using the original
+           constructor, and puts the result in register dst.
+           The string will be the result of concatenating count
+           strings with values taken from registers starting at
+           register src.
         */
-
-        int dst = vPC[1].u.operand;
-        if (LIKELY(callFrame->r(dst).jsValue().isObject())) {
-            vPC += OPCODE_LENGTH(op_construct_verify);
-            NEXT_INSTRUCTION();
-        }
-
-        int override = vPC[2].u.operand;
-        callFrame->r(dst) = callFrame->r(override);
-
-        vPC += OPCODE_LENGTH(op_construct_verify);
-        NEXT_INSTRUCTION();
-    }
-    DEFINE_OPCODE(op_strcat) {
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
         int count = vPC[3].u.operand;
 
-        callFrame->r(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
+        callFrame->uncheckedR(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count);
         CHECK_FOR_EXCEPTION();
         vPC += OPCODE_LENGTH(op_strcat);
 
@@ -4087,7 +4579,7 @@ skip_id_custom_self:
         int dst = vPC[1].u.operand;
         int src = vPC[2].u.operand;
 
-        callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
+        callFrame->uncheckedR(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame);
         vPC += OPCODE_LENGTH(op_to_primitive);
 
         NEXT_INSTRUCTION();
@@ -4104,7 +4596,7 @@ skip_id_custom_self:
         JSObject* o = v.toObject(callFrame);
         CHECK_FOR_EXCEPTION();
 
-        callFrame->r(scope) = JSValue(o);
+        callFrame->uncheckedR(scope) = JSValue(o);
         callFrame->setScopeChain(callFrame->scopeChain()->push(o));
 
         vPC += OPCODE_LENGTH(op_push_scope);
@@ -4145,10 +4637,10 @@ skip_id_custom_self:
         if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame))
             jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o);
 
-        callFrame->r(dst) = jsPropertyNameIterator;
-        callFrame->r(base) = JSValue(o);
-        callFrame->r(i) = Register::withInt(0);
-        callFrame->r(size) = Register::withInt(jsPropertyNameIterator->size());
+        callFrame->uncheckedR(dst) = jsPropertyNameIterator;
+        callFrame->uncheckedR(base) = JSValue(o);
+        callFrame->uncheckedR(i) = Register::withInt(0);
+        callFrame->uncheckedR(size) = Register::withInt(jsPropertyNameIterator->size());
         vPC += OPCODE_LENGTH(op_get_pnames);
         NEXT_INSTRUCTION();
     }
@@ -4170,10 +4662,11 @@ skip_id_custom_self:
         JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator();
         while (callFrame->r(i).i() != callFrame->r(size).i()) {
             JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i());
-            callFrame->r(i) = Register::withInt(callFrame->r(i).i() + 1);
+            CHECK_FOR_EXCEPTION();
+            callFrame->uncheckedR(i) = Register::withInt(callFrame->r(i).i() + 1);
             if (key) {
                 CHECK_FOR_TIMEOUT();
-                callFrame->r(dst) = key;
+                callFrame->uncheckedR(dst) = key;
                 vPC += target;
                 NEXT_INSTRUCTION();
             }
@@ -4229,7 +4722,7 @@ skip_id_custom_self:
         ASSERT(exceptionValue);
         ASSERT(!globalData->exception);
         int ex = vPC[1].u.operand;
-        callFrame->r(ex) = exceptionValue;
+        callFrame->uncheckedR(ex) = exceptionValue;
         exceptionValue = JSValue();
 
         vPC += OPCODE_LENGTH(op_catch);
@@ -4249,32 +4742,24 @@ skip_id_custom_self:
         int ex = vPC[1].u.operand;
         exceptionValue = callFrame->r(ex).jsValue();
 
-        handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true);
-        if (!handler) {
-            *exception = exceptionValue;
-            return jsNull();
-        }
+        handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin());
+        if (!handler)
+            return throwError(callFrame, exceptionValue);
 
-        vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
+        codeBlock = callFrame->codeBlock();
+        vPC = codeBlock->instructions().begin() + handler->target;
         NEXT_INSTRUCTION();
     }
-    DEFINE_OPCODE(op_new_error) {
-        /* new_error dst(r) type(n) message(k)
+    DEFINE_OPCODE(op_throw_reference_error) {
+        /* op_throw_reference_error message(k)
 
-           Constructs a new Error instance using the original
-           constructor, using immediate number n as the type and
-           constant message as the message string. The result is
-           written to register dst.
+           Constructs a new reference Error instance using the
+           original constructor, using constant message as the
+           message string. The result is thrown.
         */
-        int dst = vPC[1].u.operand;
-        int type = vPC[2].u.operand;
-        int message = vPC[3].u.operand;
-
-        CodeBlock* codeBlock = callFrame->codeBlock();
-        callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()));
-
-        vPC += OPCODE_LENGTH(op_new_error);
-        NEXT_INSTRUCTION();
+        UString message = callFrame->r(vPC[1].u.operand).jsValue().toString(callFrame);
+        exceptionValue = JSValue(createReferenceError(callFrame, message));
+        goto vm_throw;
     }
     DEFINE_OPCODE(op_end) {
         /* end result(r)
@@ -4283,11 +4768,6 @@ skip_id_custom_self:
            program. Return control to the calling native code.
         */
 
-        if (callFrame->codeBlock()->needsFullScopeChain()) {
-            ScopeChainNode* scopeChain = callFrame->scopeChain();
-            ASSERT(scopeChain->refCount > 1);
-            scopeChain->deref();
-        }
         int result = vPC[1].u.operand;
         return callFrame->r(result).jsValue();
     }
@@ -4308,7 +4788,7 @@ skip_id_custom_self:
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
-        Identifier& ident = callFrame->codeBlock()->identifier(property);
+        Identifier& ident = codeBlock->identifier(property);
         ASSERT(callFrame->r(function).jsValue().isObject());
         baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
 
@@ -4332,7 +4812,7 @@ skip_id_custom_self:
 
         ASSERT(callFrame->r(base).jsValue().isObject());
         JSObject* baseObj = asObject(callFrame->r(base).jsValue());
-        Identifier& ident = callFrame->codeBlock()->identifier(property);
+        Identifier& ident = codeBlock->identifier(property);
         ASSERT(callFrame->r(function).jsValue().isObject());
         baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
 
@@ -4417,13 +4897,16 @@ skip_id_custom_self:
             // cannot fathom if we don't assign to the exceptionValue before branching)
             exceptionValue = createInterruptedExecutionException(globalData);
         }
-        handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), false);
+        JSGlobalObject* globalObject = callFrame->lexicalGlobalObject();
+        handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin());
         if (!handler) {
-            *exception = exceptionValue;
-            return jsNull();
+            // Can't use the callframe at this point as the scopechain, etc have
+            // been released.
+            return throwError(globalObject->globalExec(), exceptionValue);
         }
 
-        vPC = callFrame->codeBlock()->instructions().begin() + handler->target;
+        codeBlock = callFrame->codeBlock();
+        vPC = codeBlock->instructions().begin() + handler->target;
         NEXT_INSTRUCTION();
     }
     }
@@ -4446,27 +4929,22 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio
     CodeBlock* codeBlock = functionCallFrame->codeBlock();
     if (codeBlock->usesArguments()) {
         ASSERT(codeBlock->codeType() == FunctionCode);
-        SymbolTable& symbolTable = *codeBlock->symbolTable();
-        int argumentsIndex = symbolTable.get(functionCallFrame->propertyNames().arguments.ustring().rep()).getIndex();
-        if (!functionCallFrame->r(argumentsIndex).jsValue()) {
-            Arguments* arguments = new (callFrame) Arguments(functionCallFrame);
-            functionCallFrame->setCalleeArguments(arguments);
-            functionCallFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments);
-        }
-        return functionCallFrame->r(argumentsIndex).jsValue();
-    }
-
-    Arguments* arguments = functionCallFrame->optionalCalleeArguments();
-    if (!arguments) {
-        arguments = new (functionCallFrame) Arguments(functionCallFrame);
-        arguments->copyRegisters();
-        callFrame->setCalleeArguments(arguments);
-    }
-
+        int argumentsRegister = codeBlock->argumentsRegister();
+        int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
+        if (JSValue arguments = functionCallFrame->uncheckedR(argumentsRegister).jsValue())
+            return arguments;
+        JSValue arguments = JSValue(new (callFrame) Arguments(functionCallFrame));
+        functionCallFrame->r(argumentsRegister) = arguments;
+        functionCallFrame->r(realArgumentsRegister) = arguments;
+        return arguments;
+    }
+
+    Arguments* arguments = new (functionCallFrame) Arguments(functionCallFrame);
+    arguments->copyRegisters(functionCallFrame->globalData());
     return arguments;
 }
 
-JSValue Interpreter::retrieveCaller(CallFrame* callFrame, InternalFunction* function) const
+JSValue Interpreter::retrieveCaller(CallFrame* callFrame, JSFunction* function) const
 {
     CallFrame* functionCallFrame = findFunctionCallFrame(callFrame, function);
     if (!functionCallFrame)
@@ -4499,21 +4977,21 @@ void Interpreter::retrieveLastCaller(CallFrame* callFrame, int& lineNumber, intp
     unsigned bytecodeOffset = 0;
 #if ENABLE(INTERPRETER)
     if (!callerFrame->globalData().canUseJIT())
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnVPC());
+        bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnVPC());
 #if ENABLE(JIT)
     else
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
+        bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
 #endif
 #else
-    bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
+    bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
 #endif
-    lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
+    lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
     sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
     function = callerFrame->callee();
 }
 
-CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunction* function)
+CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, JSFunction* function)
 {
     for (CallFrame* candidate = callFrame; candidate; candidate = candidate->callerFrame()->removeHostCallFrameFlag()) {
         if (candidate->callee() == function)
index 2bcc82ffdfaa06935ce25c1389320ab9b657c6d1..9a4352e7a9d764c1c9aea9910d34729f97d6d8a8 100644 (file)
@@ -30,7 +30,6 @@
 #define Interpreter_h
 
 #include "ArgList.h"
-#include "FastAllocBase.h"
 #include "JSCell.h"
 #include "JSValue.h"
 #include "JSObject.h"
@@ -44,7 +43,6 @@ namespace JSC {
     class CodeBlock;
     class EvalExecutable;
     class FunctionExecutable;
-    class InternalFunction;
     class JSFunction;
     class JSGlobalObject;
     class ProgramExecutable;
@@ -66,13 +64,14 @@ namespace JSC {
 
     // We use a smaller reentrancy limit on iPhone because of the high amount of
     // stack space required on the web thread.
-    enum { MaxLargeThreadReentryDepth = 100, MaxSmallThreadReentryDepth = 32 };
+    enum { MaxLargeThreadReentryDepth = 93, MaxSmallThreadReentryDepth = 32 };
 
-    class Interpreter : public FastAllocBase {
+    class Interpreter {
+        WTF_MAKE_FAST_ALLOCATED;
         friend class JIT;
         friend class CachedCall;
     public:
-        Interpreter();
+        Interpreter(JSGlobalData&);
 
         RegisterFile& registerFile() { return m_registerFile; }
         
@@ -96,21 +95,22 @@ namespace JSC {
         }
 
         bool isOpcode(Opcode);
-        
-        JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
-        JSValue execute(FunctionExecutable*, CallFrame*, JSFunction*, JSObject* thisObj, const ArgList& args, ScopeChainNode*, JSValue* exception);
-        JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
+
+        JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj);
+        JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
+        JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
+        JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain);
 
         JSValue retrieveArguments(CallFrame*, JSFunction*) const;
-        JSValue retrieveCaller(CallFrame*, InternalFunction*) const;
+        JSValue retrieveCaller(CallFrame*, JSFunction*) const;
         void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const;
         
         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
         
         SamplingTool* sampler() { return m_sampler.get(); }
 
-        NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue);
-        NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool);
+        NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset);
+        NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset);
         NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
 
         void dumpSampleData(ExecState* exec);
@@ -119,11 +119,11 @@ namespace JSC {
     private:
         enum ExecutionFlag { Normal, InitializeAndReturn };
 
-        CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*, JSValue* exception);
+        CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*);
         void endRepeatCall(CallFrameClosure&);
-        JSValue execute(CallFrameClosure&, JSValue* exception);
+        JSValue execute(CallFrameClosure&);
 
-        JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
+        JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*);
 
 #if ENABLE(INTERPRETER)
         NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
@@ -144,9 +144,9 @@ namespace JSC {
 
         static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc);
 
-        static CallFrame* findFunctionCallFrame(CallFrame*, InternalFunction*);
+        static CallFrame* findFunctionCallFrame(CallFrame*, JSFunction*);
 
-        JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue* exception);
+        JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*);
 
         void dumpCallFrame(CallFrame*);
         void dumpRegisters(CallFrame*);
index ecd7403246a2eb3952071392623a18766ded561e..fb02c12089b21ad3dcc1a4e99d862865b74d5123 100644 (file)
 
 #include "JSValue.h"
 #include <wtf/Assertions.h>
-#include <wtf/FastAllocBase.h>
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
 
-    class Arguments;
     class CodeBlock;
     class ExecState;
     class JSActivation;
-    class JSFunction;
+    class JSObject;
     class JSPropertyNameIterator;
     class ScopeChainNode;
 
@@ -48,50 +46,43 @@ namespace JSC {
 
     typedef ExecState CallFrame;
 
-    class Register : public WTF::FastAllocBase {
+    class Register {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         Register();
 
         Register(const JSValue&);
         Register& operator=(const JSValue&);
         JSValue jsValue() const;
+        EncodedJSValue encodedJSValue() const;
         
-        Register& operator=(JSActivation*);
         Register& operator=(CallFrame*);
         Register& operator=(CodeBlock*);
-        Register& operator=(JSFunction*);
-        Register& operator=(JSPropertyNameIterator*);
         Register& operator=(ScopeChainNode*);
         Register& operator=(Instruction*);
 
         int32_t i() const;
         JSActivation* activation() const;
-        Arguments* arguments() const;
         CallFrame* callFrame() const;
         CodeBlock* codeBlock() const;
-        JSFunction* function() const;
+        JSObject* function() const;
         JSPropertyNameIterator* propertyNameIterator() const;
         ScopeChainNode* scopeChain() const;
         Instruction* vPC() const;
 
         static Register withInt(int32_t i)
         {
-            Register r;
-            r.u.i = i;
+            Register r = jsNumber(i);
             return r;
         }
 
+        static inline Register withCallee(JSObject* callee);
+
     private:
         union {
-            int32_t i;
             EncodedJSValue value;
-
-            JSActivation* activation;
             CallFrame* callFrame;
             CodeBlock* codeBlock;
-            JSFunction* function;
-            JSPropertyNameIterator* propertyNameIterator;
-            ScopeChainNode* scopeChain;
             Instruction* vPC;
         } u;
     };
@@ -125,14 +116,13 @@ namespace JSC {
         return JSValue::decode(u.value);
     }
 
-    // Interpreter functions
-
-    ALWAYS_INLINE Register& Register::operator=(JSActivation* activation)
+    ALWAYS_INLINE EncodedJSValue Register::encodedJSValue() const
     {
-        u.activation = activation;
-        return *this;
+        return u.value;
     }
 
+    // Interpreter functions
+
     ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame)
     {
         u.callFrame = callFrame;
@@ -145,40 +135,17 @@ namespace JSC {
         return *this;
     }
 
-    ALWAYS_INLINE Register& Register::operator=(JSFunction* function)
-    {
-        u.function = function;
-        return *this;
-    }
-
     ALWAYS_INLINE Register& Register::operator=(Instruction* vPC)
     {
         u.vPC = vPC;
         return *this;
     }
 
-    ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
-    {
-        u.scopeChain = scopeChain;
-        return *this;
-    }
-
-    ALWAYS_INLINE Register& Register::operator=(JSPropertyNameIterator* propertyNameIterator)
-    {
-        u.propertyNameIterator = propertyNameIterator;
-        return *this;
-    }
-
     ALWAYS_INLINE int32_t Register::i() const
     {
-        return u.i;
+        return jsValue().asInt32();
     }
-    
-    ALWAYS_INLINE JSActivation* Register::activation() const
-    {
-        return u.activation;
-    }
-    
+
     ALWAYS_INLINE CallFrame* Register::callFrame() const
     {
         return u.callFrame;
@@ -188,22 +155,7 @@ namespace JSC {
     {
         return u.codeBlock;
     }
-    
-    ALWAYS_INLINE JSFunction* Register::function() const
-    {
-        return u.function;
-    }
-    
-    ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
-    {
-        return u.propertyNameIterator;
-    }
-    
-    ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
-    {
-        return u.scopeChain;
-    }
-    
+
     ALWAYS_INLINE Instruction* Register::vPC() const
     {
         return u.vPC;
index 63ea5b371c4e5af90743aa44eed59db63b0fc000..e3b34bb08a40c5b0692c3e23a6b7be0aff0c7f11 100644 (file)
 #include "config.h"
 #include "RegisterFile.h"
 
+#include "ConservativeRoots.h"
+#include "Interpreter.h"
+#include "JSGlobalData.h"
 #include "JSGlobalObject.h"
 
 namespace JSC {
 
+static size_t committedBytesCount = 0;
+
+static Mutex& registerFileStatisticsMutex()
+{
+    DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
+    return staticMutex;
+}    
+    
 RegisterFile::~RegisterFile()
 {
-#if HAVE(MMAP)
-    munmap(m_buffer, ((m_max - m_start) + m_maxGlobals) * sizeof(Register));
-#elif HAVE(VIRTUALALLOC)
-#if OS(WINCE)
-    VirtualFree(m_buffer, DWORD(m_commitEnd) - DWORD(m_buffer), MEM_DECOMMIT);
-#endif
-    VirtualFree(m_buffer, 0, MEM_RELEASE);
-#else
-    fastFree(m_buffer);
-#endif
+    void* base = m_reservation.base();
+    m_reservation.decommit(base, reinterpret_cast<intptr_t>(m_commitEnd) - reinterpret_cast<intptr_t>(base));
+    addToCommittedByteCount(-(reinterpret_cast<intptr_t>(m_commitEnd) - reinterpret_cast<intptr_t>(base)));
+    m_reservation.deallocate();
+}
+
+void RegisterFile::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
+{
+    for (Register* it = start(); it != end(); ++it) {
+        JSValue v = it->jsValue();
+        if (!v.isCell())
+            continue;
+        conservativeRoots.add(v.asCell());
+    }
 }
 
 void RegisterFile::releaseExcessCapacity()
 {
-#if HAVE(MMAP) && HAVE(MADV_FREE) && !HAVE(VIRTUALALLOC)
-    while (madvise(m_start, (m_max - m_start) * sizeof(Register), MADV_FREE) == -1 && errno == EAGAIN) { }
-#elif HAVE(VIRTUALALLOC)
-    VirtualFree(m_start, (m_max - m_start) * sizeof(Register), MEM_DECOMMIT);
+    m_reservation.decommit(m_start, reinterpret_cast<intptr_t>(m_commitEnd) - reinterpret_cast<intptr_t>(m_start));
+    addToCommittedByteCount(-(reinterpret_cast<intptr_t>(m_commitEnd) - reinterpret_cast<intptr_t>(m_start)));
     m_commitEnd = m_start;
-#endif
     m_maxUsed = m_start;
 }
 
 void RegisterFile::setGlobalObject(JSGlobalObject* globalObject)
 {
-    m_globalObject = globalObject;
+    m_globalObject.set(globalObject->globalData(), globalObject, &m_globalObjectOwner, this);
 }
 
-bool RegisterFile::clearGlobalObject(JSGlobalObject* globalObject)
+JSGlobalObject* RegisterFile::globalObject()
 {
-    return m_globalObject.clear(globalObject);
+    return m_globalObject.get();
 }
 
-JSGlobalObject* RegisterFile::globalObject()
+void RegisterFile::initializeThreading()
 {
-    return m_globalObject.get();
+    registerFileStatisticsMutex();
+}
+
+size_t RegisterFile::committedByteCount()
+{
+    MutexLocker locker(registerFileStatisticsMutex());
+    return committedBytesCount;
+}
+
+void RegisterFile::addToCommittedByteCount(long byteCount)
+{
+    MutexLocker locker(registerFileStatisticsMutex());
+    ASSERT(static_cast<long>(committedBytesCount) + byteCount > -1);
+    committedBytesCount += byteCount;
 }
 
 } // namespace JSC
index def9e2549195a0def3c7374cd490fc5984986485..f59c13a1b5327e7e4cf25f79c9c8b1cc1f6fed69 100644 (file)
 #ifndef RegisterFile_h
 #define RegisterFile_h
 
-#include "Collector.h"
+#include "Heap.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
-#include "WeakGCPtr.h"
+#include "Weak.h"
 #include <stdio.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
-#if HAVE(MMAP)
-#include <errno.h>
-#include <sys/mman.h>
-#endif
-
 namespace JSC {
 
 /*
@@ -93,40 +89,38 @@ namespace JSC {
 
     class JSGlobalObject;
 
-    class RegisterFile : public Noncopyable {
-        friend class JIT;
+    class RegisterFile {
+        WTF_MAKE_NONCOPYABLE(RegisterFile);
     public:
         enum CallFrameHeaderEntry {
-            CallFrameHeaderSize = 8,
-
-            CodeBlock = -8,
-            ScopeChain = -7,
-            CallerFrame = -6,
-            ReturnPC = -5, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
-            ReturnValueRegister = -4,
-            ArgumentCount = -3,
-            Callee = -2,
-            OptionalCalleeArguments = -1,
+            CallFrameHeaderSize = 6,
+
+            ArgumentCount = -6,
+            CallerFrame = -5,
+            Callee = -4,
+            ScopeChain = -3,
+            ReturnPC = -2, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
+            CodeBlock = -1,
         };
 
         enum { ProgramCodeThisRegister = -CallFrameHeaderSize - 1 };
-        enum { ArgumentsRegister = 0 };
 
-        static const size_t defaultCapacity = 524288;
-        static const size_t defaultMaxGlobals = 8192;
-        static const size_t commitSize = 1 << 14;
+        static const size_t defaultCapacity = 512 * 1024;
+        static const size_t defaultMaxGlobals = 8 * 1024;
+        static const size_t commitSize = 16 * 1024;
         // Allow 8k of excess registers before we start trying to reap the registerfile
         static const ptrdiff_t maxExcessCapacity = 8 * 1024;
 
-        RegisterFile(size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals);
+        RegisterFile(JSGlobalData&, size_t capacity = defaultCapacity, size_t maxGlobals = defaultMaxGlobals);
         ~RegisterFile();
+        
+        void gatherConservativeRoots(ConservativeRoots&);
 
         Register* start() const { return m_start; }
         Register* end() const { return m_end; }
         size_t size() const { return m_end - m_start; }
 
         void setGlobalObject(JSGlobalObject*);
-        bool clearGlobalObject(JSGlobalObject*);
         JSGlobalObject* globalObject();
 
         bool grow(Register* newEnd);
@@ -138,85 +132,53 @@ namespace JSC {
 
         Register* lastGlobal() const { return m_start - m_numGlobals; }
         
-        void markGlobals(MarkStack& markStack, Heap* heap) { heap->markConservatively(markStack, lastGlobal(), m_start); }
-        void markCallFrames(MarkStack& markStack, Heap* heap) { heap->markConservatively(markStack, m_start, m_end); }
+        static size_t committedByteCount();
+        static void initializeThreading();
+
+        Register* const * addressOfEnd() const
+        {
+            return &m_end;
+        }
 
     private:
         void releaseExcessCapacity();
+        void addToCommittedByteCount(long);
         size_t m_numGlobals;
         const size_t m_maxGlobals;
         Register* m_start;
         Register* m_end;
         Register* m_max;
-        Register* m_buffer;
         Register* m_maxUsed;
-
-#if HAVE(VIRTUALALLOC)
         Register* m_commitEnd;
-#endif
+        PageReservation m_reservation;
 
-        WeakGCPtr<JSGlobalObject> m_globalObject; // The global object whose vars are currently stored in the register file.
+        Weak<JSGlobalObject> m_globalObject; // The global object whose vars are currently stored in the register file.
+        class GlobalObjectOwner : public WeakHandleOwner {
+            virtual void finalize(Handle<Unknown>, void* context)
+            {
+                static_cast<RegisterFile*>(context)->setNumGlobals(0);
+            }
+        } m_globalObjectOwner;
     };
 
-    // FIXME: Add a generic getpagesize() to WTF, then move this function to WTF as well.
-    inline bool isPageAligned(size_t size) { return size != 0 && size % (8 * 1024) == 0; }
-
-    inline RegisterFile::RegisterFile(size_t capacity, size_t maxGlobals)
+    inline RegisterFile::RegisterFile(JSGlobalData& globalData, size_t capacity, size_t maxGlobals)
         : m_numGlobals(0)
         , m_maxGlobals(maxGlobals)
         , m_start(0)
         , m_end(0)
         , m_max(0)
-        , m_buffer(0)
+        , m_globalObject(globalData, 0, &m_globalObjectOwner, this)
     {
-        // Verify that our values will play nice with mmap and VirtualAlloc.
-        ASSERT(isPageAligned(maxGlobals));
-        ASSERT(isPageAligned(capacity));
-
+        ASSERT(maxGlobals && isPageAligned(maxGlobals));
+        ASSERT(capacity && isPageAligned(capacity));
         size_t bufferLength = (capacity + maxGlobals) * sizeof(Register);
-    #if HAVE(MMAP)
-        m_buffer = static_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, VM_TAG_FOR_REGISTERFILE_MEMORY, 0));
-        if (m_buffer == MAP_FAILED) {
-#if OS(WINCE)
-            fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
-#else
-            fprintf(stderr, "Could not allocate register file: %d\n", errno);
-#endif
-            CRASH();
-        }
-    #elif HAVE(VIRTUALALLOC)
-        m_buffer = static_cast<Register*>(VirtualAlloc(0, roundUpAllocationSize(bufferLength, commitSize), MEM_RESERVE, PAGE_READWRITE));
-        if (!m_buffer) {
-#if OS(WINCE)
-            fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
-#else
-            fprintf(stderr, "Could not allocate register file: %d\n", errno);
-#endif
-            CRASH();
-        }
+        m_reservation = PageReservation::reserve(roundUpAllocationSize(bufferLength, commitSize), OSAllocator::JSVMStackPages);
+        void* base = m_reservation.base();
         size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize);
-        void* commitCheck = VirtualAlloc(m_buffer, committedSize, MEM_COMMIT, PAGE_READWRITE);
-        if (commitCheck != m_buffer) {
-#if OS(WINCE)
-            fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
-#else
-            fprintf(stderr, "Could not allocate register file: %d\n", errno);
-#endif
-            CRASH();
-        }
-        m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_buffer) + committedSize);
-    #else 
-        /* 
-         * If neither MMAP nor VIRTUALALLOC are available - use fastMalloc instead.
-         *
-         * Please note that this is the fallback case, which is non-optimal.
-         * If any possible, the platform should provide for a better memory
-         * allocation mechanism that allows for "lazy commit" or dynamic
-         * pre-allocation, similar to mmap or VirtualAlloc, to avoid waste of memory.
-         */
-        m_buffer = static_cast<Register*>(fastMalloc(bufferLength));
-    #endif
-        m_start = m_buffer + maxGlobals;
+        m_reservation.commit(base, committedSize);
+        addToCommittedByteCount(static_cast<long>(committedSize));
+        m_commitEnd = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(base) + committedSize);
+        m_start = static_cast<Register*>(base) + maxGlobals;
         m_end = m_start;
         m_maxUsed = m_end;
         m_max = m_start + capacity;
@@ -239,20 +201,12 @@ namespace JSC {
         if (newEnd > m_max)
             return false;
 
-#if !HAVE(MMAP) && HAVE(VIRTUALALLOC)
         if (newEnd > m_commitEnd) {
             size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize);
-            if (!VirtualAlloc(m_commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) {
-#if OS(WINCE)
-                fprintf(stderr, "Could not allocate register file: %d\n", GetLastError());
-#else
-                fprintf(stderr, "Could not allocate register file: %d\n", errno);
-#endif
-                CRASH();
-            }
-            m_commitEnd = reinterpret_cast<Register*>(reinterpret_cast<char*>(m_commitEnd) + size);
+            m_reservation.commit(m_commitEnd, size);
+            addToCommittedByteCount(static_cast<long>(size));
+            m_commitEnd = reinterpret_cast_ptr<Register*>(reinterpret_cast<char*>(m_commitEnd) + size);
         }
-#endif
 
         if (newEnd > m_maxUsed)
             m_maxUsed = newEnd;
index 5e10e863d49f6ddd899a33709c0540dfa94aa125..35531d92ed08db71ee0bb6ff0cb005b4bbd089bf 100644 (file)
@@ -33,8 +33,59 @@ namespace JSC {
 
 size_t ExecutableAllocator::pageSize = 0;
 
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+
+void ExecutableAllocator::intializePageSize()
+{
+#if OS(SYMBIAN) && CPU(ARMV5_OR_LOWER)
+    // The moving memory model (as used in ARMv5 and earlier platforms)
+    // on Symbian OS limits the number of chunks for each process to 16. 
+    // To mitigate this limitation increase the pagesize to allocate
+    // fewer, larger chunks. Set the page size to 256 Kb to compensate
+    // for moving memory model limitation
+    ExecutableAllocator::pageSize = 256 * 1024;
+#else
+    ExecutableAllocator::pageSize = WTF::pageSize();
+#endif
+}
+
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
+{
+    PageAllocation allocation = PageAllocation::allocate(size, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+    if (!allocation)
+        CRASH();
+    return allocation;
+}
+
+void ExecutablePool::systemRelease(ExecutablePool::Allocation& allocation)
+{
+    allocation.deallocate();
+}
+
+bool ExecutableAllocator::isValid() const
+{
+    return true;
+}
+    
+bool ExecutableAllocator::underMemoryPressure()
+{
+    return false;
+}
+    
+size_t ExecutableAllocator::committedByteCount()
+{
+    return 0;
+} 
+
+#endif
+
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
-void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting)
+
+#if OS(WINDOWS) || OS(SYMBIAN)
+#error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
+#endif
+
+void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSetting setting)
 {
     if (!pageSize)
         intializePageSize();
@@ -52,9 +103,11 @@ void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSe
 
     mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
 }
+
 #endif
 
 #if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
+
 __asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
 {
     ARM
@@ -67,6 +120,7 @@ __asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
     pop {r7}
     bx lr
 }
+
 #endif
 
 }
index 62d708d8e69d8c8b47099b1e83c9a36a14583372..be315c70e8162cdac730e39fa9eddd9d5ef71b02 100644 (file)
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
-
 #include <stddef.h> // for ptrdiff_t
 #include <limits>
 #include <wtf/Assertions.h>
+#include <wtf/PageAllocation.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/UnusedParam.h>
 #include <wtf/Vector.h>
 
-#if OS(IPHONE_OS)
+#if OS(IOS)
 #include <libkern/OSCacheControl.h>
 #include <sys/mman.h>
 #endif
 #include <sys/cachectl.h>
 #endif
 
+#if CPU(SH4) && OS(LINUX)
+#include <asm/cachectl.h>
+#include <asm/unistd.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#endif
+
 #if OS(WINCE)
 // From pkfuncs.h (private header file from the Platform Builder)
 #define CACHE_SYNC_ALL 0x07F
 extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags);
 #endif
 
+#if PLATFORM(BREWMP)
+#include <AEEIMemCache1.h>
+#include <AEEMemCache1.bid>
+#include <wtf/brew/RefPtrBrew.h>
+#endif
+
 #define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
 #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4)
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 #define PROTECTION_FLAGS_RW (PROT_READ | PROT_WRITE)
 #define PROTECTION_FLAGS_RX (PROT_READ | PROT_EXEC)
-#define INITIAL_PROTECTION_FLAGS PROTECTION_FLAGS_RX
+#define EXECUTABLE_POOL_WRITABLE false
 #else
-#define INITIAL_PROTECTION_FLAGS (PROT_READ | PROT_WRITE | PROT_EXEC)
+#define EXECUTABLE_POOL_WRITABLE true
 #endif
 
 namespace JSC {
@@ -80,28 +93,42 @@ inline size_t roundUpAllocationSize(size_t request, size_t granularity)
 
 }
 
-#if ENABLE(ASSEMBLER)
+#if ENABLE(JIT) && ENABLE(ASSEMBLER)
 
 namespace JSC {
 
+class JSGlobalData;
+void releaseExecutableMemory(JSGlobalData&);
+
 class ExecutablePool : public RefCounted<ExecutablePool> {
-private:
-    struct Allocation {
-        char* pages;
-        size_t size;
-#if OS(SYMBIAN)
-        RChunk* chunk;
-#endif
+public:
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+    typedef PageAllocation Allocation;
+#else
+    class Allocation {
+    public:
+        Allocation(void* base, size_t size)
+            : m_base(base)
+            , m_size(size)
+        {
+        }
+        void* base() { return m_base; }
+        size_t size() { return m_size; }
+        bool operator!() const { return !m_base; }
+
+    private:
+        void* m_base;
+        size_t m_size;
     };
+#endif
     typedef Vector<Allocation, 2> AllocationList;
 
-public:
-    static PassRefPtr<ExecutablePool> create(size_t n)
+    static PassRefPtr<ExecutablePool> create(JSGlobalData& globalData, size_t n)
     {
-        return adoptRef(new ExecutablePool(n));
+        return adoptRef(new ExecutablePool(globalData, n));
     }
 
-    void* alloc(size_t n)
+    void* alloc(JSGlobalData& globalData, size_t n)
     {
         ASSERT(m_freePtr <= m_end);
 
@@ -117,7 +144,7 @@ public:
 
         // Insufficient space to allocate in the existing pool
         // so we need allocate into a new pool
-        return poolAllocate(n);
+        return poolAllocate(globalData, n);
     }
     
     void tryShrink(void* allocation, size_t oldSize, size_t newSize)
@@ -129,22 +156,20 @@ public:
 
     ~ExecutablePool()
     {
-        AllocationList::const_iterator end = m_pools.end();
-        for (AllocationList::const_iterator ptr = m_pools.begin(); ptr != end; ++ptr)
+        AllocationList::iterator end = m_pools.end();
+        for (AllocationList::iterator ptr = m_pools.begin(); ptr != end; ++ptr)
             ExecutablePool::systemRelease(*ptr);
     }
 
     size_t available() const { return (m_pools.size() > 1) ? 0 : m_end - m_freePtr; }
 
-    static bool underMemoryPressure();
-
 private:
     static Allocation systemAlloc(size_t n);
-    static void systemRelease(const Allocation& alloc);
+    static void systemRelease(Allocation& alloc);
 
-    ExecutablePool(size_t n);
+    ExecutablePool(JSGlobalData&, size_t n);
 
-    void* poolAllocate(size_t n);
+    void* poolAllocate(JSGlobalData&, size_t n);
 
     char* m_freePtr;
     char* m_end;
@@ -152,16 +177,16 @@ private:
 };
 
 class ExecutableAllocator {
-    enum ProtectionSeting { Writable, Executable };
+    enum ProtectionSetting { Writable, Executable };
 
 public:
     static size_t pageSize;
-    ExecutableAllocator()
+    ExecutableAllocator(JSGlobalData& globalData)
     {
         if (!pageSize)
             intializePageSize();
         if (isValid())
-            m_smallAllocationPool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
+            m_smallAllocationPool = ExecutablePool::create(globalData, JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
 #if !ENABLE(INTERPRETER)
         else
             CRASH();
@@ -169,8 +194,10 @@ public:
     }
 
     bool isValid() const;
-    
-    PassRefPtr<ExecutablePool> poolForSize(size_t n)
+
+    static bool underMemoryPressure();
+
+    PassRefPtr<ExecutablePool> poolForSize(JSGlobalData& globalData, size_t n)
     {
         // Try to fit in the existing small allocator
         ASSERT(m_smallAllocationPool);
@@ -179,10 +206,10 @@ public:
 
         // If the request is large, we just provide a unshared allocator
         if (n > JIT_ALLOCATOR_LARGE_ALLOC_SIZE)
-            return ExecutablePool::create(n);
+            return ExecutablePool::create(globalData, n);
 
         // Create a new allocator
-        RefPtr<ExecutablePool> pool = ExecutablePool::create(JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
+        RefPtr<ExecutablePool> pool = ExecutablePool::create(globalData, JIT_ALLOCATOR_LARGE_ALLOC_SIZE);
 
         // If the new allocator will result in more free space than in
         // the current small allocator, then we will use it instead
@@ -214,8 +241,8 @@ public:
 #elif CPU(MIPS)
     static void cacheFlush(void* code, size_t size)
     {
-#if COMPILER(GCC) && (GCC_VERSION >= 40300)
-#if WTF_MIPS_ISA_REV(2) && (GCC_VERSION < 40403)
+#if GCC_VERSION_AT_LEAST(4, 3, 0)
+#if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4, 4, 3)
         int lineSize;
         asm("rdhwr %0, $1" : "=r" (lineSize));
         //
@@ -237,11 +264,10 @@ public:
         _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
 #endif
     }
-#elif CPU(ARM_THUMB2) && OS(IPHONE_OS)
+#elif CPU(ARM_THUMB2) && OS(IOS)
     static void cacheFlush(void* code, size_t size)
     {
-        sys_dcache_flush(code, size);
-        sys_icache_invalidate(code, size);
+        sys_cache_control(kCacheFunctionPrepareForExecution, code, size);
     }
 #elif CPU(ARM_THUMB2) && OS(LINUX)
     static void cacheFlush(void* code, size_t size)
@@ -287,52 +313,88 @@ public:
     {
         CacheRangeFlush(code, size, CACHE_SYNC_ALL);
     }
+#elif PLATFORM(BREWMP)
+    static void cacheFlush(void* code, size_t size)
+    {
+        RefPtr<IMemCache1> memCache = createRefPtrInstance<IMemCache1>(AEECLSID_MemCache1);
+        IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_FLUSH, MEMSPACE_DATACACHE);
+        IMemCache1_ClearCache(memCache.get(), reinterpret_cast<uint32>(code), size, MEMSPACE_CACHE_INVALIDATE, MEMSPACE_INSTCACHE);
+    }
+#elif CPU(SH4) && OS(LINUX)
+    static void cacheFlush(void* code, size_t size)
+    {
+#ifdef CACHEFLUSH_D_L2
+        syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2);
+#else
+        syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I);
+#endif
+    }
 #else
     #error "The cacheFlush support is missing on this platform."
 #endif
+    static size_t committedByteCount();
 
 private:
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
-    static void reprotectRegion(void*, size_t, ProtectionSeting);
+    static void reprotectRegion(void*, size_t, ProtectionSetting);
 #endif
 
     RefPtr<ExecutablePool> m_smallAllocationPool;
     static void intializePageSize();
 };
 
-inline ExecutablePool::ExecutablePool(size_t n)
+inline ExecutablePool::ExecutablePool(JSGlobalData& globalData, size_t n)
 {
     size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE);
     Allocation mem = systemAlloc(allocSize);
+    if (!mem.base()) {
+        releaseExecutableMemory(globalData);
+        mem = systemAlloc(allocSize);
+    }
     m_pools.append(mem);
-    m_freePtr = mem.pages;
+    m_freePtr = static_cast<char*>(mem.base());
     if (!m_freePtr)
         CRASH(); // Failed to allocate
     m_end = m_freePtr + allocSize;
 }
 
-inline void* ExecutablePool::poolAllocate(size_t n)
+inline void* ExecutablePool::poolAllocate(JSGlobalData& globalData, size_t n)
 {
     size_t allocSize = roundUpAllocationSize(n, JIT_ALLOCATOR_PAGE_SIZE);
     
     Allocation result = systemAlloc(allocSize);
-    if (!result.pages)
-        CRASH(); // Failed to allocate
+    if (!result.base()) {
+        releaseExecutableMemory(globalData);
+        result = systemAlloc(allocSize);
+        if (!result.base())
+            CRASH(); // Failed to allocate
+    }
     
     ASSERT(m_end >= m_freePtr);
     if ((allocSize - n) > static_cast<size_t>(m_end - m_freePtr)) {
         // Replace allocation pool
-        m_freePtr = result.pages + n;
-        m_end = result.pages + allocSize;
+        m_freePtr = static_cast<char*>(result.base()) + n;
+        m_end = static_cast<char*>(result.base()) + allocSize;
     }
 
     m_pools.append(result);
-    return result.pages;
+    return result.base();
 }
 
 }
 
-#endif // ENABLE(ASSEMBLER)
+#else
+
+namespace JSC {
+
+class ExecutableAllocator {
+public: 
+    static size_t committedByteCount();
+};
+
+} // namespace JSC
+
+#endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
 
 #endif // !defined(ExecutableAllocator)
index 3048e20cdc8d5da0c4f1658a6680542c7e5e9fca..792e931497faaf73e1cee7e3077beaece67bd853 100644 (file)
 #include <sys/mman.h>
 #include <unistd.h>
 #include <wtf/AVLTree.h>
+#include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
+#if OS(LINUX)
+#include <stdio.h>
+#endif
+
     #define MMAP_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_JIT)
 
 using namespace WTF;
 
 namespace JSC {
-
+    
 #define TwoPow(n) (1ull << n)
 
 class AllocationTableSizeClass {
@@ -273,7 +278,7 @@ public:
                     // Mirror the suballocation's full bit.
                     if (m_suballocations[i].isFull())
                         m_full |= bit;
-                    return (i * subregionSize) + location;
+                    return (i * subregionSize) | location;
                 }
             }
             return notFound;
@@ -381,6 +386,7 @@ private:
     BitField m_hasSuballocation;
 };
 
+
 typedef AllocationTableLeaf<6> PageTables256KB;
 typedef AllocationTableDirectory<PageTables256KB, 6> PageTables16MB;
 typedef AllocationTableDirectory<LazyAllocationTable<PageTables16MB>, 1> PageTables32MB;
@@ -388,103 +394,75 @@ typedef AllocationTableDirectory<LazyAllocationTable<PageTables16MB>, 6> PageTab
 
 #if CPU(ARM)
 typedef PageTables16MB FixedVMPoolPageTables;
-#elif CPU(X86_64) && !OS(LINUX)
+#elif CPU(X86_64)
 typedef PageTables1GB FixedVMPoolPageTables;
 #else
 typedef PageTables32MB FixedVMPoolPageTables;
 #endif
 
+
 class FixedVMPoolAllocator
 {
 public:
     FixedVMPoolAllocator()
     {
-        m_base = mmap(0, FixedVMPoolPageTables::size(), INITIAL_PROTECTION_FLAGS, MMAP_FLAGS, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0);
+        ASSERT(PageTables256KB::size() == 256 * 1024);
+        ASSERT(PageTables16MB::size() == 16 * 1024 * 1024);
+        ASSERT(PageTables32MB::size() == 32 * 1024 * 1024);
+        ASSERT(PageTables1GB::size() == 1024 * 1024 * 1024);
 
-        if (m_base == MAP_FAILED) {
-#if ENABLE(INTERPRETER)
-            m_base = 0;
-#else
+        m_reservation = PageReservation::reserveWithGuardPages(FixedVMPoolPageTables::size(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
+#if !ENABLE(INTERPRETER)
+        if (!isValid())
             CRASH();
 #endif
-        } else {
-            // For simplicity, we keep all memory in m_freeList in a 'released' state.
-            // This means that we can simply reuse all memory when allocating, without
-            // worrying about it's previous state, and also makes coalescing m_freeList
-            // simpler since we need not worry about the possibility of coalescing released
-            // chunks with non-released ones.
-            release(m_base, FixedVMPoolPageTables::size());
-        }
     }
  
-    void* alloc(size_t size)
+    ExecutablePool::Allocation alloc(size_t requestedSize)
     {
+        ASSERT(requestedSize);
+        AllocationTableSizeClass sizeClass = classForSize(requestedSize);
+        size_t size = sizeClass.size();
         ASSERT(size);
-        AllocationTableSizeClass sizeClass = classForSize(size);
-        ASSERT(sizeClass.size());
-        if (sizeClass.size() >= FixedVMPoolPageTables::size())
-            CRASH();
 
+        if (size >= FixedVMPoolPageTables::size())
+            return ExecutablePool::Allocation(0, 0);
         if (m_pages.isFull())
-            CRASH();
+            return ExecutablePool::Allocation(0, 0);
+
         size_t offset = m_pages.allocate(sizeClass);
         if (offset == notFound)
-            CRASH();
+            return ExecutablePool::Allocation(0, 0);
 
-        void* result = offsetToPointer(offset);
-        reuse(result, size);
-        return result;
+        void* pointer = offsetToPointer(offset);
+        m_reservation.commit(pointer, size);
+        return ExecutablePool::Allocation(pointer, size);
     }
 
-    void free(void* pointer, size_t size)
+    void free(ExecutablePool::Allocation allocation)
     {
-        release(pointer, size);
-
+        void* pointer = allocation.base();
+        size_t size = allocation.size();
         ASSERT(size);
-        AllocationTableSizeClass sizeClass = classForSize(size);
-        ASSERT(sizeClass.size());
-        ASSERT(sizeClass.size() < FixedVMPoolPageTables::size());
 
-        m_pages.free(pointerToOffset(pointer), sizeClass);
-    }
+        m_reservation.decommit(pointer, size);
 
-    bool isValid() const
-    {
-        return !!m_base;
+        AllocationTableSizeClass sizeClass = classForSize(size);
+        ASSERT(sizeClass.size() == size);
+        m_pages.free(pointerToOffset(pointer), sizeClass);
     }
 
-private:
-    // Use madvise as apropriate to prevent freed pages from being spilled,
-    // and to attempt to ensure that used memory is reported correctly.
-#if HAVE(MADV_FREE_REUSE)
-    void release(void* position, size_t size)
+    size_t allocated()
     {
-        while (madvise(position, size, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
+        return m_reservation.committed();
     }
 
-    void reuse(void* position, size_t size)
-    {
-        while (madvise(position, size, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
-    }
-#elif HAVE(MADV_FREE)
-    void release(void* position, size_t size)
-    {
-        while (madvise(position, size, MADV_FREE) == -1 && errno == EAGAIN) { }
-    }
-    
-    void reuse(void*, size_t) {}
-#elif HAVE(MADV_DONTNEED)
-    void release(void* position, size_t size)
+    bool isValid() const
     {
-        while (madvise(position, size, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
+        return !!m_reservation;
     }
 
-    void reuse(void*, size_t) {}
-#else
-    void release(void*, size_t) {}
-    void reuse(void*, size_t) {}
-#endif
-
+private:
     AllocationTableSizeClass classForSize(size_t size)
     {
         return FixedVMPoolPageTables::classForSize(size);
@@ -492,27 +470,34 @@ private:
 
     void* offsetToPointer(size_t offset)
     {
-        return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(m_base) + offset);
+        return reinterpret_cast<void*>(reinterpret_cast<intptr_t>(m_reservation.base()) + offset);
     }
 
     size_t pointerToOffset(void* pointer)
     {
-        return reinterpret_cast<intptr_t>(pointer) - reinterpret_cast<intptr_t>(m_base);
+        return reinterpret_cast<intptr_t>(pointer) - reinterpret_cast<intptr_t>(m_reservation.base());
     }
 
-    void* m_base;
+    PageReservation m_reservation;
     FixedVMPoolPageTables m_pages;
 };
 
+
+static SpinLock spinlock = SPINLOCK_INITIALIZER;
+static FixedVMPoolAllocator* allocator = 0;
+
+
+size_t ExecutableAllocator::committedByteCount()
+{
+    SpinLockHolder lockHolder(&spinlock);
+    return allocator ? allocator->allocated() : 0;
+}   
+
 void ExecutableAllocator::intializePageSize()
 {
     ExecutableAllocator::pageSize = getpagesize();
 }
 
-static FixedVMPoolAllocator* allocator = 0;
-static size_t allocatedCount = 0;
-static SpinLock spinlock = SPINLOCK_INITIALIZER;
-
 bool ExecutableAllocator::isValid() const
 {
     SpinLockHolder lock_holder(&spinlock);
@@ -521,34 +506,38 @@ bool ExecutableAllocator::isValid() const
     return allocator->isValid();
 }
 
-ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
+bool ExecutableAllocator::underMemoryPressure()
 {
-    SpinLockHolder lock_holder(&spinlock);
-
-    if (!allocator)
-        allocator = new FixedVMPoolAllocator();
-    ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocator->alloc(size)), size};
-    allocatedCount += size;
-    return alloc;
+    // Technically we should take the spin lock here, but we don't care if we get stale data.
+    // This is only really a heuristic anyway.
+    return allocator && (allocator->allocated() > (FixedVMPoolPageTables::size() / 2));
 }
 
-void ExecutablePool::systemRelease(const ExecutablePool::Allocation& allocation) 
+ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
 {
     SpinLockHolder lock_holder(&spinlock);
-
     ASSERT(allocator);
-    allocator->free(allocation.pages, allocation.size);
-    allocatedCount -= allocation.size;
+    return allocator->alloc(size);
 }
 
-bool ExecutablePool::underMemoryPressure()
+void ExecutablePool::systemRelease(ExecutablePool::Allocation& allocation) 
 {
-    // Technically we should take the spin lock here, but we don't
-    // care if we get stale data.  This is only really a heuristic
-    // anyway.
-    return allocatedCount > (FixedVMPoolPageTables::size() / 2);
+    SpinLockHolder lock_holder(&spinlock);
+    ASSERT(allocator);
+    allocator->free(allocation);
 }
 
 }
 
+
 #endif // HAVE(ASSEMBLER)
+
+#if !ENABLE(JIT)
+// FIXME: Needed to satisfy JavaScriptCore.exp requirements when building only the interpreter.
+namespace JSC {
+size_t ExecutableAllocator::committedByteCount()
+{
+    return 0;
+}
+} // namespace JSC
+#endif // !ENABLE(JIT)
diff --git a/jit/ExecutableAllocatorPosix.cpp b/jit/ExecutableAllocatorPosix.cpp
deleted file mode 100644 (file)
index 0a1b8df..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2008 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. 
- */
-
-#include "config.h"
-
-#include "ExecutableAllocator.h"
-
-#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && !OS(WINDOWS) && !OS(SYMBIAN)
-
-#include <sys/mman.h>
-#include <unistd.h>
-#include <wtf/VMTags.h>
-
-namespace JSC {
-
-void ExecutableAllocator::intializePageSize()
-{
-    ExecutableAllocator::pageSize = getpagesize();
-}
-
-ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
-{
-    void* allocation = mmap(NULL, n, INITIAL_PROTECTION_FLAGS, MAP_PRIVATE | MAP_ANON, VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, 0);
-    if (allocation == MAP_FAILED)
-        CRASH();
-    ExecutablePool::Allocation alloc = { reinterpret_cast<char*>(allocation), n };
-    return alloc;
-}
-
-void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
-{ 
-    int result = munmap(alloc.pages, alloc.size);
-    ASSERT_UNUSED(result, !result);
-}
-
-bool ExecutablePool::underMemoryPressure()
-{
-    return false;
-}
-
-bool ExecutableAllocator::isValid() const
-{
-    return true;
-}
-
-#if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
-__asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
-{
-    ARM
-    push {r7}
-    add r1, r1, r0
-    mov r7, #0xf0000
-    add r7, r7, #0x2
-    mov r2, #0x0
-    svc #0x0
-    pop {r7}
-    bx lr
-}
-#endif
-
-}
-
-#endif
diff --git a/jit/ExecutableAllocatorSymbian.cpp b/jit/ExecutableAllocatorSymbian.cpp
deleted file mode 100644 (file)
index 9028f50..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- *  Boston, MA  02110-1301  USA
- *
- */
-
-#include "config.h"
-
-#include "ExecutableAllocator.h"
-
-#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && OS(SYMBIAN)
-
-#include <e32hal.h>
-#include <e32std.h>
-
-// Set the page size to 256 Kb to compensate for moving memory model limitation
-const size_t MOVING_MEM_PAGE_SIZE = 256 * 1024; 
-
-namespace JSC {
-
-void ExecutableAllocator::intializePageSize()
-{
-#if CPU(ARMV5_OR_LOWER)
-    // The moving memory model (as used in ARMv5 and earlier platforms)
-    // on Symbian OS limits the number of chunks for each process to 16. 
-    // To mitigate this limitation increase the pagesize to 
-    // allocate less of larger chunks.
-    ExecutableAllocator::pageSize = MOVING_MEM_PAGE_SIZE;
-#else
-    TInt page_size;
-    UserHal::PageSizeInBytes(page_size);
-    ExecutableAllocator::pageSize = page_size;
-#endif
-}
-
-ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
-{
-    RChunk* codeChunk = new RChunk();
-
-    TInt errorCode = codeChunk->CreateLocalCode(n, n);
-
-    char* allocation = reinterpret_cast<char*>(codeChunk->Base());
-    if (!allocation)
-        CRASH();
-    ExecutablePool::Allocation alloc = { allocation, n, codeChunk };
-    return alloc;
-}
-
-void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
-{ 
-    alloc.chunk->Close();
-    delete alloc.chunk;
-}
-
-#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
-#error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
-#endif
-
-}
-
-#endif // HAVE(ASSEMBLER)
diff --git a/jit/ExecutableAllocatorWin.cpp b/jit/ExecutableAllocatorWin.cpp
deleted file mode 100644 (file)
index 19179d4..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2008 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. 
- */
-
-#include "config.h"
-
-#include "ExecutableAllocator.h"
-
-#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) && OS(WINDOWS)
-
-#include "windows.h"
-
-namespace JSC {
-
-void ExecutableAllocator::intializePageSize()
-{
-    SYSTEM_INFO system_info;
-    GetSystemInfo(&system_info);
-    ExecutableAllocator::pageSize = system_info.dwPageSize;
-}
-
-ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n)
-{
-    void* allocation = VirtualAlloc(0, n, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
-    if (!allocation)
-        CRASH();
-    ExecutablePool::Allocation alloc = {reinterpret_cast<char*>(allocation), n};
-    return alloc;
-}
-
-void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc)
-{ 
-    VirtualFree(alloc.pages, 0, MEM_RELEASE); 
-}
-
-bool ExecutablePool::underMemoryPressure()
-{
-    return false;
-}
-
-bool ExecutableAllocator::isValid() const
-{
-    return true;
-}
-
-#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
-#error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform."
-#endif
-
-}
-
-#endif // HAVE(ASSEMBLER)
index d3330d82a19b5894df852fc28c080cac0643df98..26e1f630f924642e1677a694abc34e61b8822393 100644 (file)
@@ -24,6 +24,8 @@
  */
 
 #include "config.h"
+
+#if ENABLE(JIT)
 #include "JIT.h"
 
 // This probably does not belong here; adding here for now as a quick Windows build fix.
@@ -32,9 +34,8 @@
 JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
 #endif
 
-#if ENABLE(JIT)
-
 #include "CodeBlock.h"
+#include "CryptographicallyRandomNumber.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -44,10 +45,7 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse
 #include "RepatchBuffer.h"
 #include "ResultType.h"
 #include "SamplingTool.h"
-
-#ifndef NDEBUG
-#include <stdio.h>
-#endif
+#include "dfg/DFGNode.h" // for DFG_SUCCESS_STATS
 
 using namespace std;
 
@@ -71,17 +69,17 @@ void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAd
     repatchBuffer.relinkCallerToFunction(returnAddress, newCalleeFunction);
 }
 
-JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock, void* linkerOffset)
+JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
     : m_interpreter(globalData->interpreter)
     , m_globalData(globalData)
     , m_codeBlock(codeBlock)
     , m_labels(codeBlock ? codeBlock->instructions().size() : 0)
     , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0)
     , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0)
-    , m_bytecodeIndex((unsigned)-1)
+    , m_bytecodeOffset((unsigned)-1)
 #if USE(JSVALUE32_64)
     , m_jumpTargetIndex(0)
-    , m_mappedBytecodeIndex((unsigned)-1)
+    , m_mappedBytecodeOffset((unsigned)-1)
     , m_mappedVirtualRegisterIndex((unsigned)-1)
     , m_mappedTag((RegisterID)-1)
     , m_mappedPayload((RegisterID)-1)
@@ -89,14 +87,18 @@ JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock, void* linkerOffset)
     , m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
     , m_jumpTargetsPosition(0)
 #endif
-    , m_linkerOffset(linkerOffset)
+#if USE(OS_RANDOMNESS)
+    , m_randomGenerator(cryptographicallyRandomNumber())
+#else
+    , m_randomGenerator(static_cast<unsigned>(randomNumber() * 0xFFFFFFF))
+#endif
 {
 }
 
 #if USE(JSVALUE32_64)
 void JIT::emitTimeoutCheck()
 {
-    Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister);
+    Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), timeoutCheckRegister);
     JITStubCall stubCall(this, cti_timeout_check);
     stubCall.addArgument(regT1, regT0); // save last result registers.
     stubCall.call(timeoutCheckRegister);
@@ -106,7 +108,7 @@ void JIT::emitTimeoutCheck()
 #else
 void JIT::emitTimeoutCheck()
 {
-    Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister);
+    Jump skipTimeout = branchSub32(NonZero, TrustedImm32(1), timeoutCheckRegister);
     JITStubCall(this, cti_timeout_check).call(timeoutCheckRegister);
     skipTimeout.link(this);
 
@@ -115,7 +117,7 @@ void JIT::emitTimeoutCheck()
 #endif
 
 #define NEXT_OPCODE(name) \
-    m_bytecodeIndex += OPCODE_LENGTH(name); \
+    m_bytecodeOffset += OPCODE_LENGTH(name); \
     break;
 
 #if USE(JSVALUE32_64)
@@ -177,27 +179,24 @@ void JIT::privateCompileMainPass()
     m_globalResolveInfoIndex = 0;
     m_callLinkInfoIndex = 0;
 
-    for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) {
-        Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
-        ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeIndex);
+    for (m_bytecodeOffset = 0; m_bytecodeOffset < instructionCount; ) {
+        Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
+        ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeOffset);
 
 #if ENABLE(OPCODE_SAMPLING)
-        if (m_bytecodeIndex > 0) // Avoid the overhead of sampling op_enter twice.
+        if (m_bytecodeOffset > 0) // Avoid the overhead of sampling op_enter twice.
             sampleInstruction(currentInstruction);
 #endif
 
-#if !USE(JSVALUE32_64)
-        if (m_labels[m_bytecodeIndex].isUsed())
+#if USE(JSVALUE64)
+        if (atJumpTarget())
             killLastResultRegister();
 #endif
 
-        m_labels[m_bytecodeIndex] = label();
+        m_labels[m_bytecodeOffset] = label();
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_BINARY_OP(op_del_by_val)
-#if USE(JSVALUE32)
-        DEFINE_BINARY_OP(op_div)
-#endif
         DEFINE_BINARY_OP(op_in)
         DEFINE_BINARY_OP(op_less)
         DEFINE_BINARY_OP(op_lesseq)
@@ -207,7 +206,7 @@ void JIT::privateCompileMainPass()
         DEFINE_UNARY_OP(op_is_object)
         DEFINE_UNARY_OP(op_is_string)
         DEFINE_UNARY_OP(op_is_undefined)
-#if !USE(JSVALUE32_64)
+#if USE(JSVALUE64)
         DEFINE_UNARY_OP(op_negate)
 #endif
         DEFINE_UNARY_OP(op_typeof)
@@ -222,26 +221,29 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_call_varargs)
         DEFINE_OP(op_catch)
         DEFINE_OP(op_construct)
-        DEFINE_OP(op_construct_verify)
+        DEFINE_OP(op_get_callee)
+        DEFINE_OP(op_create_this)
         DEFINE_OP(op_convert_this)
-        DEFINE_OP(op_init_arguments)
+        DEFINE_OP(op_convert_this_strict)
+        DEFINE_OP(op_init_lazy_reg)
         DEFINE_OP(op_create_arguments)
         DEFINE_OP(op_debug)
         DEFINE_OP(op_del_by_id)
-#if !USE(JSVALUE32)
         DEFINE_OP(op_div)
-#endif
         DEFINE_OP(op_end)
         DEFINE_OP(op_enter)
-        DEFINE_OP(op_enter_with_activation)
+        DEFINE_OP(op_create_activation)
         DEFINE_OP(op_eq)
         DEFINE_OP(op_eq_null)
         DEFINE_OP(op_get_by_id)
+        DEFINE_OP(op_get_arguments_length)
         DEFINE_OP(op_get_by_val)
+        DEFINE_OP(op_get_argument_by_val)
         DEFINE_OP(op_get_by_pname)
         DEFINE_OP(op_get_global_var)
         DEFINE_OP(op_get_pnames)
         DEFINE_OP(op_get_scoped_var)
+        DEFINE_OP(op_check_has_instance)
         DEFINE_OP(op_instanceof)
         DEFINE_OP(op_jeq_null)
         DEFINE_OP(op_jfalse)
@@ -272,7 +274,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_neq)
         DEFINE_OP(op_neq_null)
         DEFINE_OP(op_new_array)
-        DEFINE_OP(op_new_error)
+        DEFINE_OP(op_new_array_buffer)
         DEFINE_OP(op_new_func)
         DEFINE_OP(op_new_func_exp)
         DEFINE_OP(op_new_object)
@@ -298,11 +300,14 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_put_setter)
         DEFINE_OP(op_resolve)
         DEFINE_OP(op_resolve_base)
+        DEFINE_OP(op_ensure_property_exists)
         DEFINE_OP(op_resolve_global)
         DEFINE_OP(op_resolve_global_dynamic)
         DEFINE_OP(op_resolve_skip)
         DEFINE_OP(op_resolve_with_base)
         DEFINE_OP(op_ret)
+        DEFINE_OP(op_call_put_result)
+        DEFINE_OP(op_ret_object_or_this)
         DEFINE_OP(op_rshift)
         DEFINE_OP(op_urshift)
         DEFINE_OP(op_sret)
@@ -315,6 +320,7 @@ void JIT::privateCompileMainPass()
         DEFINE_OP(op_tear_off_activation)
         DEFINE_OP(op_tear_off_arguments)
         DEFINE_OP(op_throw)
+        DEFINE_OP(op_throw_reference_error)
         DEFINE_OP(op_to_jsnumber)
         DEFINE_OP(op_to_primitive)
 
@@ -348,7 +354,7 @@ void JIT::privateCompileMainPass()
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
-    m_bytecodeIndex = (unsigned)-1;
+    m_bytecodeOffset = (unsigned)-1;
 #endif
 }
 
@@ -357,7 +363,7 @@ void JIT::privateCompileLinkPass()
 {
     unsigned jmpTableCount = m_jmpTable.size();
     for (unsigned i = 0; i < jmpTableCount; ++i)
-        m_jmpTable[i].from.linkTo(m_labels[m_jmpTable[i].toBytecodeIndex], this);
+        m_jmpTable[i].from.linkTo(m_labels[m_jmpTable[i].toBytecodeOffset], this);
     m_jmpTable.clear();
 }
 
@@ -370,15 +376,15 @@ void JIT::privateCompileSlowCases()
     m_callLinkInfoIndex = 0;
 
     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
-#if !USE(JSVALUE32_64)
+#if USE(JSVALUE64)
         killLastResultRegister();
 #endif
 
-        m_bytecodeIndex = iter->to;
+        m_bytecodeOffset = iter->to;
 #ifndef NDEBUG
-        unsigned firstTo = m_bytecodeIndex;
+        unsigned firstTo = m_bytecodeOffset;
 #endif
-        Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
+        Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_SLOWCASE_OP(op_add)
@@ -390,15 +396,16 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_call_eval)
         DEFINE_SLOWCASE_OP(op_call_varargs)
         DEFINE_SLOWCASE_OP(op_construct)
-        DEFINE_SLOWCASE_OP(op_construct_verify)
         DEFINE_SLOWCASE_OP(op_convert_this)
-#if !USE(JSVALUE32)
+        DEFINE_SLOWCASE_OP(op_convert_this_strict)
         DEFINE_SLOWCASE_OP(op_div)
-#endif
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
+        DEFINE_SLOWCASE_OP(op_get_arguments_length)
         DEFINE_SLOWCASE_OP(op_get_by_val)
+        DEFINE_SLOWCASE_OP(op_get_argument_by_val)
         DEFINE_SLOWCASE_OP(op_get_by_pname)
+        DEFINE_SLOWCASE_OP(op_check_has_instance)
         DEFINE_SLOWCASE_OP(op_instanceof)
         DEFINE_SLOWCASE_OP(op_jfalse)
         DEFINE_SLOWCASE_OP(op_jnless)
@@ -406,6 +413,7 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_OP(op_jlesseq)
         DEFINE_SLOWCASE_OP(op_jnlesseq)
         DEFINE_SLOWCASE_OP(op_jtrue)
+        DEFINE_SLOWCASE_OP(op_load_varargs)
         DEFINE_SLOWCASE_OP(op_loop_if_less)
         DEFINE_SLOWCASE_OP(op_loop_if_lesseq)
         DEFINE_SLOWCASE_OP(op_loop_if_true)
@@ -451,79 +459,96 @@ void JIT::privateCompileSlowCases()
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
-    m_bytecodeIndex = (unsigned)-1;
+    m_bytecodeOffset = (unsigned)-1;
 #endif
 }
 
-JITCode JIT::privateCompile()
+JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
 {
-    sampleCodeBlock(m_codeBlock);
-#if ENABLE(OPCODE_SAMPLING)
-    sampleInstruction(m_codeBlock->instructions().begin());
-#endif
+    // Just add a little bit of randomness to the codegen
+    if (m_randomGenerator.getUint32() & 1)
+        nop();
 
     // Could use a pop_m, but would need to offset the following instruction if so.
     preserveReturnAddressAfterCall(regT2);
     emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
 
-    Jump slowRegisterFileCheck;
-    Label afterRegisterFileCheck;
+    Label beginLabel(this);
+
+    sampleCodeBlock(m_codeBlock);
+#if ENABLE(OPCODE_SAMPLING)
+    sampleInstruction(m_codeBlock->instructions().begin());
+#endif
+
+    Jump registerFileCheck;
     if (m_codeBlock->codeType() == FunctionCode) {
+#if DFG_SUCCESS_STATS
+        static SamplingCounter counter("orignalJIT");
+        emitCount(counter);
+#endif
+
         // In the case of a fast linked call, we do not set this up in the caller.
         emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
 
-        peek(regT0, OBJECT_OFFSETOF(JITStackFrame, registerFile) / sizeof (void*));
         addPtr(Imm32(m_codeBlock->m_numCalleeRegisters * sizeof(Register)), callFrameRegister, regT1);
-
-        slowRegisterFileCheck = branchPtr(Above, regT1, Address(regT0, OBJECT_OFFSETOF(RegisterFile, m_end)));
-        afterRegisterFileCheck = label();
+        registerFileCheck = branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT1);
     }
 
+    Label functionBody = label();
+
     privateCompileMainPass();
     privateCompileLinkPass();
     privateCompileSlowCases();
 
+    Label arityCheck;
     if (m_codeBlock->codeType() == FunctionCode) {
-        slowRegisterFileCheck.link(this);
-        m_bytecodeIndex = 0;
+        registerFileCheck.link(this);
+        m_bytecodeOffset = 0;
         JITStubCall(this, cti_register_file_check).call();
 #ifndef NDEBUG
-        m_bytecodeIndex = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs.
+        m_bytecodeOffset = (unsigned)-1; // Reset this, in order to guard its use with ASSERTs.
 #endif
-        jump(afterRegisterFileCheck);
+        jump(functionBody);
+
+        arityCheck = label();
+        preserveReturnAddressAfterCall(regT2);
+        emitPutToCallFrameHeader(regT2, RegisterFile::ReturnPC);
+        branch32(Equal, regT1, TrustedImm32(m_codeBlock->m_numParameters)).linkTo(beginLabel, this);
+        restoreArgumentReference();
+
+        JITStubCall(this, m_codeBlock->m_isConstructor ? cti_op_construct_arityCheck : cti_op_call_arityCheck).call(callFrameRegister);
+
+        jump(beginLabel);
     }
 
     ASSERT(m_jmpTable.isEmpty());
 
-    RefPtr<ExecutablePool> executablePool = m_globalData->executableAllocator.poolForSize(m_assembler.size());
-    if (!executablePool)
-        return JITCode();
-    LinkBuffer patchBuffer(this, executablePool.release(), m_linkerOffset);
+    LinkBuffer patchBuffer(*m_globalData, this, m_globalData->executableAllocator);
 
     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
     for (unsigned i = 0; i < m_switches.size(); ++i) {
         SwitchRecord record = m_switches[i];
-        unsigned bytecodeIndex = record.bytecodeIndex;
+        unsigned bytecodeOffset = record.bytecodeOffset;
 
         if (record.type != SwitchRecord::String) {
             ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); 
             ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
 
-            record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]);
+            record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeOffset + record.defaultOffset]);
 
             for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
                 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
-                record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
+                record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeOffset + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
             }
         } else {
             ASSERT(record.type == SwitchRecord::String);
 
-            record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]);
+            record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeOffset + record.defaultOffset]);
 
             StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();            
             for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
                 unsigned offset = it->second.branchOffset;
-                it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
+                it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeOffset + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
             }
         }
     }
@@ -538,10 +563,10 @@ JITCode JIT::privateCompile()
             patchBuffer.link(iter->from, FunctionPtr(iter->to));
     }
 
-    if (m_codeBlock->hasExceptionInfo()) {
+    if (m_codeBlock->needsCallReturnIndices()) {
         m_codeBlock->callReturnIndexVector().reserveCapacity(m_calls.size());
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter)
-            m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeIndex(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeIndex));
+            m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset));
     }
 
     // Link absolute addresses for jsr
@@ -558,7 +583,7 @@ JITCode JIT::privateCompile()
 #if ENABLE(JIT_OPTIMIZE_CALL)
     for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
         CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
-        info.ownerCodeBlock = m_codeBlock;
+        info.isCall = m_callStructureStubCompilationInfo[i].isCall;
         info.callReturnLocation = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].callReturnLocation);
         info.hotPathBegin = patchBuffer.locationOf(m_callStructureStubCompilationInfo[i].hotPathBegin);
         info.hotPathOther = patchBuffer.locationOfNearCall(m_callStructureStubCompilationInfo[i].hotPathOther);
@@ -568,44 +593,35 @@ JITCode JIT::privateCompile()
     m_codeBlock->addMethodCallLinkInfos(methodCallCount);
     for (unsigned i = 0; i < methodCallCount; ++i) {
         MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
-        info.structureLabel = patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare);
+        info.cachedStructure.setLocation(patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare));
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
+    if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck)
+        *functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
+
     return patchBuffer.finalizeCode();
 }
 
-#if !USE(JSVALUE32_64)
-void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
-{
-    loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), dst);
-    loadPtr(Address(dst, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), dst);
-    loadPtr(Address(dst, index * sizeof(Register)), dst);
-}
+#if ENABLE(JIT_OPTIMIZE_CALL)
 
-void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
+void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
 {
-    loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject, d)), variableObject);
-    loadPtr(Address(variableObject, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), variableObject);
-    storePtr(src, Address(variableObject, index * sizeof(Register)));
-}
-#endif
+    RepatchBuffer repatchBuffer(callerCodeBlock);
 
-#if ENABLE(JIT_OPTIMIZE_CALL)
-void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
-{
-    // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
-    // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
-    // match).  Reset the check so it no longer matches.
-    RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock);
-#if USE(JSVALUE32_64)
-    repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0);
-#else
-    repatchBuffer.repatch(callLinkInfo->hotPathBegin, JSValue::encode(JSValue()));
-#endif
+    // Currently we only link calls with the exact number of arguments.
+    // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
+    if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) {
+        ASSERT(!callLinkInfo->isLinked());
+        callLinkInfo->callee.set(*globalData, callLinkInfo->hotPathBegin, callerCodeBlock->ownerExecutable(), callee);
+        repatchBuffer.relink(callLinkInfo->hotPathOther, code);
+    }
+
+    // patch the call so we do not continue to try to link.
+    repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualCall());
 }
 
-void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode& code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
+void JIT::linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JIT::CodePtr code, CallLinkInfo* callLinkInfo, int callerArgCount, JSGlobalData* globalData)
 {
     RepatchBuffer repatchBuffer(callerCodeBlock);
 
@@ -613,16 +629,12 @@ void JIT::linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* ca
     // If this is a native call calleeCodeBlock is null so the number of parameters is unimportant
     if (!calleeCodeBlock || (callerArgCount == calleeCodeBlock->m_numParameters)) {
         ASSERT(!callLinkInfo->isLinked());
-    
-        if (calleeCodeBlock)
-            calleeCodeBlock->addCaller(callLinkInfo);
-    
-        repatchBuffer.repatch(callLinkInfo->hotPathBegin, callee);
-        repatchBuffer.relink(callLinkInfo->hotPathOther, code.addressForCall());
+        callLinkInfo->callee.set(*globalData, callLinkInfo->hotPathBegin, callerCodeBlock->ownerExecutable(), callee);
+        repatchBuffer.relink(callLinkInfo->hotPathOther, code);
     }
 
     // patch the call so we do not continue to try to link.
-    repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualCall());
+    repatchBuffer.relink(callLinkInfo->callReturnLocation, globalData->jitStubs->ctiVirtualConstruct());
 }
 #endif // ENABLE(JIT_OPTIMIZE_CALL)
 
index ff72c80f74d3e1e3b4be3698d1d0227785c4ec7d..6cc55fd7e5035838c1a2c1eae3b4678395d7da4b 100644 (file)
--- a/jit/JIT.h
+++ b/jit/JIT.h
@@ -36,7 +36,8 @@
 #define JIT_CLASS_ALIGNMENT
 #endif
 
-#define ASSERT_JIT_OFFSET(actual, expected) ASSERT_WITH_MESSAGE(actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(actual), static_cast<int>(expected));
+#define ASSERT_JIT_OFFSET_UNUSED(variable, actual, expected) ASSERT_WITH_MESSAGE_UNUSED(variable, actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(expected), static_cast<int>(actual));
+#define ASSERT_JIT_OFFSET(actual, expected) ASSERT_WITH_MESSAGE(actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(expected), static_cast<int>(actual));
 
 #include "CodeBlock.h"
 #include "Interpreter.h"
@@ -66,16 +67,16 @@ namespace JSC {
 
     struct CallRecord {
         MacroAssembler::Call from;
-        unsigned bytecodeIndex;
+        unsigned bytecodeOffset;
         void* to;
 
         CallRecord()
         {
         }
 
-        CallRecord(MacroAssembler::Call from, unsigned bytecodeIndex, void* to = 0)
+        CallRecord(MacroAssembler::Call from, unsigned bytecodeOffset, void* to = 0)
             : from(from)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
             , to(to)
         {
         }
@@ -83,11 +84,11 @@ namespace JSC {
 
     struct JumpTable {
         MacroAssembler::Jump from;
-        unsigned toBytecodeIndex;
+        unsigned toBytecodeOffset;
 
         JumpTable(MacroAssembler::Jump f, unsigned t)
             : from(f)
-            , toBytecodeIndex(t)
+            , toBytecodeOffset(t)
         {
         }
     };
@@ -119,20 +120,20 @@ namespace JSC {
             StringJumpTable* stringJumpTable;
         } jumpTable;
 
-        unsigned bytecodeIndex;
+        unsigned bytecodeOffset;
         unsigned defaultOffset;
 
-        SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type)
+        SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeOffset, unsigned defaultOffset, Type type)
             : type(type)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
             , defaultOffset(defaultOffset)
         {
             this->jumpTable.simpleJumpTable = jumpTable;
         }
 
-        SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset)
+        SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeOffset, unsigned defaultOffset)
             : type(String)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
             , defaultOffset(defaultOffset)
         {
             this->jumpTable.stringJumpTable = jumpTable;
@@ -148,6 +149,7 @@ namespace JSC {
         MacroAssembler::DataLabelPtr hotPathBegin;
         MacroAssembler::Call hotPathOther;
         MacroAssembler::Call callReturnLocation;
+        bool isCall;
     };
 
     struct MethodCallCompilationInfo {
@@ -173,14 +175,15 @@ namespace JSC {
         using MacroAssembler::Label;
 
         static const int patchGetByIdDefaultStructure = -1;
+        static const int patchGetByIdDefaultOffset = 0;
         // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler
         // will compress the displacement, and we may not be able to fit a patched offset.
-        static const int patchGetByIdDefaultOffset = 256;
+        static const int patchPutByIdDefaultOffset = 256;
 
     public:
-        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, void* offsetBase = 0)
+        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, CodePtr* functionEntryArityCheck = 0)
         {
-            return JIT(globalData, codeBlock, offsetBase).privateCompile();
+            return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck);
         }
 
         static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
@@ -221,13 +224,21 @@ namespace JSC {
         {
             if (!globalData->canUseJIT())
                 return;
-            JIT jit(globalData, 0, 0);
+            JIT jit(globalData, 0);
             jit.privateCompileCTIMachineTrampolines(executablePool, globalData, trampolines);
         }
 
+        static CodePtr compileCTINativeCall(JSGlobalData* globalData, PassRefPtr<ExecutablePool> executablePool, NativeFunction func)
+        {
+            if (!globalData->canUseJIT())
+                return CodePtr();
+            JIT jit(globalData, 0);
+            return jit.privateCompileCTINativeCall(executablePool, globalData, func);
+        }
+
         static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
         static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct);
-        static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
+        static void patchMethodCallProto(JSGlobalData&, CodeBlock* codeblock, MethodCallLinkInfo&, JSObjectWithGlobalObject*, Structure*, JSObject*, ReturnAddressPtr);
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
@@ -235,8 +246,8 @@ namespace JSC {
             return jit.privateCompilePatchGetArrayLength(returnAddress);
         }
 
-        static void linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode&, CallLinkInfo*, int callerArgCount, JSGlobalData*);
-        static void unlinkCall(CallLinkInfo*);
+        static void linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, int callerArgCount, JSGlobalData*);
+        static void linkConstruct(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, int callerArgCount, JSGlobalData*);
 
     private:
         struct JSRInfo {
@@ -250,12 +261,12 @@ namespace JSC {
             }
         };
 
-        JIT(JSGlobalData*, CodeBlock* = 0, void* = 0);
+        JIT(JSGlobalData*, CodeBlock* = 0);
 
         void privateCompileMainPass();
         void privateCompileLinkPass();
         void privateCompileSlowCases();
-        JITCode privateCompile();
+        JITCode privateCompile(CodePtr* functionEntryArityCheck);
         void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
         void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, const Identifier&, const PropertySlot&, size_t cachedOffset);
         void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
@@ -264,6 +275,8 @@ namespace JSC {
         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress, bool direct);
 
         void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, TrampolineStructure *trampolines);
+        Label privateCompileCTINativeCall(JSGlobalData*, bool isConstruct = false);
+        CodePtr privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executablePool, JSGlobalData* data, NativeFunction func);
         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
 
         void addSlowCase(Jump);
@@ -274,11 +287,8 @@ namespace JSC {
         void compileOpCall(OpcodeID, Instruction* instruction, unsigned callLinkInfoIndex);
         void compileOpCallVarargs(Instruction* instruction);
         void compileOpCallInitializeCallFrame();
-        void compileOpCallSetupArgs(Instruction*);
-        void compileOpCallVarargsSetupArgs(Instruction*);
         void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
         void compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter);
-        void compileOpConstructSetupArgs(Instruction*);
 
         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
         void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
@@ -287,7 +297,7 @@ namespace JSC {
         void emitLoadDouble(unsigned index, FPRegisterID value);
         void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
 
-        void testPrototype(Structure*, JumpList& failureCases);
+        void testPrototype(JSValue, JumpList& failureCases);
 
 #if USE(JSVALUE32_64)
         bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
@@ -302,13 +312,13 @@ namespace JSC {
         void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
         void emitStore(unsigned index, const JSValue constant, RegisterID base = callFrameRegister);
         void emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32 = false);
-        void emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32 = false);
+        void emitStoreInt32(unsigned index, TrustedImm32 payload, bool indexIsInt32 = false);
         void emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell = false);
-        void emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool = false);
+        void emitStoreBool(unsigned index, RegisterID payload, bool indexIsBool = false);
         void emitStoreDouble(unsigned index, FPRegisterID value);
 
-        bool isLabeled(unsigned bytecodeIndex);
-        void map(unsigned bytecodeIndex, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload);
+        bool isLabeled(unsigned bytecodeOffset);
+        void map(unsigned bytecodeOffset, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload);
         void unmap(RegisterID);
         void unmap();
         bool isMapped(unsigned virtualRegisterIndex);
@@ -324,8 +334,8 @@ namespace JSC {
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
-        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
-        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset);
+        void compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset);
         void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
 
         // Arithmetic opcode helpers
@@ -336,24 +346,16 @@ namespace JSC {
 #if CPU(X86)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
-        static const int patchOffsetPutByIdExternalLoad = 13;
-        static const int patchLengthPutByIdExternalLoad = 3;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 22;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 7;
         static const int patchOffsetGetByIdBranchToSlowCase = 13;
-        static const int patchOffsetGetByIdExternalLoad = 13;
-        static const int patchLengthGetByIdExternalLoad = 3;
-        static const int patchOffsetGetByIdPropertyMapOffset1 = 22;
-        static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
-        static const int patchOffsetGetByIdPutResult = 28;
-#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST)
-        static const int patchOffsetGetByIdSlowCaseCall = 35;
-#elif ENABLE(OPCODE_SAMPLING)
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 19;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 22;
+        static const int patchOffsetGetByIdPutResult = 22;
+#if ENABLE(OPCODE_SAMPLING)
         static const int patchOffsetGetByIdSlowCaseCall = 37;
-#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
-        static const int patchOffsetGetByIdSlowCaseCall = 25;
 #else
         static const int patchOffsetGetByIdSlowCaseCall = 27;
 #endif
@@ -365,15 +367,11 @@ namespace JSC {
 #elif CPU(ARM_TRADITIONAL)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 4;
-        static const int patchOffsetPutByIdExternalLoad = 16;
-        static const int patchLengthPutByIdExternalLoad = 4;
         static const int patchOffsetPutByIdPropertyMapOffset1 = 20;
         static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 4;
         static const int patchOffsetGetByIdBranchToSlowCase = 16;
-        static const int patchOffsetGetByIdExternalLoad = 16;
-        static const int patchLengthGetByIdExternalLoad = 4;
         static const int patchOffsetGetByIdPropertyMapOffset1 = 20;
         static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
         static const int patchOffsetGetByIdPutResult = 36;
@@ -398,7 +396,7 @@ namespace JSC {
         static const int sequenceGetByIdHotPathInstructionSpace = 36;
         static const int sequenceGetByIdHotPathConstantSpace = 4;
         // sequenceGetByIdSlowCase
-        static const int sequenceGetByIdSlowCaseInstructionSpace = 40;
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 56;
         static const int sequenceGetByIdSlowCaseConstantSpace = 2;
         // sequencePutById
         static const int sequencePutByIdInstructionSpace = 36;
@@ -406,18 +404,14 @@ namespace JSC {
 #elif CPU(ARM_THUMB2)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 26;
-        static const int patchLengthPutByIdExternalLoad = 12;
-        static const int patchOffsetPutByIdPropertyMapOffset1 = 46;
-        static const int patchOffsetPutByIdPropertyMapOffset2 = 58;
+        static const int patchOffsetPutByIdPropertyMapOffset1 = 36;
+        static const int patchOffsetPutByIdPropertyMapOffset2 = 48;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         static const int patchOffsetGetByIdBranchToSlowCase = 26;
-        static const int patchOffsetGetByIdExternalLoad = 26;
-        static const int patchLengthGetByIdExternalLoad = 12;
-        static const int patchOffsetGetByIdPropertyMapOffset1 = 46;
-        static const int patchOffsetGetByIdPropertyMapOffset2 = 58;
-        static const int patchOffsetGetByIdPutResult = 62;
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 28;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 30;
+        static const int patchOffsetGetByIdPutResult = 32;
 #if ENABLE(OPCODE_SAMPLING)
         #error "OPCODE_SAMPLING is not yet supported"
 #else
@@ -444,6 +438,86 @@ namespace JSC {
         // sequencePutById
         static const int sequencePutByIdInstructionSpace = 36;
         static const int sequencePutByIdConstantSpace = 4;
+#elif CPU(MIPS)
+#if WTF_MIPS_ISA(1)
+        static const int patchOffsetPutByIdStructure = 16;
+        static const int patchOffsetPutByIdPropertyMapOffset1 = 56;
+        static const int patchOffsetPutByIdPropertyMapOffset2 = 72;
+        static const int patchOffsetGetByIdStructure = 16;
+        static const int patchOffsetGetByIdBranchToSlowCase = 48;
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 56;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 76;
+        static const int patchOffsetGetByIdPutResult = 96;
+#if ENABLE(OPCODE_SAMPLING)
+        #error "OPCODE_SAMPLING is not yet supported"
+#else
+        static const int patchOffsetGetByIdSlowCaseCall = 44;
+#endif
+        static const int patchOffsetOpCallCompareToJump = 32;
+        static const int patchOffsetMethodCheckProtoObj = 32;
+        static const int patchOffsetMethodCheckProtoStruct = 56;
+        static const int patchOffsetMethodCheckPutFunction = 88;
+#else // WTF_MIPS_ISA(1)
+        static const int patchOffsetPutByIdStructure = 12;
+        static const int patchOffsetPutByIdPropertyMapOffset1 = 48;
+        static const int patchOffsetPutByIdPropertyMapOffset2 = 64;
+        static const int patchOffsetGetByIdStructure = 12;
+        static const int patchOffsetGetByIdBranchToSlowCase = 44;
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 48;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 64;
+        static const int patchOffsetGetByIdPutResult = 80;
+#if ENABLE(OPCODE_SAMPLING)
+        #error "OPCODE_SAMPLING is not yet supported"
+#else
+        static const int patchOffsetGetByIdSlowCaseCall = 44;
+#endif
+        static const int patchOffsetOpCallCompareToJump = 32;
+        static const int patchOffsetMethodCheckProtoObj = 32;
+        static const int patchOffsetMethodCheckProtoStruct = 52;
+        static const int patchOffsetMethodCheckPutFunction = 84;
+#endif
+#elif CPU(SH4)
+       // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+        static const int patchOffsetGetByIdStructure = 6;
+        static const int patchOffsetPutByIdPropertyMapOffset = 24;
+        static const int patchOffsetPutByIdStructure = 6;
+        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+        static const int patchOffsetGetByIdBranchToSlowCase = 10;
+        static const int patchOffsetGetByIdPropertyMapOffset = 24;
+        static const int patchOffsetGetByIdPutResult = 32;
+
+        // sequenceOpCall
+        static const int sequenceOpCallInstructionSpace = 12;
+        static const int sequenceOpCallConstantSpace = 2;
+        // sequenceMethodCheck
+        static const int sequenceMethodCheckInstructionSpace = 40;
+        static const int sequenceMethodCheckConstantSpace = 6;
+        // sequenceGetByIdHotPath
+        static const int sequenceGetByIdHotPathInstructionSpace = 36;
+        static const int sequenceGetByIdHotPathConstantSpace = 5;
+        // sequenceGetByIdSlowCase
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 26;
+        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
+        // sequencePutById
+        static const int sequencePutByIdInstructionSpace = 36;
+        static const int sequencePutByIdConstantSpace = 5;
+
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 20;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 26;
+
+        static const int patchOffsetPutByIdPropertyMapOffset1 = 20;
+        static const int patchOffsetPutByIdPropertyMapOffset2 = 26;
+
+#if ENABLE(OPCODE_SAMPLING)
+        static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
+#else
+        static const int patchOffsetGetByIdSlowCaseCall = 22;
+#endif
+        static const int patchOffsetOpCallCompareToJump = 4;
+
+        static const int patchOffsetMethodCheckProtoObj = 12;
+        static const int patchOffsetMethodCheckProtoStruct = 20;
+        static const int patchOffsetMethodCheckPutFunction = 32;
 #else
 #error "JSVALUE32_64 not supported on this platform."
 #endif
@@ -455,9 +529,6 @@ namespace JSC {
 
         int32_t getConstantOperandImmediateInt(unsigned src);
 
-        void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
-        void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
-        
         void killLastResultRegister();
 
         Jump emitJumpIfJSCell(RegisterID);
@@ -466,8 +537,7 @@ namespace JSC {
         Jump emitJumpIfNotJSCell(RegisterID);
         void emitJumpSlowCaseIfNotJSCell(RegisterID);
         void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
-#if USE(JSVALUE64)
-#else
+#if USE(JSVALUE32_64)
         JIT::Jump emitJumpIfImmediateNumber(RegisterID reg)
         {
             return emitJumpIfImmediateInteger(reg);
@@ -485,7 +555,7 @@ namespace JSC {
         void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
-#if !USE(JSVALUE64)
+#if USE(JSVALUE32_64)
         void emitFastArithDeTagImmediate(RegisterID);
         Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
 #endif
@@ -505,23 +575,19 @@ namespace JSC {
         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
 #endif
         void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
-        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
-        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch);
+        void compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset);
+        void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch);
         void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
 
 #if CPU(X86_64)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 20;
-        static const int patchLengthPutByIdExternalLoad = 4;
         static const int patchOffsetPutByIdPropertyMapOffset = 31;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         static const int patchOffsetGetByIdBranchToSlowCase = 20;
-        static const int patchOffsetGetByIdExternalLoad = 20;
-        static const int patchLengthGetByIdExternalLoad = 4;
-        static const int patchOffsetGetByIdPropertyMapOffset = 31;
-        static const int patchOffsetGetByIdPutResult = 31;
+        static const int patchOffsetGetByIdPropertyMapOffset = 28;
+        static const int patchOffsetGetByIdPutResult = 28;
 #if ENABLE(OPCODE_SAMPLING)
         static const int patchOffsetGetByIdSlowCaseCall = 64;
 #else
@@ -535,22 +601,14 @@ namespace JSC {
 #elif CPU(X86)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 7;
-        static const int patchOffsetPutByIdExternalLoad = 13;
-        static const int patchLengthPutByIdExternalLoad = 3;
         static const int patchOffsetPutByIdPropertyMapOffset = 22;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 7;
         static const int patchOffsetGetByIdBranchToSlowCase = 13;
-        static const int patchOffsetGetByIdExternalLoad = 13;
-        static const int patchLengthGetByIdExternalLoad = 3;
         static const int patchOffsetGetByIdPropertyMapOffset = 22;
         static const int patchOffsetGetByIdPutResult = 22;
-#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST)
-        static const int patchOffsetGetByIdSlowCaseCall = 31;
-#elif ENABLE(OPCODE_SAMPLING)
+#if ENABLE(OPCODE_SAMPLING)
         static const int patchOffsetGetByIdSlowCaseCall = 33;
-#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
-        static const int patchOffsetGetByIdSlowCaseCall = 21;
 #else
         static const int patchOffsetGetByIdSlowCaseCall = 23;
 #endif
@@ -562,14 +620,10 @@ namespace JSC {
 #elif CPU(ARM_THUMB2)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 10;
-        static const int patchOffsetPutByIdExternalLoad = 26;
-        static const int patchLengthPutByIdExternalLoad = 12;
         static const int patchOffsetPutByIdPropertyMapOffset = 46;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 10;
         static const int patchOffsetGetByIdBranchToSlowCase = 26;
-        static const int patchOffsetGetByIdExternalLoad = 26;
-        static const int patchLengthGetByIdExternalLoad = 12;
         static const int patchOffsetGetByIdPropertyMapOffset = 46;
         static const int patchOffsetGetByIdPutResult = 50;
 #if ENABLE(OPCODE_SAMPLING)
@@ -585,14 +639,10 @@ namespace JSC {
 #elif CPU(ARM_TRADITIONAL)
         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
         static const int patchOffsetPutByIdStructure = 4;
-        static const int patchOffsetPutByIdExternalLoad = 16;
-        static const int patchLengthPutByIdExternalLoad = 4;
         static const int patchOffsetPutByIdPropertyMapOffset = 20;
         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
         static const int patchOffsetGetByIdStructure = 4;
         static const int patchOffsetGetByIdBranchToSlowCase = 16;
-        static const int patchOffsetGetByIdExternalLoad = 16;
-        static const int patchLengthGetByIdExternalLoad = 4;
         static const int patchOffsetGetByIdPropertyMapOffset = 20;
         static const int patchOffsetGetByIdPutResult = 28;
 #if ENABLE(OPCODE_SAMPLING)
@@ -624,13 +674,9 @@ namespace JSC {
 #elif CPU(MIPS)
 #if WTF_MIPS_ISA(1)
         static const int patchOffsetPutByIdStructure = 16;
-        static const int patchOffsetPutByIdExternalLoad = 48;
-        static const int patchLengthPutByIdExternalLoad = 20;
         static const int patchOffsetPutByIdPropertyMapOffset = 68;
         static const int patchOffsetGetByIdStructure = 16;
         static const int patchOffsetGetByIdBranchToSlowCase = 48;
-        static const int patchOffsetGetByIdExternalLoad = 48;
-        static const int patchLengthGetByIdExternalLoad = 20;
         static const int patchOffsetGetByIdPropertyMapOffset = 68;
         static const int patchOffsetGetByIdPutResult = 88;
 #if ENABLE(OPCODE_SAMPLING)
@@ -644,13 +690,9 @@ namespace JSC {
         static const int patchOffsetMethodCheckPutFunction = 88;
 #else // WTF_MIPS_ISA(1)
         static const int patchOffsetPutByIdStructure = 12;
-        static const int patchOffsetPutByIdExternalLoad = 44;
-        static const int patchLengthPutByIdExternalLoad = 16;
         static const int patchOffsetPutByIdPropertyMapOffset = 60;
         static const int patchOffsetGetByIdStructure = 12;
         static const int patchOffsetGetByIdBranchToSlowCase = 44;
-        static const int patchOffsetGetByIdExternalLoad = 44;
-        static const int patchLengthGetByIdExternalLoad = 16;
         static const int patchOffsetGetByIdPropertyMapOffset = 60;
         static const int patchOffsetGetByIdPutResult = 76;
 #if ENABLE(OPCODE_SAMPLING)
@@ -667,15 +709,17 @@ namespace JSC {
 #endif // USE(JSVALUE32_64)
 
 #if (defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL)
-#define BEGIN_UNINTERRUPTED_SEQUENCE(name) do { beginUninterruptedSequence(); beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); } while (false)
-#define END_UNINTERRUPTED_SEQUENCE(name) do { endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); endUninterruptedSequence(); } while (false)
+#define BEGIN_UNINTERRUPTED_SEQUENCE(name) do { beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); } while (false)
+#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) do { endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace, dst); } while (false)
+#define END_UNINTERRUPTED_SEQUENCE(name) END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, 0)
 
         void beginUninterruptedSequence(int, int);
-        void endUninterruptedSequence(int, int);
+        void endUninterruptedSequence(int, int, int);
 
 #else
 #define BEGIN_UNINTERRUPTED_SEQUENCE(name)  do { beginUninterruptedSequence(); } while (false)
 #define END_UNINTERRUPTED_SEQUENCE(name)  do { endUninterruptedSequence(); } while (false)
+#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) do { endUninterruptedSequence(); } while (false)
 #endif
 
         void emit_op_add(Instruction*);
@@ -686,25 +730,31 @@ namespace JSC {
         void emit_op_call(Instruction*);
         void emit_op_call_eval(Instruction*);
         void emit_op_call_varargs(Instruction*);
+        void emit_op_call_put_result(Instruction*);
         void emit_op_catch(Instruction*);
         void emit_op_construct(Instruction*);
-        void emit_op_construct_verify(Instruction*);
+        void emit_op_get_callee(Instruction*);
+        void emit_op_create_this(Instruction*);
         void emit_op_convert_this(Instruction*);
+        void emit_op_convert_this_strict(Instruction*);
         void emit_op_create_arguments(Instruction*);
         void emit_op_debug(Instruction*);
         void emit_op_del_by_id(Instruction*);
         void emit_op_div(Instruction*);
         void emit_op_end(Instruction*);
         void emit_op_enter(Instruction*);
-        void emit_op_enter_with_activation(Instruction*);
+        void emit_op_create_activation(Instruction*);
         void emit_op_eq(Instruction*);
         void emit_op_eq_null(Instruction*);
         void emit_op_get_by_id(Instruction*);
+        void emit_op_get_arguments_length(Instruction*);
         void emit_op_get_by_val(Instruction*);
+        void emit_op_get_argument_by_val(Instruction*);
         void emit_op_get_by_pname(Instruction*);
         void emit_op_get_global_var(Instruction*);
         void emit_op_get_scoped_var(Instruction*);
-        void emit_op_init_arguments(Instruction*);
+        void emit_op_init_lazy_reg(Instruction*);
+        void emit_op_check_has_instance(Instruction*);
         void emit_op_instanceof(Instruction*);
         void emit_op_jeq_null(Instruction*);
         void emit_op_jfalse(Instruction*);
@@ -733,7 +783,7 @@ namespace JSC {
         void emit_op_neq(Instruction*);
         void emit_op_neq_null(Instruction*);
         void emit_op_new_array(Instruction*);
-        void emit_op_new_error(Instruction*);
+        void emit_op_new_array_buffer(Instruction*);
         void emit_op_new_func(Instruction*);
         void emit_op_new_func_exp(Instruction*);
         void emit_op_new_object(Instruction*);
@@ -760,11 +810,13 @@ namespace JSC {
         void emit_op_put_setter(Instruction*);
         void emit_op_resolve(Instruction*);
         void emit_op_resolve_base(Instruction*);
+        void emit_op_ensure_property_exists(Instruction*);
         void emit_op_resolve_global(Instruction*, bool dynamic = false);
         void emit_op_resolve_global_dynamic(Instruction*);
         void emit_op_resolve_skip(Instruction*);
         void emit_op_resolve_with_base(Instruction*);
         void emit_op_ret(Instruction*);
+        void emit_op_ret_object_or_this(Instruction*);
         void emit_op_rshift(Instruction*);
         void emit_op_sret(Instruction*);
         void emit_op_strcat(Instruction*);
@@ -776,11 +828,12 @@ namespace JSC {
         void emit_op_tear_off_activation(Instruction*);
         void emit_op_tear_off_arguments(Instruction*);
         void emit_op_throw(Instruction*);
+        void emit_op_throw_reference_error(Instruction*);
         void emit_op_to_jsnumber(Instruction*);
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
         void emit_op_urshift(Instruction*);
-#if ENABLE(JIT_OPTIMIZE_MOD)
+#if ENABLE(JIT_USE_SOFT_MODULO)
         void softModulo();
 #endif
 
@@ -793,13 +846,16 @@ namespace JSC {
         void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
-        void emitSlow_op_construct_verify(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_convert_this_strict(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_check_has_instance(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -807,6 +863,7 @@ namespace JSC {
         void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&, bool invert = false);
         void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_load_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
@@ -838,21 +895,14 @@ namespace JSC {
         void emitRightShift(Instruction*, bool isUnsigned);
         void emitRightShiftSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator&, bool isUnsigned);
 
-        /* These functions are deprecated: Please use JITStubCall instead. */
-        void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
-#if USE(JSVALUE32_64)
-        void emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber);
-        void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2);
-#else
-        void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
-#endif
-        void emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber);
-        void emitPutJITStubArgConstant(void* value, unsigned argumentNumber);
+        /* This function is deprecated. */
         void emitGetJITStubArg(unsigned argumentNumber, RegisterID dst);
 
         void emitInitRegister(unsigned dst);
 
         void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
+        void emitPutCellToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry);
+        void emitPutIntToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry);
         void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry);
         void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister);
         void emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister);
@@ -861,6 +911,8 @@ namespace JSC {
         bool isOperandConstantImmediateInt(unsigned src);
         bool isOperandConstantImmediateChar(unsigned src);
 
+        bool atJumpTarget();
+
         Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
         {
             return iter++->from;
@@ -921,7 +973,7 @@ namespace JSC {
         Vector<MethodCallCompilationInfo> m_methodCallCompilationInfo;
         Vector<JumpTable> m_jmpTable;
 
-        unsigned m_bytecodeIndex;
+        unsigned m_bytecodeOffset;
         Vector<JSRInfo> m_jsrSites;
         Vector<SlowCaseEntry> m_slowCases;
         Vector<SwitchRecord> m_switches;
@@ -932,14 +984,14 @@ namespace JSC {
 
 #if USE(JSVALUE32_64)
         unsigned m_jumpTargetIndex;
-        unsigned m_mappedBytecodeIndex;
+        unsigned m_mappedBytecodeOffset;
         unsigned m_mappedVirtualRegisterIndex;
         RegisterID m_mappedTag;
         RegisterID m_mappedPayload;
 #else
         int m_lastResultBytecodeRegister;
-        unsigned m_jumpTargetsPosition;
 #endif
+        unsigned m_jumpTargetsPosition;
 
 #ifndef NDEBUG
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
@@ -947,8 +999,8 @@ namespace JSC {
         int m_uninterruptedConstantSequenceBegin;
 #endif
 #endif
-        void* m_linkerOffset;
-        static PassRefPtr<NativeExecutable> stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool);
+        WeakRandom m_randomGenerator;
+        static CodePtr stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool);
     } JIT_CLASS_ALIGNMENT;
 
     inline void JIT::emit_op_loop(Instruction* currentInstruction)
index cd39b3ad01c1ff45e15551efbbe01f0c12b633fc..c2a84c5a4a634e36b6b469da5088e01c6866cc9d 100644 (file)
  */
 
 #include "config.h"
-#include "JIT.h"
 
 #if ENABLE(JIT)
+#if USE(JSVALUE64)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
@@ -46,8 +47,6 @@ using namespace std;
 
 namespace JSC {
 
-#if !USE(JSVALUE32_64)
-
 void JIT::emit_op_lshift(Instruction* currentInstruction)
 {
     unsigned result = currentInstruction[1].u.operand;
@@ -61,10 +60,6 @@ void JIT::emit_op_lshift(Instruction* currentInstruction)
     emitFastArithImmToInt(regT0);
     emitFastArithImmToInt(regT2);
     lshift32(regT2, regT0);
-#if USE(JSVALUE32)
-    addSlowCase(branchAdd32(Overflow, regT0, regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
     emitFastArithReTagImmediate(regT0, regT0);
     emitPutVirtualRegister(result);
 }
@@ -75,20 +70,10 @@ void JIT::emitSlow_op_lshift(Instruction* currentInstruction, Vector<SlowCaseEnt
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
-#if USE(JSVALUE64)
     UNUSED_PARAM(op1);
     UNUSED_PARAM(op2);
     linkSlowCase(iter);
     linkSlowCase(iter);
-#else
-    // If we are limited to 32-bit immediates there is a third slow case, which required the operands to have been reloaded.
-    Jump notImm1 = getSlowCase(iter);
-    Jump notImm2 = getSlowCase(iter);
-    linkSlowCase(iter);
-    emitGetVirtualRegisters(op1, regT0, op2, regT2);
-    notImm1.link(this);
-    notImm2.link(this);
-#endif
     JITStubCall stubCall(this, cti_op_lshift);
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT2);
@@ -111,20 +96,11 @@ void JIT::emit_op_rshift(Instruction* currentInstruction)
         emitGetVirtualRegisters(op1, regT0, op2, regT2);
         if (supportsFloatingPointTruncate()) {
             Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
-#if USE(JSVALUE64)
             // supportsFloatingPoint() && USE(JSVALUE64) => 3 SlowCases
             addSlowCase(emitJumpIfNotImmediateNumber(regT0));
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
             addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
-#else
-            // supportsFloatingPoint() && !USE(JSVALUE64) => 5 SlowCases (of which 1 IfNotJSCell)
-            emitJumpSlowCaseIfNotJSCell(regT0, op1);
-            addSlowCase(checkStructure(regT0, m_globalData->numberStructure.get()));
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-            addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
-            addSlowCase(branchAdd32(Overflow, regT0, regT0));
-#endif
             lhsIsInt.link(this);
             emitJumpSlowCaseIfNotImmediateInteger(regT2);
         } else {
@@ -134,15 +110,8 @@ void JIT::emit_op_rshift(Instruction* currentInstruction)
         }
         emitFastArithImmToInt(regT2);
         rshift32(regT2, regT0);
-#if USE(JSVALUE32)
-        signExtend32ToPtr(regT0, regT0);
-#endif
     }
-#if USE(JSVALUE64)
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
-#endif
     emitPutVirtualRegister(result);
 }
 
@@ -160,17 +129,9 @@ void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEnt
         stubCall.addArgument(op2, regT2);
     } else {
         if (supportsFloatingPointTruncate()) {
-#if USE(JSVALUE64)
             linkSlowCase(iter);
             linkSlowCase(iter);
             linkSlowCase(iter);
-#else
-            linkSlowCaseIfNotJSCell(iter, op1);
-            linkSlowCase(iter);
-            linkSlowCase(iter);
-            linkSlowCase(iter);
-            linkSlowCase(iter);
-#endif
             // We're reloading op1 to regT0 as we can no longer guarantee that
             // we have not munged the operand.  It may have already been shifted
             // correctly, but it still will not have been tagged.
@@ -206,11 +167,7 @@ void JIT::emit_op_urshift(Instruction* currentInstruction)
         // a toUint conversion, which can result in a value we can represent
         // as an immediate int.
         if (shift < 0 || !(shift & 31))
-            addSlowCase(branch32(LessThan, regT0, Imm32(0)));
-#if USE(JSVALUE32)
-        addSlowCase(branchAdd32(Overflow, regT0, regT0));
-        signExtend32ToPtr(regT0, regT0);
-#endif
+            addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
         emitFastArithReTagImmediate(regT0, regT0);
         emitPutVirtualRegister(dst, regT0);
         return;
@@ -222,11 +179,7 @@ void JIT::emit_op_urshift(Instruction* currentInstruction)
     emitFastArithImmToInt(regT0);
     emitFastArithImmToInt(regT1);
     urshift32(regT1, regT0);
-    addSlowCase(branch32(LessThan, regT0, Imm32(0)));
-#if USE(JSVALUE32)
-    addSlowCase(branchAdd32(Overflow, regT0, regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
+    addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
     emitFastArithReTagImmediate(regT0, regT0);
     emitPutVirtualRegister(dst, regT0);
 }
@@ -240,7 +193,6 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn
         int shift = getConstantOperand(op2).asInt32();
         // op1 = regT0
         linkSlowCase(iter); // int32 check
-#if USE(JSVALUE64)
         if (supportsFloatingPointTruncate()) {
             JumpList failures;
             failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
@@ -250,24 +202,19 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn
             if (shift)
                 urshift32(Imm32(shift & 0x1f), regT0);
             if (shift < 0 || !(shift & 31))
-                failures.append(branch32(LessThan, regT0, Imm32(0)));
+                failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
             emitFastArithReTagImmediate(regT0, regT0);
             emitPutVirtualRegister(dst, regT0);
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
             failures.link(this);
         }
-#endif // JSVALUE64
         if (shift < 0 || !(shift & 31))
             linkSlowCase(iter); // failed to box in hot path
-#if USE(JSVALUE32)
-        linkSlowCase(iter); // Couldn't box result
-#endif
     } else {
         // op1 = regT0
         // op2 = regT1
         if (!isOperandConstantImmediateInt(op1)) {
             linkSlowCase(iter); // int32 check -- op1 is not an int
-#if USE(JSVALUE64)
             if (supportsFloatingPointTruncate()) {
                 JumpList failures;
                 failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
@@ -277,20 +224,16 @@ void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEn
                 failures.append(emitJumpIfNotImmediateInteger(regT1)); // op2 is not an int
                 emitFastArithImmToInt(regT1);
                 urshift32(regT1, regT0);
-                failures.append(branch32(LessThan, regT0, Imm32(0)));
+                failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
                 emitFastArithReTagImmediate(regT0, regT0);
                 emitPutVirtualRegister(dst, regT0);
                 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
                 failures.link(this);
             }
-#endif
         }
         
         linkSlowCase(iter); // int32 check - op2 is not an int
         linkSlowCase(iter); // Can't represent unsigned result as an immediate
-#if USE(JSVALUE32)
-        linkSlowCase(iter); // Couldn't box result
-#endif
     }
     
     JITStubCall stubCall(this, cti_op_urshift);
@@ -331,20 +274,12 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
-#else
-        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
-#endif
         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
         int32_t op1imm = getConstantOperandImmediateInt(op1);
-#else
-        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
-#endif
         addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
@@ -382,18 +317,9 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1 = emitJumpIfNotJSCell(regT0);
-
-            Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-#endif
 
             int32_t op2imm = getConstantOperand(op2).asInt32();;
 
@@ -404,13 +330,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -423,18 +343,9 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1 = emitJumpIfNotJSCell(regT1);
-
-            Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
-            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-#endif
 
             int32_t op1imm = getConstantOperand(op1).asInt32();;
 
@@ -445,13 +356,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -464,7 +369,6 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
             Jump fail3 = emitJumpIfImmediateInteger(regT1);
@@ -472,37 +376,14 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT0, fpRegT0);
             movePtrToDouble(regT1, fpRegT1);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1 = emitJumpIfNotJSCell(regT0);
-
-            Jump fail2;
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail2 = emitJumpIfNotJSCell(regT1);
-
-            Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
-            Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-#endif
 
             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail2.link(this);
             fail3.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail2.link(this);
-            fail3.link(this);
-            fail4.link(this);
-#endif
         }
 
         linkSlowCase(iter);
@@ -546,20 +427,12 @@ void JIT::emit_op_jless(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
-#else
-        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
-#endif
         addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
         int32_t op1imm = getConstantOperandImmediateInt(op1);
-#else
-        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
-#endif
         addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
@@ -597,18 +470,9 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1 = emitJumpIfNotJSCell(regT0);
-
-            Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-#endif
 
             int32_t op2imm = getConstantOperand(op2).asInt32();
 
@@ -619,13 +483,7 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -638,18 +496,9 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1 = emitJumpIfNotJSCell(regT1);
-
-            Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
-            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-#endif
 
             int32_t op1imm = getConstantOperand(op1).asInt32();
 
@@ -660,13 +509,7 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -679,7 +522,6 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
             Jump fail3 = emitJumpIfImmediateInteger(regT1);
@@ -687,37 +529,14 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT0, fpRegT0);
             movePtrToDouble(regT1, fpRegT1);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1 = emitJumpIfNotJSCell(regT0);
-
-            Jump fail2;
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail2 = emitJumpIfNotJSCell(regT1);
-
-            Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
-            Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-#endif
 
             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail2.link(this);
             fail3.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail2.link(this);
-            fail3.link(this);
-            fail4.link(this);
-#endif
         }
 
         linkSlowCase(iter);
@@ -761,20 +580,12 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
-#else
-        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
-#endif
         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
         int32_t op1imm = getConstantOperandImmediateInt(op1);
-#else
-        int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)));
-#endif
         addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT1, Imm32(op1imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
@@ -813,18 +624,9 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1 = emitJumpIfNotJSCell(regT0);
-
-            Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get());
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-#endif
 
             int32_t op2imm = getConstantOperand(op2).asInt32();;
 
@@ -835,13 +637,7 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
-#if USE(JSVALUE64)
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jlesseq);
@@ -854,18 +650,9 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1 = emitJumpIfNotJSCell(regT1);
-
-            Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get());
-            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-#endif
 
             int32_t op1imm = getConstantOperand(op1).asInt32();;
 
@@ -876,13 +663,7 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
-#if USE(JSVALUE64)
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jlesseq);
@@ -895,7 +676,6 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
             Jump fail3 = emitJumpIfImmediateInteger(regT1);
@@ -903,37 +683,14 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT0, fpRegT0);
             movePtrToDouble(regT1, fpRegT1);
-#else
-            Jump fail1;
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1 = emitJumpIfNotJSCell(regT0);
-
-            Jump fail2;
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail2 = emitJumpIfNotJSCell(regT1);
-
-            Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get());
-            Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get());
-            loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-            loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-#endif
 
             emitJumpSlowToHot(branchDouble(invert ? DoubleLessThanOrUnordered : DoubleGreaterThanOrEqual, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail2.link(this);
             fail3.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail2.link(this);
-            fail3.link(this);
-            fail4.link(this);
-#endif
         }
 
         linkSlowCase(iter);
@@ -964,25 +721,17 @@ void JIT::emit_op_bitand(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t imm = getConstantOperandImmediateInt(op1);
         andPtr(Imm32(imm), regT0);
         if (imm >= 0)
             emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-        andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1)))), regT0);
-#endif
     } else if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t imm = getConstantOperandImmediateInt(op2);
         andPtr(Imm32(imm), regT0);
         if (imm >= 0)
             emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-        andPtr(Imm32(static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)))), regT0);
-#endif
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
         andPtr(regT1, regT0);
@@ -1024,13 +773,8 @@ void JIT::emit_op_post_inc(Instruction* currentInstruction)
     emitGetVirtualRegister(srcDst, regT0);
     move(regT0, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-    addSlowCase(branchAdd32(Overflow, Imm32(1), regT1));
+    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT1));
     emitFastArithIntToImmNoCheck(regT1, regT1);
-#else
-    addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
-    signExtend32ToPtr(regT1, regT1);
-#endif
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
 }
@@ -1056,13 +800,8 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction)
     emitGetVirtualRegister(srcDst, regT0);
     move(regT0, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-    addSlowCase(branchSub32(Zero, Imm32(1), regT1));
+    addSlowCase(branchSub32(Zero, TrustedImm32(1), regT1));
     emitFastArithIntToImmNoCheck(regT1, regT1);
-#else
-    addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
-    signExtend32ToPtr(regT1, regT1);
-#endif
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
 }
@@ -1086,13 +825,8 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction)
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-    addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
     emitPutVirtualRegister(srcDst);
 }
 
@@ -1115,13 +849,8 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction)
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-    addSlowCase(branchSub32(Zero, Imm32(1), regT0));
+    addSlowCase(branchSub32(Zero, TrustedImm32(1), regT0));
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
     emitPutVirtualRegister(srcDst);
 }
 
@@ -1140,7 +869,7 @@ void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEn
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if CPU(X86) || CPU(X86_64)
+#if CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1148,21 +877,21 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
-    emitGetVirtualRegisters(op1, X86Registers::eax, op2, X86Registers::ecx);
-    emitJumpSlowCaseIfNotImmediateInteger(X86Registers::eax);
-    emitJumpSlowCaseIfNotImmediateInteger(X86Registers::ecx);
-#if USE(JSVALUE64)
-    addSlowCase(branchPtr(Equal, X86Registers::ecx, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))));
-    m_assembler.cdq();
-    m_assembler.idivl_r(X86Registers::ecx);
-#else
-    emitFastArithDeTagImmediate(X86Registers::eax);
-    addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86Registers::ecx));
-    m_assembler.cdq();
-    m_assembler.idivl_r(X86Registers::ecx);
-    signExtend32ToPtr(X86Registers::edx, X86Registers::edx);
+#if CPU(X86) || CPU(X86_64)
+    // Make sure registers are correct for x86 IDIV instructions.
+    ASSERT(regT0 == X86Registers::eax);
+    ASSERT(regT1 == X86Registers::edx);
+    ASSERT(regT2 == X86Registers::ecx);
 #endif
-    emitFastArithReTagImmediate(X86Registers::edx, X86Registers::eax);
+
+    emitGetVirtualRegisters(op1, regT0, op2, regT2);
+    emitJumpSlowCaseIfNotImmediateInteger(regT0);
+    emitJumpSlowCaseIfNotImmediateInteger(regT2);
+
+    addSlowCase(branchPtr(Equal, regT2, TrustedImmPtr(JSValue::encode(jsNumber(0)))));
+    m_assembler.cdq();
+    m_assembler.idivl_r(regT2);
+    emitFastArithReTagImmediate(regT1, regT0);
     emitPutVirtualRegister(result);
 }
 
@@ -1170,26 +899,16 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
 {
     unsigned result = currentInstruction[1].u.operand;
 
-#if USE(JSVALUE64)
-    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
-#else
-    Jump notImm1 = getSlowCase(iter);
-    Jump notImm2 = getSlowCase(iter);
     linkSlowCase(iter);
-    emitFastArithReTagImmediate(X86Registers::eax, X86Registers::eax);
-    emitFastArithReTagImmediate(X86Registers::ecx, X86Registers::ecx);
-    notImm1.link(this);
-    notImm2.link(this);
-#endif
     JITStubCall stubCall(this, cti_op_mod);
-    stubCall.addArgument(X86Registers::eax);
-    stubCall.addArgument(X86Registers::ecx);
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(regT2);
     stubCall.call(result);
 }
 
-#else // CPU(X86) || CPU(X86_64)
+#else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1197,27 +916,15 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
-#if ENABLE(JIT_OPTIMIZE_MOD)
-    emitGetVirtualRegisters(op1, regT0, op2, regT2);
-    emitJumpSlowCaseIfNotImmediateInteger(regT0);
-    emitJumpSlowCaseIfNotImmediateInteger(regT2);
-
-    addSlowCase(branch32(Equal, regT2, Imm32(1)));
-
-    emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
-
-    emitPutVirtualRegister(result, regT0);
-#else
     JITStubCall stubCall(this, cti_op_mod);
     stubCall.addArgument(op1, regT2);
     stubCall.addArgument(op2, regT2);
     stubCall.call(result);
-#endif
 }
 
 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-#if ENABLE(JIT_OPTIMIZE_MOD)
+#if ENABLE(JIT_USE_SOFT_MODULO)
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
@@ -1237,8 +944,6 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
-#if USE(JSVALUE64)
-
 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
 
 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsigned op2, OperandTypes)
@@ -1261,7 +966,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned, unsigned op1, unsign
 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned result, unsigned op1, unsigned op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)
 {
     // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.
-    COMPILE_ASSERT(((JSImmediate::TagTypeNumber + JSImmediate::DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
+    COMPILE_ASSERT(((TagTypeNumber + DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);
 
     Jump notImm1;
     Jump notImm2;
@@ -1390,7 +1095,7 @@ void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1);
     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2);
-    compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
+    compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types, op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
 }
 
 void JIT::emit_op_mul(Instruction* currentInstruction)
@@ -1427,7 +1132,7 @@ void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
     bool op1HasImmediateIntFastCase = isOperandConstantImmediateInt(op1) && getConstantOperandImmediateInt(op1) > 0;
     bool op2HasImmediateIntFastCase = !op1HasImmediateIntFastCase && isOperandConstantImmediateInt(op2) && getConstantOperandImmediateInt(op2) > 0;
-    compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand), op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
+    compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, types, op1HasImmediateIntFastCase, op2HasImmediateIntFastCase);
 }
 
 void JIT::emit_op_div(Instruction* currentInstruction)
@@ -1531,311 +1236,9 @@ void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>
     compileBinaryArithOpSlowCase(op_sub, iter, result, op1, op2, types, false, false);
 }
 
-#else // USE(JSVALUE64)
-
-/* ------------------------------ BEGIN: !USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */
-
-void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
-{
-    Structure* numberStructure = m_globalData->numberStructure.get();
-    Jump wasJSNumberCell1;
-    Jump wasJSNumberCell2;
-
-    emitGetVirtualRegisters(src1, regT0, src2, regT1);
-
-    if (types.second().isReusable() && supportsFloatingPoint()) {
-        ASSERT(types.second().mightBeNumber());
-
-        // Check op2 is a number
-        Jump op2imm = emitJumpIfImmediateInteger(regT1);
-        if (!types.second().definitelyIsNumber()) {
-            emitJumpSlowCaseIfNotJSCell(regT1, src2);
-            addSlowCase(checkStructure(regT1, numberStructure));
-        }
-
-        // (1) In this case src2 is a reusable number cell.
-        //     Slow case if src1 is not a number type.
-        Jump op1imm = emitJumpIfImmediateInteger(regT0);
-        if (!types.first().definitelyIsNumber()) {
-            emitJumpSlowCaseIfNotJSCell(regT0, src1);
-            addSlowCase(checkStructure(regT0, numberStructure));
-        }
-
-        // (1a) if we get here, src1 is also a number cell
-        loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-        Jump loadedDouble = jump();
-        // (1b) if we get here, src1 is an immediate
-        op1imm.link(this);
-        emitFastArithImmToInt(regT0);
-        convertInt32ToDouble(regT0, fpRegT0);
-        // (1c)
-        loadedDouble.link(this);
-        if (opcodeID == op_add)
-            addDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-        else if (opcodeID == op_sub)
-            subDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-        else {
-            ASSERT(opcodeID == op_mul);
-            mulDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-        }
-
-        // Store the result to the JSNumberCell and jump.
-        storeDouble(fpRegT0, Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)));
-        move(regT1, regT0);
-        emitPutVirtualRegister(dst);
-        wasJSNumberCell2 = jump();
-
-        // (2) This handles cases where src2 is an immediate number.
-        //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
-        op2imm.link(this);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-    } else if (types.first().isReusable() && supportsFloatingPoint()) {
-        ASSERT(types.first().mightBeNumber());
-
-        // Check op1 is a number
-        Jump op1imm = emitJumpIfImmediateInteger(regT0);
-        if (!types.first().definitelyIsNumber()) {
-            emitJumpSlowCaseIfNotJSCell(regT0, src1);
-            addSlowCase(checkStructure(regT0, numberStructure));
-        }
-
-        // (1) In this case src1 is a reusable number cell.
-        //     Slow case if src2 is not a number type.
-        Jump op2imm = emitJumpIfImmediateInteger(regT1);
-        if (!types.second().definitelyIsNumber()) {
-            emitJumpSlowCaseIfNotJSCell(regT1, src2);
-            addSlowCase(checkStructure(regT1, numberStructure));
-        }
-
-        // (1a) if we get here, src2 is also a number cell
-        loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1);
-        Jump loadedDouble = jump();
-        // (1b) if we get here, src2 is an immediate
-        op2imm.link(this);
-        emitFastArithImmToInt(regT1);
-        convertInt32ToDouble(regT1, fpRegT1);
-        // (1c)
-        loadedDouble.link(this);
-        loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0);
-        if (opcodeID == op_add)
-            addDouble(fpRegT1, fpRegT0);
-        else if (opcodeID == op_sub)
-            subDouble(fpRegT1, fpRegT0);
-        else {
-            ASSERT(opcodeID == op_mul);
-            mulDouble(fpRegT1, fpRegT0);
-        }
-        storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
-        emitPutVirtualRegister(dst);
-
-        // Store the result to the JSNumberCell and jump.
-        storeDouble(fpRegT0, Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)));
-        emitPutVirtualRegister(dst);
-        wasJSNumberCell1 = jump();
-
-        // (2) This handles cases where src1 is an immediate number.
-        //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
-        op1imm.link(this);
-        emitJumpSlowCaseIfNotImmediateInteger(regT1);
-    } else
-        emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
-
-    if (opcodeID == op_add) {
-        emitFastArithDeTagImmediate(regT0);
-        addSlowCase(branchAdd32(Overflow, regT1, regT0));
-    } else  if (opcodeID == op_sub) {
-        addSlowCase(branchSub32(Overflow, regT1, regT0));
-        signExtend32ToPtr(regT0, regT0);
-        emitFastArithReTagImmediate(regT0, regT0);
-    } else {
-        ASSERT(opcodeID == op_mul);
-        // convert eax & edx from JSImmediates to ints, and check if either are zero
-        emitFastArithImmToInt(regT1);
-        Jump op1Zero = emitFastArithDeTagImmediateJumpIfZero(regT0);
-        Jump op2NonZero = branchTest32(NonZero, regT1);
-        op1Zero.link(this);
-        // if either input is zero, add the two together, and check if the result is < 0.
-        // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate.
-        move(regT0, regT2);
-        addSlowCase(branchAdd32(Signed, regT1, regT2));
-        // Skip the above check if neither input is zero
-        op2NonZero.link(this);
-        addSlowCase(branchMul32(Overflow, regT1, regT0));
-        signExtend32ToPtr(regT0, regT0);
-        emitFastArithReTagImmediate(regT0, regT0);
-    }
-    emitPutVirtualRegister(dst);
-
-    if (types.second().isReusable() && supportsFloatingPoint())
-        wasJSNumberCell2.link(this);
-    else if (types.first().isReusable() && supportsFloatingPoint())
-        wasJSNumberCell1.link(this);
-}
-
-void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types)
-{
-    linkSlowCase(iter);
-    if (types.second().isReusable() && supportsFloatingPoint()) {
-        if (!types.first().definitelyIsNumber()) {
-            linkSlowCaseIfNotJSCell(iter, src1);
-            linkSlowCase(iter);
-        }
-        if (!types.second().definitelyIsNumber()) {
-            linkSlowCaseIfNotJSCell(iter, src2);
-            linkSlowCase(iter);
-        }
-    } else if (types.first().isReusable() && supportsFloatingPoint()) {
-        if (!types.first().definitelyIsNumber()) {
-            linkSlowCaseIfNotJSCell(iter, src1);
-            linkSlowCase(iter);
-        }
-        if (!types.second().definitelyIsNumber()) {
-            linkSlowCaseIfNotJSCell(iter, src2);
-            linkSlowCase(iter);
-        }
-    }
-    linkSlowCase(iter);
-
-    // additional entry point to handle -0 cases.
-    if (opcodeID == op_mul)
-        linkSlowCase(iter);
-
-    JITStubCall stubCall(this, opcodeID == op_add ? cti_op_add : opcodeID == op_sub ? cti_op_sub : cti_op_mul);
-    stubCall.addArgument(src1, regT2);
-    stubCall.addArgument(src2, regT2);
-    stubCall.call(dst);
-}
-
-void JIT::emit_op_add(Instruction* currentInstruction)
-{
-    unsigned result = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
-
-    if (!types.first().mightBeNumber() || !types.second().mightBeNumber()) {
-        JITStubCall stubCall(this, cti_op_add);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call(result);
-        return;
-    }
-
-    if (isOperandConstantImmediateInt(op1)) {
-        emitGetVirtualRegister(op2, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0));
-        signExtend32ToPtr(regT0, regT0);
-        emitPutVirtualRegister(result);
-    } else if (isOperandConstantImmediateInt(op2)) {
-        emitGetVirtualRegister(op1, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        addSlowCase(branchAdd32(Overflow, Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0));
-        signExtend32ToPtr(regT0, regT0);
-        emitPutVirtualRegister(result);
-    } else {
-        compileBinaryArithOp(op_add, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
-    }
-}
-
-void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned result = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-
-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
-    if (!types.first().mightBeNumber() || !types.second().mightBeNumber())
-        return;
-
-    if (isOperandConstantImmediateInt(op1)) {
-        Jump notImm = getSlowCase(iter);
-        linkSlowCase(iter);
-        sub32(Imm32(getConstantOperandImmediateInt(op1) << JSImmediate::IntegerPayloadShift), regT0);
-        notImm.link(this);
-        JITStubCall stubCall(this, cti_op_add);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(regT0);
-        stubCall.call(result);
-    } else if (isOperandConstantImmediateInt(op2)) {
-        Jump notImm = getSlowCase(iter);
-        linkSlowCase(iter);
-        sub32(Imm32(getConstantOperandImmediateInt(op2) << JSImmediate::IntegerPayloadShift), regT0);
-        notImm.link(this);
-        JITStubCall stubCall(this, cti_op_add);
-        stubCall.addArgument(regT0);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call(result);
-    } else {
-        OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
-        ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
-        compileBinaryArithOpSlowCase(op_add, iter, result, op1, op2, types);
-    }
-}
-
-void JIT::emit_op_mul(Instruction* currentInstruction)
-{
-    unsigned result = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-
-    // For now, only plant a fast int case if the constant operand is greater than zero.
-    int32_t value;
-    if (isOperandConstantImmediateInt(op1) && ((value = getConstantOperandImmediateInt(op1)) > 0)) {
-        emitGetVirtualRegister(op2, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        emitFastArithDeTagImmediate(regT0);
-        addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
-        signExtend32ToPtr(regT0, regT0);
-        emitFastArithReTagImmediate(regT0, regT0);
-        emitPutVirtualRegister(result);
-    } else if (isOperandConstantImmediateInt(op2) && ((value = getConstantOperandImmediateInt(op2)) > 0)) {
-        emitGetVirtualRegister(op1, regT0);
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-        emitFastArithDeTagImmediate(regT0);
-        addSlowCase(branchMul32(Overflow, Imm32(value), regT0, regT0));
-        signExtend32ToPtr(regT0, regT0);
-        emitFastArithReTagImmediate(regT0, regT0);
-        emitPutVirtualRegister(result);
-    } else
-        compileBinaryArithOp(op_mul, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
-}
-
-void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned result = currentInstruction[1].u.operand;
-    unsigned op1 = currentInstruction[2].u.operand;
-    unsigned op2 = currentInstruction[3].u.operand;
-
-    if ((isOperandConstantImmediateInt(op1) && (getConstantOperandImmediateInt(op1) > 0))
-        || (isOperandConstantImmediateInt(op2) && (getConstantOperandImmediateInt(op2) > 0))) {
-        linkSlowCase(iter);
-        linkSlowCase(iter);
-        // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
-        JITStubCall stubCall(this, cti_op_mul);
-        stubCall.addArgument(op1, regT2);
-        stubCall.addArgument(op2, regT2);
-        stubCall.call(result);
-    } else
-        compileBinaryArithOpSlowCase(op_mul, iter, result, op1, op2, OperandTypes::fromInt(currentInstruction[4].u.operand));
-}
-
-void JIT::emit_op_sub(Instruction* currentInstruction)
-{
-    compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
-}
-
-void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
-}
-
-#endif // USE(JSVALUE64)
-
 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
 
-#endif // !USE(JSVALUE32_64)
-
 } // namespace JSC
 
+#endif // USE(JSVALUE64)
 #endif // ENABLE(JIT)
index 3e5adc955b94e730f2fa9646fcccdda309a5c35d..67946548dc14309a3fb6ab884d571edd0bc76985 100644 (file)
 */
 
 #include "config.h"
-#include "JIT.h"
 
 #if ENABLE(JIT)
+#if USE(JSVALUE32_64)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
@@ -46,8 +47,6 @@ using namespace std;
 
 namespace JSC {
 
-#if USE(JSVALUE32_64)
-
 void JIT::emit_op_negate(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -55,17 +54,17 @@ void JIT::emit_op_negate(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
-    Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
-    addSlowCase(branchTest32(Zero, regT0, Imm32(0x7fffffff)));
+    Jump srcNotInt = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
+    addSlowCase(branchTest32(Zero, regT0, TrustedImm32(0x7fffffff)));
     neg32(regT0);
     emitStoreInt32(dst, regT0, (dst == src));
 
     Jump end = jump();
 
     srcNotInt.link(this);
-    addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+    addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
 
-    xor32(Imm32(1 << 31), regT1);
+    xor32(TrustedImm32(1 << 31), regT1);
     store32(regT1, tagFor(dst));
     if (dst != src)
         store32(regT0, payloadFor(dst));
@@ -97,7 +96,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
     // Character less.
     if (isOperandConstantImmediateChar(op1)) {
         emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
@@ -106,7 +105,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
     }
     if (isOperandConstantImmediateChar(op2)) {
         emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
@@ -116,16 +115,16 @@ void JIT::emit_op_jnless(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         // Int32 less.
         emitLoad(op2, regT3, regT2);
-        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
-        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(GreaterThanOrEqual, regT0, regT2), target);
     }
 
@@ -186,7 +185,7 @@ void JIT::emit_op_jless(Instruction* currentInstruction)
     // Character less.
     if (isOperandConstantImmediateChar(op1)) {
         emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
@@ -195,7 +194,7 @@ void JIT::emit_op_jless(Instruction* currentInstruction)
     }
     if (isOperandConstantImmediateChar(op2)) {
         emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
@@ -204,16 +203,16 @@ void JIT::emit_op_jless(Instruction* currentInstruction)
     } 
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
-        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
-        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(LessThan, regT0, regT2), target);
     }
 
@@ -273,7 +272,7 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
     // Character less.
     if (isOperandConstantImmediateChar(op1)) {
         emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
@@ -282,7 +281,7 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
     }
     if (isOperandConstantImmediateChar(op2)) {
         emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
         JumpList failures;
         emitLoadCharacterString(regT0, regT0, failures);
         addSlowCase(failures);
@@ -291,16 +290,16 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
     }
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT3, regT2);
-        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(invert ? LessThan : GreaterThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target);
     } else if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
-        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
     } else {
         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-        notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+        notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(invert ? GreaterThan : LessThanOrEqual, regT0, regT2), target);
     }
 
@@ -369,7 +368,7 @@ void JIT::emit_op_lshift(Instruction* currentInstruction)
 
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         lshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
         emitStoreInt32(dst, regT0, dst == op1);
         return;
@@ -377,8 +376,8 @@ void JIT::emit_op_lshift(Instruction* currentInstruction)
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
     if (!isOperandConstantImmediateInt(op1))
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     lshift32(regT2, regT0);
     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
 }
@@ -411,7 +410,7 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned)
     // shift arguments, so any changes must be updated there as well.
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         int shift = getConstantOperand(op2).asInt32();
         if (isUnsigned) {
             if (shift)
@@ -420,7 +419,7 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned)
             // a toUint conversion, which can result in a value we can represent
             // as an immediate int.
             if (shift < 0 || !(shift & 31))
-                addSlowCase(branch32(LessThan, regT0, Imm32(0)));
+                addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
         } else if (shift) { // signed right shift by zero is simply toInt conversion
             rshift32(Imm32(shift & 0x1f), regT0);
         }
@@ -430,11 +429,11 @@ void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned)
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
     if (!isOperandConstantImmediateInt(op1))
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     if (isUnsigned) {
         urshift32(regT2, regT0);
-        addSlowCase(branch32(LessThan, regT0, Imm32(0)));
+        addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
     } else
         rshift32(regT2, regT0);
     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
@@ -451,14 +450,14 @@ void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCas
         linkSlowCase(iter); // int32 check
         if (supportsFloatingPointTruncate()) {
             JumpList failures;
-            failures.append(branch32(AboveOrEqual, regT1, Imm32(JSValue::LowestTag)));
+            failures.append(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag)));
             emitLoadDouble(op1, fpRegT0);
             failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
             if (isUnsigned) {
                 if (shift)
                     urshift32(Imm32(shift & 0x1f), regT0);
                 if (shift < 0 || !(shift & 31))
-                    failures.append(branch32(LessThan, regT0, Imm32(0)));
+                    failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
             } else if (shift)
                 rshift32(Imm32(shift & 0x1f), regT0);
             emitStoreInt32(dst, regT0, false);
@@ -473,9 +472,9 @@ void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCas
         if (!isOperandConstantImmediateInt(op1)) {
             linkSlowCase(iter); // int32 check -- op1 is not an int
             if (supportsFloatingPointTruncate()) {
-                Jump notDouble = branch32(Above, regT1, Imm32(JSValue::LowestTag)); // op1 is not a double
+                Jump notDouble = branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)); // op1 is not a double
                 emitLoadDouble(op1, fpRegT0);
-                Jump notInt = branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)); // op2 is not an int
+                Jump notInt = branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)); // op2 is not an int
                 Jump cantTruncate = branchTruncateDoubleToInt32(fpRegT0, regT0);
                 if (isUnsigned)
                     urshift32(regT2, regT0);
@@ -536,15 +535,15 @@ void JIT::emit_op_bitand(Instruction* currentInstruction)
     int32_t constant;
     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
         emitLoad(op, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         and32(Imm32(constant), regT0);
         emitStoreInt32(dst, regT0, (op == dst));
         return;
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     and32(regT2, regT0);
     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
 }
@@ -577,15 +576,15 @@ void JIT::emit_op_bitor(Instruction* currentInstruction)
     int32_t constant;
     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
         emitLoad(op, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         or32(Imm32(constant), regT0);
         emitStoreInt32(dst, regT0, (op == dst));
         return;
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     or32(regT2, regT0);
     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
 }
@@ -618,15 +617,15 @@ void JIT::emit_op_bitxor(Instruction* currentInstruction)
     int32_t constant;
     if (getOperandConstantImmediateInt(op1, op2, op, constant)) {
         emitLoad(op, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         xor32(Imm32(constant), regT0);
         emitStoreInt32(dst, regT0, (op == dst));
         return;
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     xor32(regT2, regT0);
     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
 }
@@ -655,7 +654,7 @@ void JIT::emit_op_bitnot(Instruction* currentInstruction)
     unsigned src = currentInstruction[2].u.operand;
 
     emitLoad(src, regT1, regT0);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
 
     not32(regT0);
     emitStoreInt32(dst, regT0, (dst == src));
@@ -680,14 +679,14 @@ void JIT::emit_op_post_inc(Instruction* currentInstruction)
     unsigned srcDst = currentInstruction[2].u.operand;
 
     emitLoad(srcDst, regT1, regT0);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
 
     if (dst == srcDst) // x = x++ is a noop for ints.
         return;
 
     emitStoreInt32(dst, regT0);
 
-    addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
     emitStoreInt32(srcDst, regT0, true);
 }
 
@@ -714,14 +713,14 @@ void JIT::emit_op_post_dec(Instruction* currentInstruction)
     unsigned srcDst = currentInstruction[2].u.operand;
 
     emitLoad(srcDst, regT1, regT0);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
 
     if (dst == srcDst) // x = x-- is a noop for ints.
         return;
 
     emitStoreInt32(dst, regT0);
 
-    addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
+    addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
     emitStoreInt32(srcDst, regT0, true);
 }
 
@@ -736,7 +735,7 @@ void JIT::emitSlow_op_post_dec(Instruction* currentInstruction, Vector<SlowCaseE
 
     JITStubCall stubCall(this, cti_op_post_dec);
     stubCall.addArgument(srcDst);
-    stubCall.addArgument(Imm32(srcDst));
+    stubCall.addArgument(TrustedImm32(srcDst));
     stubCall.call(dst);
 }
 
@@ -748,8 +747,8 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction)
 
     emitLoad(srcDst, regT1, regT0);
 
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
     emitStoreInt32(srcDst, regT0, true);
 }
 
@@ -773,8 +772,8 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction)
 
     emitLoad(srcDst, regT1, regT0);
 
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branchSub32(Overflow, Imm32(1), regT0));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branchSub32(Overflow, TrustedImm32(1), regT0));
     emitStoreInt32(srcDst, regT0, true);
 }
 
@@ -818,8 +817,8 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
     // Int32 case.
     addSlowCase(branchAdd32(Overflow, regT2, regT0));
@@ -841,7 +840,7 @@ void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultT
 {
     // Int32 case.
     emitLoad(op, regT1, regT0);
-    Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+    Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
     addSlowCase(branchAdd32(Overflow, Imm32(constant), regT0));
     emitStoreInt32(dst, regT0, (op == dst));
 
@@ -854,7 +853,7 @@ void JIT::emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultT
 
     notInt32.link(this);
     if (!opType.definitelyIsNumber())
-        addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+        addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
     move(Imm32(constant), regT2);
     convertInt32ToDouble(regT2, fpRegT0);
     emitLoadDouble(op, fpRegT1);
@@ -927,8 +926,8 @@ void JIT::emit_op_sub(Instruction* currentInstruction)
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
     // Int32 case.
     addSlowCase(branchSub32(Overflow, regT2, regT0));
@@ -950,7 +949,7 @@ void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultT
 {
     // Int32 case.
     emitLoad(op, regT1, regT0);
-    Jump notInt32 = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
+    Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
     addSlowCase(branchSub32(Overflow, Imm32(constant), regT0));
     emitStoreInt32(dst, regT0, (op == dst));
 
@@ -963,7 +962,7 @@ void JIT::emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultT
 
     notInt32.link(this);
     if (!opType.definitelyIsNumber())
-        addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+        addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
     move(Imm32(constant), regT2);
     convertInt32ToDouble(regT2, fpRegT0);
     emitLoadDouble(op, fpRegT1);
@@ -1020,15 +1019,15 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
 
         // Verify Op1 is double.
         if (!types.first().definitelyIsNumber())
-            addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
+            addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
 
         if (!op2IsInRegisters)
             emitLoad(op2, regT3, regT2);
 
-        Jump doubleOp2 = branch32(Below, regT3, Imm32(JSValue::LowestTag));
+        Jump doubleOp2 = branch32(Below, regT3, TrustedImm32(JSValue::LowestTag));
 
         if (!types.second().definitelyIsNumber())
-            addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+            addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
         convertInt32ToDouble(regT2, fpRegT0);
         Jump doTheMath = jump();
@@ -1097,7 +1096,7 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi
 
         // Verify op2 is double.
         if (!types.second().definitelyIsNumber())
-            addSlowCase(branch32(Above, regT3, Imm32(JSValue::LowestTag)));
+            addSlowCase(branch32(Above, regT3, TrustedImm32(JSValue::LowestTag)));
 
         // Do the math.
         switch (opcodeID) {
@@ -1158,8 +1157,8 @@ void JIT::emit_op_mul(Instruction* currentInstruction)
     JumpList notInt32Op2;
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
     // Int32 case.
     move(regT0, regT3);
@@ -1190,7 +1189,7 @@ void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>
     linkSlowCase(iter); // zero result check
 
     Jump negZero = branchOr32(Signed, regT2, regT3);
-    emitStoreInt32(dst, Imm32(0), (op1 == dst || op2 == dst));
+    emitStoreInt32(dst, TrustedImm32(0), (op1 == dst || op2 == dst));
 
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
 
@@ -1241,22 +1240,12 @@ void JIT::emit_op_div(Instruction* currentInstruction)
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
 
-    notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
     convertInt32ToDouble(regT0, fpRegT0);
     convertInt32ToDouble(regT2, fpRegT1);
     divDouble(fpRegT1, fpRegT0);
-
-    JumpList doubleResult;
-    branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1);
-
-    // Int32 result.
-    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
-    end.append(jump());
-
-    // Double result.
-    doubleResult.link(this);
     emitStoreDouble(dst, fpRegT0);
     end.append(jump());
 
@@ -1294,7 +1283,7 @@ void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if CPU(X86) || CPU(X86_64)
+#if CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1302,34 +1291,47 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
+#if CPU(X86) || CPU(X86_64)
+    // Make sure registers are correct for x86 IDIV instructions.
+    ASSERT(regT0 == X86Registers::eax);
+    ASSERT(regT1 == X86Registers::edx);
+    ASSERT(regT2 == X86Registers::ecx);
+    ASSERT(regT3 == X86Registers::ebx);
+#endif
+
     if (isOperandConstantImmediateInt(op2) && getConstantOperand(op2).asInt32() != 0) {
-        emitLoad(op1, X86Registers::edx, X86Registers::eax);
-        move(Imm32(getConstantOperand(op2).asInt32()), X86Registers::ecx);
-        addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
+        emitLoad(op1, regT1, regT0);
+        move(Imm32(getConstantOperand(op2).asInt32()), regT2);
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         if (getConstantOperand(op2).asInt32() == -1)
-            addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
+            addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
     } else {
-        emitLoad2(op1, X86Registers::edx, X86Registers::eax, op2, X86Registers::ebx, X86Registers::ecx);
-        addSlowCase(branch32(NotEqual, X86Registers::edx, Imm32(JSValue::Int32Tag)));
-        addSlowCase(branch32(NotEqual, X86Registers::ebx, Imm32(JSValue::Int32Tag)));
+        emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
-        addSlowCase(branch32(Equal, X86Registers::eax, Imm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
-        addSlowCase(branch32(Equal, X86Registers::ecx, Imm32(0))); // divide by 0
+        addSlowCase(branch32(Equal, regT0, TrustedImm32(0x80000000))); // -2147483648 / -1 => EXC_ARITHMETIC
+        addSlowCase(branch32(Equal, regT2, TrustedImm32(0))); // divide by 0
     }
 
-    move(X86Registers::eax, X86Registers::ebx); // Save dividend payload, in case of 0.
+    move(regT0, regT3); // Save dividend payload, in case of 0.
+#if CPU(X86) || CPU(X86_64)
     m_assembler.cdq();
-    m_assembler.idivl_r(X86Registers::ecx);
+    m_assembler.idivl_r(regT2);
+#elif CPU(MIPS)
+    m_assembler.div(regT0, regT2);
+    m_assembler.mfhi(regT1);
+#endif
 
     // If the remainder is zero and the dividend is negative, the result is -0.
-    Jump storeResult1 = branchTest32(NonZero, X86Registers::edx);
-    Jump storeResult2 = branchTest32(Zero, X86Registers::ebx, Imm32(0x80000000)); // not negative
-    emitStore(dst, jsNumber(m_globalData, -0.0));
+    Jump storeResult1 = branchTest32(NonZero, regT1);
+    Jump storeResult2 = branchTest32(Zero, regT3, TrustedImm32(0x80000000)); // not negative
+    emitStore(dst, jsNumber(-0.0));
     Jump end = jump();
 
     storeResult1.link(this);
     storeResult2.link(this);
-    emitStoreInt32(dst, X86Registers::edx, (op1 == dst || op2 == dst));
+    emitStoreInt32(dst, regT1, (op1 == dst || op2 == dst));
     end.link(this);
 }
 
@@ -1356,7 +1358,7 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
     stubCall.call(dst);
 }
 
-#else // CPU(X86) || CPU(X86_64)
+#else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
@@ -1364,14 +1366,14 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
 
-#if ENABLE(JIT_OPTIMIZE_MOD)
+#if ENABLE(JIT_USE_SOFT_MODULO)
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
-    addSlowCase(branch32(Equal, regT2, Imm32(0)));
+    addSlowCase(branch32(Equal, regT2, TrustedImm32(0)));
 
-    emitNakedCall(m_globalData->jitStubs.ctiSoftModulo());
+    emitNakedCall(m_globalData->jitStubs->ctiSoftModulo());
 
     emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
 #else
@@ -1384,7 +1386,9 @@ void JIT::emit_op_mod(Instruction* currentInstruction)
 
 void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
-#if ENABLE(JIT_OPTIMIZE_MOD)
+    UNUSED_PARAM(currentInstruction);
+    UNUSED_PARAM(iter);
+#if ENABLE(JIT_USE_SOFT_MODULO)
     unsigned result = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
@@ -1406,8 +1410,7 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
-#endif // USE(JSVALUE32_64)
-
-}
+} // namespace JSC
 
+#endif // USE(JSVALUE32_64)
 #endif // ENABLE(JIT)
index 625b40dbdf1dcafabdf0e51a143d4fb558684c09..d0c266836ea7a2fed215880a440f1dc5d3d6a2ef 100644 (file)
  */
 
 #include "config.h"
-#include "JIT.h"
 
 #if ENABLE(JIT)
+#if USE(JSVALUE64)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
@@ -45,455 +46,38 @@ using namespace std;
 
 namespace JSC {
 
-#if USE(JSVALUE32_64)
-
 void JIT::compileOpCallInitializeCallFrame()
 {
     // regT0 holds callee, regT1 holds argCount
-    store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // scopeChain
-
-    emitStore(static_cast<unsigned>(RegisterFile::OptionalCalleeArguments), JSValue());
-    storePtr(regT0, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); // callee
-    storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); // scopeChain
-}
-
-void JIT::compileOpCallSetupArgs(Instruction* instruction)
-{
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-
-    emitPutJITStubArg(regT1, regT0, 0);
-    emitPutJITStubArgConstant(registerOffset, 1);
-    emitPutJITStubArgConstant(argCount, 2);
-}
-          
-void JIT::compileOpConstructSetupArgs(Instruction* instruction)
-{
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-    int proto = instruction[5].u.operand;
-    int thisRegister = instruction[6].u.operand;
-
-    emitPutJITStubArg(regT1, regT0, 0);
-    emitPutJITStubArgConstant(registerOffset, 1);
-    emitPutJITStubArgConstant(argCount, 2);
-    emitPutJITStubArgFromVirtualRegister(proto, 3, regT2, regT3);
-    emitPutJITStubArgConstant(thisRegister, 4);
-}
-
-void JIT::compileOpCallVarargsSetupArgs(Instruction*)
-{
-    emitPutJITStubArg(regT1, regT0, 0);
-    emitPutJITStubArg(regT3, 1); // registerOffset
-    emitPutJITStubArg(regT2, 2); // argCount
-}
-
-void JIT::compileOpCallVarargs(Instruction* instruction)
-{
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCountRegister = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-
-    emitLoad(callee, regT1, regT0);
-    emitLoadPayload(argCountRegister, regT2); // argCount
-    addPtr(Imm32(registerOffset), regT2, regT3); // registerOffset
-
-    compileOpCallVarargsSetupArgs(instruction);
-
-    emitJumpSlowCaseIfNotJSCell(callee, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
-
-    // Speculatively roll the callframe, assuming argCount will match the arity.
-    mul32(Imm32(sizeof(Register)), regT3, regT3);
-    addPtr(callFrameRegister, regT3);
-    storePtr(callFrameRegister, Address(regT3, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register))));
-    move(regT3, callFrameRegister);
-
-    move(regT2, regT1); // argCount
-
-    emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
-
-    emitStore(dst, regT1, regT0);
-    
-    sampleCodeBlock(m_codeBlock);
-}
-
-void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-
-    linkSlowCaseIfNotJSCell(iter, callee);
-    linkSlowCase(iter);
-
-    JITStubCall stubCall(this, cti_op_call_NotJSFunction);
-    stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
-
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_call_varargs), dst, regT1, regT0);
-    sampleCodeBlock(m_codeBlock);
-}
-
-void JIT::emit_op_ret(Instruction* currentInstruction)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-
-    // We could JIT generate the deref, only calling out to C when the refcount hits zero.
-    if (m_codeBlock->needsFullScopeChain())
-        JITStubCall(this, cti_op_ret_scopeChain).call();
-
-    emitLoad(dst, regT1, regT0);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
-
-    restoreReturnAddressBeforeReturn(regT2);
-    ret();
-}
-
-void JIT::emit_op_construct_verify(Instruction* currentInstruction)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-
-    emitLoad(dst, regT1, regT0);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
-}
-
-void JIT::emitSlow_op_construct_verify(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    unsigned dst = currentInstruction[1].u.operand;
-    unsigned src = currentInstruction[2].u.operand;
-
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-    emitLoad(src, regT1, regT0);
-    emitStore(dst, regT1, regT0);
-}
-
-void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
-}
-
-void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
-}
-
-void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    compileOpCallVarargsSlowCase(currentInstruction, iter);
-}
-
-void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
-{
-    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
-}
-
-void JIT::emit_op_call(Instruction* currentInstruction)
-{
-    compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
-}
-
-void JIT::emit_op_call_eval(Instruction* currentInstruction)
-{
-    compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
-}
-
-void JIT::emit_op_load_varargs(Instruction* currentInstruction)
-{
-    int argCountDst = currentInstruction[1].u.operand;
-    int argsOffset = currentInstruction[2].u.operand;
-
-    JITStubCall stubCall(this, cti_op_load_varargs);
-    stubCall.addArgument(Imm32(argsOffset));
-    stubCall.call();
-    // Stores a naked int32 in the register file.
-    store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register)));
-}
-
-void JIT::emit_op_call_varargs(Instruction* currentInstruction)
-{
-    compileOpCallVarargs(currentInstruction);
-}
-
-void JIT::emit_op_construct(Instruction* currentInstruction)
-{
-    compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
-}
-
-#if !ENABLE(JIT_OPTIMIZE_CALL)
-
-/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
-
-void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
-{
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-
-    Jump wasEval;
-    if (opcodeID == op_call_eval) {
-        JITStubCall stubCall(this, cti_op_call_eval);
-        stubCall.addArgument(callee);
-        stubCall.addArgument(JIT::Imm32(registerOffset));
-        stubCall.addArgument(JIT::Imm32(argCount));
-        stubCall.call();
-        wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag));
-    }
-
-    emitLoad(callee, regT1, regT0);
-
-    if (opcodeID == op_call)
-        compileOpCallSetupArgs(instruction);
-    else if (opcodeID == op_construct)
-        compileOpConstructSetupArgs(instruction);
-
-    emitJumpSlowCaseIfNotJSCell(callee, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
-
-    // First, in the case of a construct, allocate the new object.
-    if (opcodeID == op_construct) {
-        JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitLoad(callee, regT1, regT0);
-    }
-
-    // Speculatively roll the callframe, assuming argCount will match the arity.
-    storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
-    addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
-    move(Imm32(argCount), regT1);
-
-    emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
-
-    if (opcodeID == op_call_eval)
-        wasEval.link(this);
-
-    emitStore(dst, regT1, regT0);
-
-    sampleCodeBlock(m_codeBlock);
-}
-
-void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
-{
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-
-    linkSlowCaseIfNotJSCell(iter, callee);
-    linkSlowCase(iter);
-
-    JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
-    stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
-
-    sampleCodeBlock(m_codeBlock);
-}
-
-#else // !ENABLE(JIT_OPTIMIZE_CALL)
-
-/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
-
-void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
-{
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-
-    Jump wasEval;
-    if (opcodeID == op_call_eval) {
-        JITStubCall stubCall(this, cti_op_call_eval);
-        stubCall.addArgument(callee);
-        stubCall.addArgument(JIT::Imm32(registerOffset));
-        stubCall.addArgument(JIT::Imm32(argCount));
-        stubCall.call();
-        wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag));
-    }
-
-    emitLoad(callee, regT1, regT0);
-
-    DataLabelPtr addressOfLinkedFunctionCheck;
-
-    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
-
-    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(0));
-
-    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
-
-    addSlowCase(jumpToSlow);
-    ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump);
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
-
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
-
-    // The following is the fast case, only used whan a callee can be linked.
-
-    // In the case of OpConstruct, call out to a cti_ function to create the new object.
-    if (opcodeID == op_construct) {
-        int proto = instruction[5].u.operand;
-        int thisRegister = instruction[6].u.operand;
-
-        JITStubCall stubCall(this, cti_op_construct_JSConstruct);
-        stubCall.addArgument(regT1, regT0);
-        stubCall.addArgument(Imm32(0)); // FIXME: Remove this unused JITStub argument.
-        stubCall.addArgument(Imm32(0)); // FIXME: Remove this unused JITStub argument.
-        stubCall.addArgument(proto);
-        stubCall.call(thisRegister);
-
-        emitLoad(callee, regT1, regT0);
-    }
-
-    // Fast version of stack frame initialization, directly relative to edi.
-    // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
-    emitStore(registerOffset + RegisterFile::OptionalCalleeArguments, JSValue());
-    emitStore(registerOffset + RegisterFile::Callee, regT1, regT0);
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
-    store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register))));
-    storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register))));
-    storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register))));
-    addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister);
-
-    // Call to the callee
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
-    
-    if (opcodeID == op_call_eval)
-        wasEval.link(this);
-
-    // Put the return value in dst. In the interpreter, op_ret does this.
-    emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + opcodeLengths[opcodeID], dst, regT1, regT0);
-
-    sampleCodeBlock(m_codeBlock);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT3); // scopeChain
+    emitPutIntToCallFrameHeader(regT1, RegisterFile::ArgumentCount);
+    emitPutCellToCallFrameHeader(regT0, RegisterFile::Callee);
+    emitPutCellToCallFrameHeader(regT3, RegisterFile::ScopeChain);
 }
 
-void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
+void JIT::emit_op_call_put_result(Instruction* instruction)
 {
     int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-
-    linkSlowCase(iter);
-    linkSlowCase(iter);
-
-    // The arguments have been set up on the hot path for op_call_eval
-    if (opcodeID == op_call)
-        compileOpCallSetupArgs(instruction);
-    else if (opcodeID == op_construct)
-        compileOpConstructSetupArgs(instruction);
-
-    // Fast check for JS function.
-    Jump callLinkFailNotObject = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
-    Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr));
-
-    // First, in the case of a construct, allocate the new object.
-    if (opcodeID == op_construct) {
-        JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitLoad(callee, regT1, regT0);
-    }
-
-    // Speculatively roll the callframe, assuming argCount will match the arity.
-    storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
-    addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
-    move(Imm32(argCount), regT1);
-
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs->ctiVirtualCallLink());
-
-    // Put the return value in dst.
-    emitStore(dst, regT1, regT0);;
-    sampleCodeBlock(m_codeBlock);
-
-    // If not, we need an extra case in the if below!
-    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
-
-    // Done! - return back to the hot path.
-    if (opcodeID == op_construct)
-        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_construct));
-    else
-        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_call));
-
-    // This handles host functions
-    callLinkFailNotObject.link(this);
-    callLinkFailNotJSFunction.link(this);
-    JITStubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction).call();
-
-    emitStore(dst, regT1, regT0);;
-    sampleCodeBlock(m_codeBlock);
-}
-
-/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
-
-#endif // !ENABLE(JIT_OPTIMIZE_CALL)
-
-#else // USE(JSVALUE32_64)
-
-void JIT::compileOpCallInitializeCallFrame()
-{
-    store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register))));
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
-
-    storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register))));
-    storePtr(regT0, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register))));
-    storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register))));
-}
-
-void JIT::compileOpCallSetupArgs(Instruction* instruction)
-{
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-
-    // ecx holds func
-    emitPutJITStubArg(regT0, 0);
-    emitPutJITStubArgConstant(argCount, 2);
-    emitPutJITStubArgConstant(registerOffset, 1);
-}
-          
-void JIT::compileOpCallVarargsSetupArgs(Instruction* instruction)
-{
-    int registerOffset = instruction[4].u.operand;
-    
-    // ecx holds func
-    emitPutJITStubArg(regT0, 0);
-    emitPutJITStubArg(regT1, 2);
-    addPtr(Imm32(registerOffset), regT1, regT2);
-    emitPutJITStubArg(regT2, 1);
-}
-
-void JIT::compileOpConstructSetupArgs(Instruction* instruction)
-{
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
-    int proto = instruction[5].u.operand;
-    int thisRegister = instruction[6].u.operand;
-
-    // ecx holds func
-    emitPutJITStubArg(regT0, 0);
-    emitPutJITStubArgConstant(registerOffset, 1);
-    emitPutJITStubArgConstant(argCount, 2);
-    emitPutJITStubArgFromVirtualRegister(proto, 3, regT2);
-    emitPutJITStubArgConstant(thisRegister, 4);
+    emitPutVirtualRegister(dst);
 }
 
 void JIT::compileOpCallVarargs(Instruction* instruction)
 {
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCountRegister = instruction[3].u.operand;
+    int callee = instruction[1].u.operand;
+    int argCountRegister = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
 
     emitGetVirtualRegister(argCountRegister, regT1);
+    emitFastArithImmToInt(regT1);
     emitGetVirtualRegister(callee, regT0);
-    compileOpCallVarargsSetupArgs(instruction);
+    addPtr(Imm32(registerOffset), regT1, regT2);
 
     // Check for JSFunctions.
     emitJumpSlowCaseIfNotJSCell(regT0);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
-    mul32(Imm32(sizeof(Register)), regT2, regT2);
+    mul32(TrustedImm32(sizeof(Register)), regT2, regT2);
     intptr_t offset = (intptr_t)sizeof(Register) * (intptr_t)RegisterFile::CallerFrame;
     addPtr(Imm32((int32_t)offset), regT2, regT3);
     addPtr(callFrameRegister, regT3);
@@ -501,20 +85,19 @@ void JIT::compileOpCallVarargs(Instruction* instruction)
     addPtr(regT2, callFrameRegister);
     emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
 
-    // Put the return value in dst. In the interpreter, op_ret does this.
-    emitPutVirtualRegister(dst);
-    
     sampleCodeBlock(m_codeBlock);
 }
 
-void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::compileOpCallVarargsSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator& iter)
 {
-    int dst = instruction[1].u.operand;
-    
     linkSlowCase(iter);
     linkSlowCase(iter);
+
     JITStubCall stubCall(this, cti_op_call_NotJSFunction);
-    stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(regT2);
+    stubCall.addArgument(regT1);
+    stubCall.call();
     
     sampleCodeBlock(m_codeBlock);
 }
@@ -525,10 +108,9 @@ void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCase
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
 {
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
+    int callee = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
 
     // Handle eval
     Jump wasEval;
@@ -538,50 +120,41 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
-        wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue())));
+        wasEval = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())));
     }
 
     emitGetVirtualRegister(callee, regT0);
-    // The arguments have been set up on the hot path for op_call_eval
-    if (opcodeID == op_call)
-        compileOpCallSetupArgs(instruction);
-    else if (opcodeID == op_construct)
-        compileOpConstructSetupArgs(instruction);
 
     // Check for JSFunctions.
     emitJumpSlowCaseIfNotJSCell(regT0);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr)));
-
-    // First, in the case of a construct, allocate the new object.
-    if (opcodeID == op_construct) {
-        JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitGetVirtualRegister(callee, regT0);
-    }
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
     addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
     move(Imm32(argCount), regT1);
 
-    emitNakedCall(m_globalData->jitStubs.ctiVirtualCall());
+    emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall());
 
     if (opcodeID == op_call_eval)
         wasEval.link(this);
 
-    // Put the return value in dst. In the interpreter, op_ret does this.
-    emitPutVirtualRegister(dst);
-
     sampleCodeBlock(m_codeBlock);
 }
 
 void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
 {
-    int dst = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
 
     linkSlowCase(iter);
     linkSlowCase(iter);
+
     JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
-    stubCall.call(dst); // In the interpreter, the callee puts the return value in dst.
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(JIT::Imm32(registerOffset));
+    stubCall.addArgument(JIT::Imm32(argCount));
+    stubCall.call();
 
     sampleCodeBlock(m_codeBlock);
 }
@@ -592,10 +165,9 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
 {
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
+    int callee = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
 
     // Handle eval
     Jump wasEval;
@@ -605,7 +177,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
         stubCall.addArgument(JIT::Imm32(registerOffset));
         stubCall.addArgument(JIT::Imm32(argCount));
         stubCall.call();
-        wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue())));
+        wasEval = branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue())));
     }
 
     // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
@@ -615,35 +187,26 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
 
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
 
-    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(JSValue::encode(JSValue())));
+    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(JSValue::encode(JSValue())));
 
     END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
 
     addSlowCase(jumpToSlow);
     ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump);
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].isCall = opcodeID != op_construct;
 
     // The following is the fast case, only used whan a callee can be linked.
 
-    // In the case of OpConstruct, call out to a cti_ function to create the new object.
-    if (opcodeID == op_construct) {
-        int proto = instruction[5].u.operand;
-        int thisRegister = instruction[6].u.operand;
-
-        emitPutJITStubArg(regT0, 0);
-        emitPutJITStubArgFromVirtualRegister(proto, 3, regT2);
-        JITStubCall stubCall(this, cti_op_construct_JSConstruct);
-        stubCall.call(thisRegister);
-        emitGetVirtualRegister(callee, regT0);
-    }
-
     // Fast version of stack frame initialization, directly relative to edi.
     // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
-    storePtr(ImmPtr(JSValue::encode(JSValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register))));
-    storePtr(regT0, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_data) + OBJECT_OFFSETOF(ScopeChain, m_node)), regT1); // newScopeChain
-    store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register))));
+
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT1); // newScopeChain
+    
+    store32(TrustedImm32(Int32Tag), intTagFor(registerOffset + RegisterFile::ArgumentCount));
+    store32(Imm32(argCount), intPayloadFor(registerOffset + RegisterFile::ArgumentCount));
     storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register))));
+    storePtr(regT0, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register))));
     storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register))));
     addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister);
 
@@ -653,65 +216,42 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
     if (opcodeID == op_call_eval)
         wasEval.link(this);
 
-    // Put the return value in dst. In the interpreter, op_ret does this.
-    emitPutVirtualRegister(dst);
-
     sampleCodeBlock(m_codeBlock);
 }
 
 void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
 {
-    int dst = instruction[1].u.operand;
-    int callee = instruction[2].u.operand;
-    int argCount = instruction[3].u.operand;
-    int registerOffset = instruction[4].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
 
     linkSlowCase(iter);
 
-    // The arguments have been set up on the hot path for op_call_eval
-    if (opcodeID == op_call)
-        compileOpCallSetupArgs(instruction);
-    else if (opcodeID == op_construct)
-        compileOpConstructSetupArgs(instruction);
-
     // Fast check for JS function.
     Jump callLinkFailNotObject = emitJumpIfNotJSCell(regT0);
-    Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr));
-
-    // First, in the case of a construct, allocate the new object.
-    if (opcodeID == op_construct) {
-        JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
-        emitGetVirtualRegister(callee, regT0);
-    }
+    Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr));
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register))));
     addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
     move(Imm32(argCount), regT1);
 
-    move(regT0, regT2);
-
-    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_globalData->jitStubs->ctiVirtualCallLink());
-
-    // Put the return value in dst.
-    emitPutVirtualRegister(dst);
-    sampleCodeBlock(m_codeBlock);
-
-    // If not, we need an extra case in the if below!
-    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink());
 
     // Done! - return back to the hot path.
-    if (opcodeID == op_construct)
-        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_construct));
-    else
-        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_call));
+    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
+    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_call));
 
     // This handles host functions
     callLinkFailNotObject.link(this);
     callLinkFailNotJSFunction.link(this);
-    JITStubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction).call();
 
-    emitPutVirtualRegister(dst);
+    JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(JIT::Imm32(registerOffset));
+    stubCall.addArgument(JIT::Imm32(argCount));
+    stubCall.call();
+
     sampleCodeBlock(m_codeBlock);
 }
 
@@ -719,8 +259,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
 
 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
 
-#endif // USE(JSVALUE32_64)
-
 } // namespace JSC
 
+#endif // USE(JSVALUE64)
 #endif // ENABLE(JIT)
diff --git a/jit/JITCall32_64.cpp b/jit/JITCall32_64.cpp
new file mode 100644 (file)
index 0000000..0019d98
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2008 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. 
+ */
+
+#include "config.h"
+
+#if ENABLE(JIT)
+#if USE(JSVALUE32_64)
+#include "JIT.h"
+
+#include "CodeBlock.h"
+#include "Interpreter.h"
+#include "JITInlineMethods.h"
+#include "JITStubCall.h"
+#include "JSArray.h"
+#include "JSFunction.h"
+#include "ResultType.h"
+#include "SamplingTool.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace std;
+
+namespace JSC {
+
+void JIT::compileOpCallInitializeCallFrame()
+{
+    // regT0 holds callee, regT1 holds argCount
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT3); // scopeChain
+    emitPutIntToCallFrameHeader(regT1, RegisterFile::ArgumentCount);
+    emitPutCellToCallFrameHeader(regT0, RegisterFile::Callee);
+    emitPutCellToCallFrameHeader(regT3, RegisterFile::ScopeChain);
+}
+
+void JIT::emit_op_call_put_result(Instruction* instruction)
+{
+    int dst = instruction[1].u.operand;
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::compileOpCallVarargs(Instruction* instruction)
+{
+    int callee = instruction[1].u.operand;
+    int argCountRegister = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
+
+    emitLoad(callee, regT1, regT0);
+    emitLoadPayload(argCountRegister, regT2); // argCount
+    addPtr(Imm32(registerOffset), regT2, regT3); // registerOffset
+
+    emitJumpSlowCaseIfNotJSCell(callee, regT1);
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
+
+    // Speculatively roll the callframe, assuming argCount will match the arity.
+    mul32(TrustedImm32(sizeof(Register)), regT3, regT3);
+    addPtr(callFrameRegister, regT3);
+    store32(TrustedImm32(JSValue::CellTag), tagFor(RegisterFile::CallerFrame, regT3));
+    storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame, regT3));
+    move(regT3, callFrameRegister);
+
+    move(regT2, regT1); // argCount
+
+    emitNakedCall(m_globalData->jitStubs->ctiVirtualCall());
+
+    sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    int callee = instruction[1].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, callee);
+    linkSlowCase(iter);
+
+    JITStubCall stubCall(this, cti_op_call_NotJSFunction);
+    stubCall.addArgument(regT1, regT0);
+    stubCall.addArgument(regT3);
+    stubCall.addArgument(regT2);
+    stubCall.call();
+
+    sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::emit_op_ret(Instruction* currentInstruction)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+
+    emitLoad(dst, regT1, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+    restoreReturnAddressBeforeReturn(regT2);
+    ret();
+}
+
+void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
+{
+    unsigned result = currentInstruction[1].u.operand;
+    unsigned thisReg = currentInstruction[2].u.operand;
+
+    emitLoad(result, regT1, regT0);
+    Jump notJSCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    Jump notObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+    restoreReturnAddressBeforeReturn(regT2);
+    ret();
+
+    notJSCell.link(this);
+    notObject.link(this);
+    emitLoad(thisReg, regT1, regT0);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+    restoreReturnAddressBeforeReturn(regT2);
+    ret();
+}
+
+void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
+}
+
+void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
+}
+
+void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    compileOpCallVarargsSlowCase(currentInstruction, iter);
+}
+
+void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
+}
+
+void JIT::emit_op_call(Instruction* currentInstruction)
+{
+    compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_call_eval(Instruction* currentInstruction)
+{
+    compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
+}
+
+void JIT::emit_op_call_varargs(Instruction* currentInstruction)
+{
+    compileOpCallVarargs(currentInstruction);
+}
+
+void JIT::emit_op_construct(Instruction* currentInstruction)
+{
+    compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
+}
+
+#if !ENABLE(JIT_OPTIMIZE_CALL)
+
+/* ------------------------------ BEGIN: !ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
+void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
+{
+    int callee = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
+
+    Jump wasEval;
+    if (opcodeID == op_call_eval) {
+        JITStubCall stubCall(this, cti_op_call_eval);
+        stubCall.addArgument(callee);
+        stubCall.addArgument(JIT::Imm32(registerOffset));
+        stubCall.addArgument(JIT::Imm32(argCount));
+        stubCall.call();
+        wasEval = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag));
+    }
+
+    emitLoad(callee, regT1, regT0);
+
+    emitJumpSlowCaseIfNotJSCell(callee, regT1);
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr)));
+
+    // Speculatively roll the callframe, assuming argCount will match the arity.
+    store32(TrustedImm32(JSValue::CellTag), tagFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister));
+    storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister));
+    addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
+    move(TrustedImm32(argCount), regT1);
+
+    emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstruct() : m_globalData->jitStubs->ctiVirtualCall());
+
+    if (opcodeID == op_call_eval)
+        wasEval.link(this);
+
+    sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned, OpcodeID opcodeID)
+{
+    int callee = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, callee);
+    linkSlowCase(iter);
+
+    JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
+    stubCall.addArgument(callee);
+    stubCall.addArgument(JIT::Imm32(registerOffset));
+    stubCall.addArgument(JIT::Imm32(argCount));
+    stubCall.call();
+
+    sampleCodeBlock(m_codeBlock);
+}
+
+#else // !ENABLE(JIT_OPTIMIZE_CALL)
+
+/* ------------------------------ BEGIN: ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
+void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
+{
+    int callee = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
+
+    Jump wasEval;
+    if (opcodeID == op_call_eval) {
+        JITStubCall stubCall(this, cti_op_call_eval);
+        stubCall.addArgument(callee);
+        stubCall.addArgument(JIT::Imm32(registerOffset));
+        stubCall.addArgument(JIT::Imm32(argCount));
+        stubCall.call();
+        wasEval = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag));
+    }
+
+    emitLoad(callee, regT1, regT0);
+
+    DataLabelPtr addressOfLinkedFunctionCheck;
+
+    BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+
+    Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, TrustedImmPtr(0));
+
+    END_UNINTERRUPTED_SEQUENCE(sequenceOpCall);
+
+    addSlowCase(jumpToSlow);
+    ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump);
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].isCall = opcodeID != op_construct;
+
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+
+    // The following is the fast case, only used whan a callee can be linked.
+
+    // Fast version of stack frame initialization, directly relative to edi.
+    // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_scopeChain)), regT2);
+
+    store32(TrustedImm32(JSValue::Int32Tag), tagFor(registerOffset + RegisterFile::ArgumentCount));
+    store32(Imm32(argCount), payloadFor(registerOffset + RegisterFile::ArgumentCount));
+    storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister));
+    emitStore(registerOffset + RegisterFile::Callee, regT1, regT0);
+    store32(TrustedImm32(JSValue::CellTag), tagFor(registerOffset + RegisterFile::ScopeChain));
+    store32(regT2, payloadFor(registerOffset + RegisterFile::ScopeChain));
+    addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister);
+
+    // Call to the callee
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall();
+    
+    if (opcodeID == op_call_eval)
+        wasEval.link(this);
+
+    sampleCodeBlock(m_codeBlock);
+}
+
+void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID)
+{
+    int callee = instruction[1].u.operand;
+    int argCount = instruction[2].u.operand;
+    int registerOffset = instruction[3].u.operand;
+
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+
+    // Fast check for JS function.
+    Jump callLinkFailNotObject = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsFunctionVPtr));
+
+    // Speculatively roll the callframe, assuming argCount will match the arity.
+    store32(TrustedImm32(JSValue::CellTag), tagFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister));
+    storePtr(callFrameRegister, payloadFor(RegisterFile::CallerFrame + registerOffset, callFrameRegister));
+    addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister);
+    move(Imm32(argCount), regT1);
+
+    m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(opcodeID == op_construct ? m_globalData->jitStubs->ctiVirtualConstructLink() : m_globalData->jitStubs->ctiVirtualCallLink());
+
+    // Done! - return back to the hot path.
+    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_eval));
+    ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
+    emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_call));
+
+    // This handles host functions
+    callLinkFailNotObject.link(this);
+    callLinkFailNotJSFunction.link(this);
+
+    JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
+    stubCall.addArgument(callee);
+    stubCall.addArgument(JIT::Imm32(registerOffset));
+    stubCall.addArgument(JIT::Imm32(argCount));
+    stubCall.call();
+
+    sampleCodeBlock(m_codeBlock);
+}
+
+/* ------------------------------ END: !ENABLE / ENABLE(JIT_OPTIMIZE_CALL) ------------------------------ */
+
+#endif // !ENABLE(JIT_OPTIMIZE_CALL)
+
+} // namespace JSC
+
+#endif // USE(JSVALUE32_64)
+#endif // ENABLE(JIT)
index 5d889b52f9ac42f7a891803ec6bbe4b388636904..082d2a73756a4bf4245dd2420c0e32b8a4f1496a 100644 (file)
@@ -72,9 +72,10 @@ namespace JSC {
         }
 
         // Execute the code!
-        inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue* exception)
+        inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData)
         {
-            return JSValue::decode(ctiTrampoline(m_ref.m_code.executableAddress(), registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
+            JSValue result = JSValue::decode(ctiTrampoline(m_ref.m_code.executableAddress(), registerFile, callFrame, 0, Profiler::enabledProfilerReference(), globalData));
+            return globalData->exception ? jsNull() : result;
         }
 
         void* start()
@@ -100,6 +101,12 @@ namespace JSC {
             return JITCode(code.dataLocation(), 0, 0);
         }
 
+        void clear()
+        {
+            m_ref.~CodeRef();
+            new (&m_ref) CodeRef();
+        }
+
     private:
         JITCode(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
             : m_ref(code, executablePool, size)
index 824ca4b0341a8f579a4b847e3e27e50b69787bab..693ae98fdfda3bce0af0a1e8c90a2d03423ab786 100644 (file)
@@ -33,31 +33,6 @@ namespace JSC {
 
 /* Deprecated: Please use JITStubCall instead. */
 
-// puts an arg onto the stack, as an arg to a context threaded function.
-ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber)
-{
-    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
-    poke(src, argumentStackOffset);
-}
-
-/* Deprecated: Please use JITStubCall instead. */
-
-ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber)
-{
-    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
-    poke(Imm32(value), argumentStackOffset);
-}
-
-/* Deprecated: Please use JITStubCall instead. */
-
-ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber)
-{
-    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
-    poke(ImmPtr(value), argumentStackOffset);
-}
-
-/* Deprecated: Please use JITStubCall instead. */
-
 ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst)
 {
     unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
@@ -77,27 +52,41 @@ ALWAYS_INLINE JSValue JIT::getConstantOperand(unsigned src)
 
 ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
 {
-    storePtr(from, Address(callFrameRegister, entry * sizeof(Register)));
+    storePtr(from, payloadFor(entry, callFrameRegister));
+}
+
+ALWAYS_INLINE void JIT::emitPutCellToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
+{
+#if USE(JSVALUE32_64)
+    store32(TrustedImm32(JSValue::CellTag), tagFor(entry, callFrameRegister));
+#endif
+    storePtr(from, payloadFor(entry, callFrameRegister));
+}
+
+ALWAYS_INLINE void JIT::emitPutIntToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
+{
+    store32(TrustedImm32(Int32Tag), intTagFor(entry, callFrameRegister));
+    store32(from, intPayloadFor(entry, callFrameRegister));
 }
 
 ALWAYS_INLINE void JIT::emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry)
 {
-    storePtr(ImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
+    storePtr(TrustedImmPtr(value), Address(callFrameRegister, entry * sizeof(Register)));
 }
 
 ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
 {
     loadPtr(Address(from, entry * sizeof(Register)), to);
-#if !USE(JSVALUE32_64)
+#if USE(JSVALUE64)
     killLastResultRegister();
 #endif
 }
 
 ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures)
 {
-    failures.append(branchPtr(NotEqual, Address(src), ImmPtr(m_globalData->jsStringVPtr)));
+    failures.append(branchPtr(NotEqual, Address(src), TrustedImmPtr(m_globalData->jsStringVPtr)));
     failures.append(branchTest32(NonZero, Address(src, OBJECT_OFFSETOF(JSString, m_fiberCount))));
-    failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), Imm32(1)));
+    failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1)));
     loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst);
     loadPtr(MacroAssembler::Address(dst, ThunkHelpers::stringImplDataOffset()), dst);
     load16(MacroAssembler::Address(dst, 0), dst);
@@ -106,24 +95,35 @@ ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst,
 ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from)
 {
     load32(Address(from, entry * sizeof(Register)), to);
-#if !USE(JSVALUE32_64)
+#if USE(JSVALUE64)
     killLastResultRegister();
 #endif
 }
 
 ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function)
 {
-    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 
     Call nakedCall = nearCall();
-    m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function.executableAddress()));
+    m_calls.append(CallRecord(nakedCall, m_bytecodeOffset, function.executableAddress()));
     return nakedCall;
 }
 
+ALWAYS_INLINE bool JIT::atJumpTarget()
+{
+    while (m_jumpTargetsPosition < m_codeBlock->numberOfJumpTargets() && m_codeBlock->jumpTarget(m_jumpTargetsPosition) <= m_bytecodeOffset) {
+        if (m_codeBlock->jumpTarget(m_jumpTargetsPosition) == m_bytecodeOffset)
+            return true;
+        ++m_jumpTargetsPosition;
+    }
+    return false;
+}
+
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
 ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace)
 {
+    JSInterfaceJIT::beginUninterruptedSequence();
 #if CPU(ARM_TRADITIONAL)
 #ifndef NDEBUG
     // Ensure the label after the sequence can also fit
@@ -133,6 +133,13 @@ ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace
 
     ensureSpace(insnSpace, constSpace);
 
+#elif CPU(SH4)
+#ifndef NDEBUG
+    insnSpace += sizeof(SH4Word);
+    constSpace += sizeof(uint64_t);
+#endif
+
+    m_assembler.ensureSpace(insnSpace + m_assembler.maxInstructionSize + 2, constSpace + 8);
 #endif
 
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
@@ -143,12 +150,30 @@ ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace
 #endif
 }
 
-ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace)
+ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace, int dst)
 {
+    UNUSED_PARAM(dst);
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
-    ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) == insnSpace);
-    ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin == constSpace);
+    /* There are several cases when the uninterrupted sequence is larger than
+     * maximum required offset for pathing the same sequence. Eg.: if in a
+     * uninterrupted sequence the last macroassembler's instruction is a stub
+     * call, it emits store instruction(s) which should not be included in the
+     * calculation of length of uninterrupted sequence. So, the insnSpace and
+     * constSpace should be upper limit instead of hard limit.
+     */
+#if CPU(SH4)
+    if ((dst > 15) || (dst < -16)) {
+        insnSpace += 8;
+        constSpace += 2;
+    }
+
+    if (((dst >= -16) && (dst < 0)) || ((dst > 7) && (dst <= 15)))
+        insnSpace += 8;
+#endif
+    ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) <= insnSpace);
+    ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin <= constSpace);
 #endif
+    JSInterfaceJIT::endUninterruptedSequence();
 }
 
 #endif
@@ -169,6 +194,22 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
     loadPtr(address, linkRegister);
 }
+#elif CPU(SH4)
+
+ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
+{
+    m_assembler.stspr(reg);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
+{
+    m_assembler.ldspr(reg);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
+{
+    loadPtrLinkReg(address);
+}
 
 #elif CPU(MIPS)
 
@@ -206,33 +247,28 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 
 #endif
 
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-ALWAYS_INLINE void JIT::restoreArgumentReference()
-{
-    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
-}
-ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() {}
-#else
 ALWAYS_INLINE void JIT::restoreArgumentReference()
 {
     move(stackPointerRegister, firstArgumentRegister);
-    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
 }
+
 ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
 {
 #if CPU(X86)
     // Within a trampoline the return address will be on the stack at this point.
-    addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
+    addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
 #elif CPU(ARM)
     move(stackPointerRegister, firstArgumentRegister);
+#elif CPU(SH4)
+    move(stackPointerRegister, firstArgumentRegister);
 #endif
     // In the trampoline on x86-64, the first argument register is not overwritten.
 }
-#endif
 
 ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
 {
-    return branchPtr(NotEqual, Address(reg, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(structure));
+    return branchPtr(NotEqual, Address(reg, JSCell::structureOffset()), TrustedImmPtr(structure));
 }
 
 ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg)
@@ -243,33 +279,33 @@ ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&
 
 ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
 {
-    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 
-    m_slowCases.append(SlowCaseEntry(jump, m_bytecodeIndex));
+    m_slowCases.append(SlowCaseEntry(jump, m_bytecodeOffset));
 }
 
 ALWAYS_INLINE void JIT::addSlowCase(JumpList jumpList)
 {
-    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 
     const JumpList::JumpVector& jumpVector = jumpList.jumps();
     size_t size = jumpVector.size();
     for (size_t i = 0; i < size; ++i)
-        m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeIndex));
+        m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeOffset));
 }
 
 ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset)
 {
-    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 
-    m_jmpTable.append(JumpTable(jump, m_bytecodeIndex + relativeOffset));
+    m_jmpTable.append(JumpTable(jump, m_bytecodeOffset + relativeOffset));
 }
 
 ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset)
 {
-    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 
-    jump.linkTo(m_labels[m_bytecodeIndex + relativeOffset], this);
+    jump.linkTo(m_labels[m_bytecodeOffset + relativeOffset], this);
 }
 
 #if ENABLE(SAMPLING_FLAGS)
@@ -277,14 +313,14 @@ ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
 {
     ASSERT(flag >= 1);
     ASSERT(flag <= 32);
-    or32(Imm32(1u << (flag - 1)), AbsoluteAddress(&SamplingFlags::s_flags));
+    or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags()));
 }
 
 ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
 {
     ASSERT(flag >= 1);
     ASSERT(flag <= 32);
-    and32(Imm32(~(1u << (flag - 1))), AbsoluteAddress(&SamplingFlags::s_flags));
+    and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags()));
 }
 #endif
 
@@ -292,11 +328,11 @@ ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag)
 ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count)
 {
 #if CPU(X86_64) // Or any other 64-bit plattform.
-    addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter));
+    addPtr(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter()));
 #elif CPU(X86) // Or any other little-endian 32-bit plattform.
-    intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t);
-    add32(Imm32(count), AbsoluteAddress(&counter.m_counter));
-    addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
+    intptr_t hiWord = reinterpret_cast<intptr_t>(counter.addressOfCounter()) + sizeof(int32_t);
+    add32(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter()));
+    addWithCarry32(TrustedImm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord)));
 #else
 #error "SAMPLING_FLAGS not implemented on this platform."
 #endif
@@ -307,13 +343,13 @@ ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t cou
 #if CPU(X86_64)
 ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 {
-    move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx);
-    storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx);
+    move(TrustedImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx);
+    storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx);
 }
 #else
 ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction)
 {
-    storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
+    storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
 }
 #endif
 #endif
@@ -322,13 +358,13 @@ ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostF
 #if CPU(X86_64)
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 {
-    move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx);
-    storePtr(ImmPtr(codeBlock), X86Registers::ecx);
+    move(TrustedImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx);
+    storePtr(TrustedImmPtr(codeBlock), X86Registers::ecx);
 }
 #else
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 {
-    storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
+    storePtr(TrustedImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
 }
 #endif
 #endif
@@ -419,7 +455,7 @@ inline void JIT::emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1
 inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         loadDouble(&inConstantPool, value);
     } else
         loadDouble(addressFor(index), value);
@@ -428,7 +464,7 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         char* bytePointer = reinterpret_cast<char*>(&inConstantPool);
         convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value);
     } else
@@ -445,28 +481,28 @@ inline void JIT::emitStoreInt32(unsigned index, RegisterID payload, bool indexIs
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsInt32)
-        store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
+        store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 }
 
-inline void JIT::emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32)
+inline void JIT::emitStoreInt32(unsigned index, TrustedImm32 payload, bool indexIsInt32)
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsInt32)
-        store32(Imm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
+        store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister));
 }
 
 inline void JIT::emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell)
 {
     store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsCell)
-        store32(Imm32(JSValue::CellTag), tagFor(index, callFrameRegister));
+        store32(TrustedImm32(JSValue::CellTag), tagFor(index, callFrameRegister));
 }
 
-inline void JIT::emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool)
+inline void JIT::emitStoreBool(unsigned index, RegisterID payload, bool indexIsBool)
 {
+    store32(payload, payloadFor(index, callFrameRegister));
     if (!indexIsBool)
-        store32(Imm32(0), payloadFor(index, callFrameRegister));
-    store32(tag, tagFor(index, callFrameRegister));
+        store32(TrustedImm32(JSValue::BooleanTag), tagFor(index, callFrameRegister));
 }
 
 inline void JIT::emitStoreDouble(unsigned index, FPRegisterID value)
@@ -485,24 +521,24 @@ ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
     emitStore(dst, jsUndefined());
 }
 
-inline bool JIT::isLabeled(unsigned bytecodeIndex)
+inline bool JIT::isLabeled(unsigned bytecodeOffset)
 {
     for (size_t numberOfJumpTargets = m_codeBlock->numberOfJumpTargets(); m_jumpTargetIndex != numberOfJumpTargets; ++m_jumpTargetIndex) {
         unsigned jumpTarget = m_codeBlock->jumpTarget(m_jumpTargetIndex);
-        if (jumpTarget == bytecodeIndex)
+        if (jumpTarget == bytecodeOffset)
             return true;
-        if (jumpTarget > bytecodeIndex)
+        if (jumpTarget > bytecodeOffset)
             return false;
     }
     return false;
 }
 
-inline void JIT::map(unsigned bytecodeIndex, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload)
+inline void JIT::map(unsigned bytecodeOffset, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload)
 {
-    if (isLabeled(bytecodeIndex))
+    if (isLabeled(bytecodeOffset))
         return;
 
-    m_mappedBytecodeIndex = bytecodeIndex;
+    m_mappedBytecodeOffset = bytecodeOffset;
     m_mappedVirtualRegisterIndex = virtualRegisterIndex;
     m_mappedTag = tag;
     m_mappedPayload = payload;
@@ -518,7 +554,7 @@ inline void JIT::unmap(RegisterID registerID)
 
 inline void JIT::unmap()
 {
-    m_mappedBytecodeIndex = (unsigned)-1;
+    m_mappedBytecodeOffset = (unsigned)-1;
     m_mappedVirtualRegisterIndex = (unsigned)-1;
     m_mappedTag = (RegisterID)-1;
     m_mappedPayload = (RegisterID)-1;
@@ -526,7 +562,7 @@ inline void JIT::unmap()
 
 inline bool JIT::isMapped(unsigned virtualRegisterIndex)
 {
-    if (m_mappedBytecodeIndex != m_bytecodeIndex)
+    if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
     if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
         return false;
@@ -535,7 +571,7 @@ inline bool JIT::isMapped(unsigned virtualRegisterIndex)
 
 inline bool JIT::getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload)
 {
-    if (m_mappedBytecodeIndex != m_bytecodeIndex)
+    if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
     if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
         return false;
@@ -547,7 +583,7 @@ inline bool JIT::getMappedPayload(unsigned virtualRegisterIndex, RegisterID& pay
 
 inline bool JIT::getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag)
 {
-    if (m_mappedBytecodeIndex != m_bytecodeIndex)
+    if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
     if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
         return false;
@@ -573,7 +609,7 @@ inline void JIT::emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, Regi
         if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex))
             addSlowCase(jump());
         else
-            addSlowCase(branch32(NotEqual, tag, Imm32(JSValue::CellTag)));
+            addSlowCase(branch32(NotEqual, tag, TrustedImm32(JSValue::CellTag)));
     }
 }
 
@@ -605,31 +641,6 @@ ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(unsigned op1, unsigned op
     return false;
 }
 
-/* Deprecated: Please use JITStubCall instead. */
-
-ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber)
-{
-    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
-    poke(payload, argumentStackOffset);
-    poke(tag, argumentStackOffset + 1);
-}
-
-/* Deprecated: Please use JITStubCall instead. */
-
-ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2)
-{
-    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
-    if (m_codeBlock->isConstantRegisterIndex(src)) {
-        JSValue constant = m_codeBlock->getConstant(src);
-        poke(Imm32(constant.payload()), argumentStackOffset);
-        poke(Imm32(constant.tag()), argumentStackOffset + 1);
-    } else {
-        emitLoad(src, scratch1, scratch2);
-        poke(scratch2, argumentStackOffset);
-        poke(scratch1, argumentStackOffset + 1);
-    }
-}
-
 #else // USE(JSVALUE32_64)
 
 ALWAYS_INLINE void JIT::killLastResultRegister()
@@ -640,7 +651,7 @@ ALWAYS_INLINE void JIT::killLastResultRegister()
 // get arg puts an arg from the SF register array into a h/w register
 ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
 {
-    ASSERT(m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+    ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
 
     // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
     if (m_codeBlock->isConstantRegisterIndex(src)) {
@@ -650,21 +661,12 @@ ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst)
         return;
     }
 
-    if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(src)) {
-        bool atJumpTarget = false;
-        while (m_jumpTargetsPosition < m_codeBlock->numberOfJumpTargets() && m_codeBlock->jumpTarget(m_jumpTargetsPosition) <= m_bytecodeIndex) {
-            if (m_codeBlock->jumpTarget(m_jumpTargetsPosition) == m_bytecodeIndex)
-                atJumpTarget = true;
-            ++m_jumpTargetsPosition;
-        }
-
-        if (!atJumpTarget) {
-            // The argument we want is already stored in eax
-            if (dst != cachedResultRegister)
-                move(cachedResultRegister, dst);
-            killLastResultRegister();
-            return;
-        }
+    if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(src) && !atJumpTarget()) {
+        // The argument we want is already stored in eax
+        if (dst != cachedResultRegister)
+            move(cachedResultRegister, dst);
+        killLastResultRegister();
+        return;
     }
 
     loadPtr(Address(callFrameRegister, src * sizeof(Register)), dst);
@@ -695,12 +697,12 @@ ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(unsigned src)
 ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
 {
     storePtr(from, Address(callFrameRegister, dst * sizeof(Register)));
-    m_lastResultBytecodeRegister = (from == cachedResultRegister) ? dst : std::numeric_limits<int>::max();
+    m_lastResultBytecodeRegister = (from == cachedResultRegister) ? static_cast<int>(dst) : std::numeric_limits<int>::max();
 }
 
 ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
 {
-    storePtr(ImmPtr(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
+    storePtr(TrustedImmPtr(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register)));
 }
 
 ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
@@ -708,7 +710,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg)
 #if USE(JSVALUE64)
     return branchTestPtr(Zero, reg, tagMaskRegister);
 #else
-    return branchTest32(Zero, reg, Imm32(JSImmediate::TagMask));
+    return branchTest32(Zero, reg, TrustedImm32(TagMask));
 #endif
 }
 
@@ -729,7 +731,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg)
 #if USE(JSVALUE64)
     return branchTestPtr(NonZero, reg, tagMaskRegister);
 #else
-    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagMask));
+    return branchTest32(NonZero, reg, TrustedImm32(TagMask));
 #endif
 }
 
@@ -749,7 +751,7 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg)
 inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
+        WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index);
         loadDouble(&inConstantPool, value);
     } else
         loadDouble(addressFor(index), value);
@@ -758,8 +760,8 @@ inline void JIT::emitLoadDouble(unsigned index, FPRegisterID value)
 inline void JIT::emitLoadInt32ToDouble(unsigned index, FPRegisterID value)
 {
     if (m_codeBlock->isConstantRegisterIndex(index)) {
-        Register& inConstantPool = m_codeBlock->constantRegister(index);
-        convertInt32ToDouble(AbsoluteAddress(&inConstantPool), value);
+        ASSERT(isOperandConstantImmediateInt(index));
+        convertInt32ToDouble(Imm32(getConstantOperand(index).asInt32()), value);
     } else
         convertInt32ToDouble(addressFor(index), value);
 }
@@ -770,7 +772,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg)
 #if USE(JSVALUE64)
     return branchPtr(AboveOrEqual, reg, tagTypeNumberRegister);
 #else
-    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagTypeNumber));
+    return branchTest32(NonZero, reg, TrustedImm32(TagTypeNumber));
 #endif
 }
 
@@ -779,7 +781,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg)
 #if USE(JSVALUE64)
     return branchPtr(Below, reg, tagTypeNumberRegister);
 #else
-    return branchTest32(Zero, reg, Imm32(JSImmediate::TagTypeNumber));
+    return branchTest32(Zero, reg, TrustedImm32(TagTypeNumber));
 #endif
 }
 
@@ -805,15 +807,15 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg)
     addSlowCase(emitJumpIfNotImmediateNumber(reg));
 }
 
-#if !USE(JSVALUE64)
+#if USE(JSVALUE32_64)
 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
 {
-    subPtr(Imm32(JSImmediate::TagTypeNumber), reg);
+    subPtr(TrustedImm32(TagTypeNumber), reg);
 }
 
 ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
 {
-    return branchSubPtr(Zero, Imm32(JSImmediate::TagTypeNumber), reg);
+    return branchSubPtr(Zero, TrustedImm32(TagTypeNumber), reg);
 }
 #endif
 
@@ -824,7 +826,7 @@ ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID d
 #else
     if (src != dest)
         move(src, dest);
-    addPtr(Imm32(JSImmediate::TagTypeNumber), dest);
+    addPtr(TrustedImm32(TagTypeNumber), dest);
 #endif
 }
 
@@ -844,25 +846,7 @@ ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID
 
 ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
 {
-    lshift32(Imm32(JSImmediate::ExtendedPayloadShift), reg);
-    or32(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), reg);
-}
-
-/* Deprecated: Please use JITStubCall instead. */
-
-// get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
-ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch)
-{
-    unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX;
-    if (m_codeBlock->isConstantRegisterIndex(src)) {
-        JSValue value = m_codeBlock->getConstant(src);
-        poke(ImmPtr(JSValue::encode(value)), argumentStackOffset);
-    } else {
-        loadPtr(Address(callFrameRegister, src * sizeof(Register)), scratch);
-        poke(scratch, argumentStackOffset);
-    }
-
-    killLastResultRegister();
+    or32(TrustedImm32(static_cast<int32_t>(ValueFalse)), reg);
 }
 
 #endif // USE(JSVALUE32_64)
index 403a4546e400e0e5ac139c4d7466de071f14c062..4cdd35aa96f48ef84057ad301b7672438b53c9ff 100644 (file)
  */
 
 #include "config.h"
-#include "JIT.h"
-
 #if ENABLE(JIT)
+#include "JIT.h"
 
+#include "Arguments.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 
 namespace JSC {
 
-#if !USE(JSVALUE32_64)
-
-#define RECORD_JUMP_TARGET(targetOffset) \
-   do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)
+#if USE(JSVALUE64)
 
 void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
 {
-#if ENABLE(JIT_OPTIMIZE_MOD)
-    Label softModBegin = align();
-    softModulo();
-#endif
 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
     // (2) The second function provides fast property access for string length
     Label stringLengthBegin = align();
 
     // Check eax is a string
     Jump string_failureCases1 = emitJumpIfNotJSCell(regT0);
-    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
+    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
 
     // Checks out okay! - get the length from the Ustring.
     load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT0);
 
-    Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt));
+    Jump string_failureCases3 = branch32(LessThan, regT0, TrustedImm32(0));
 
     // regT0 contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
     emitFastArithIntToImmNoCheck(regT0, regT0);
@@ -74,331 +67,209 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
 
     // VirtualCallLink Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    JumpList callLinkFailures;
     Label virtualCallLinkBegin = align();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-
-    Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
-
-    Jump hasCodeBlock2 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
-    preserveReturnAddressAfterCall(regT3);
-    restoreArgumentReference();
-    Call callJSFunction2 = call();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-    emitGetJITStubArg(2, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3);
-    hasCodeBlock2.link(this);
-
-    // Check argCount matches callee arity.
-    Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
+    compileOpCallInitializeCallFrame();
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
-    Call callArityCheck2 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callLazyLinkCall = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
-    arityCheckOkay2.link(this);
-
-    isNativeFunc2.link(this);
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
+    jump(regT0);
 
+    // VirtualConstructLink Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    Label virtualConstructLinkBegin = align();
     compileOpCallInitializeCallFrame();
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
-    Call callLazyLinkCall = call();
+    Call callLazyLinkConstruct = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
 
     // VirtualCall Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    compileOpCallInitializeCallFrame();
 
-    Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
-    Jump hasCodeBlock3 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+    Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
-    Call callJSFunction1 = call();
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callCompileCall = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     restoreReturnAddressBeforeReturn(regT3);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     hasCodeBlock3.link(this);
-    
-    // Check argCount matches callee arity.
-    Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
-    preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
-    restoreArgumentReference();
-    Call callArityCheck1 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(2, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-    arityCheckOkay3.link(this);
-
-    isNativeFunc3.link(this);
 
-    compileOpCallInitializeCallFrame();
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForCallWithArityCheck)), regT0);
     jump(regT0);
 
-    Label nativeCallThunk = align();
-    preserveReturnAddressAfterCall(regT0);
-    emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
+    // VirtualConstruct Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    Label virtualConstructBegin = align();
+    compileOpCallInitializeCallFrame();
 
-    // Load caller frame's scope chain into this callframe so that whatever we call can
-    // get to its global data.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT1);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
-    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
-    
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
-#if CPU(X86_64)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, X86Registers::ecx);
+    Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
+    preserveReturnAddressAfterCall(regT3);
+    restoreArgumentReference();
+    Call callCompileConstruct = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
+    restoreReturnAddressBeforeReturn(regT3);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    hasCodeBlock4.link(this);
 
-    // Allocate stack space for our arglist
-    subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
-    COMPILE_ASSERT((sizeof(ArgList) & 0xf) == 0, ArgList_should_by_16byte_aligned);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0);
+    jump(regT0);
     
-    // Set up arguments
-    subPtr(Imm32(1), X86Registers::ecx); // Don't include 'this' in argcount
+    // If the parser fails we want to be able to be able to keep going,
+    // So we handle this as a parse failure.
+    callLinkFailures.link(this);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+    restoreReturnAddressBeforeReturn(regT1);
+    move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
+    storePtr(regT1, regT2);
+    poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    poke(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+    ret();
 
-    // Push argcount
-    storePtr(X86Registers::ecx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
+    // NativeCall Trampoline
+    Label nativeCallThunk = privateCompileCTINativeCall(globalData);    
+    Label nativeConstructThunk = privateCompileCTINativeCall(globalData, true);    
 
-    // Calculate the start of the callframe header, and store in edx
-    addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), callFrameRegister, X86Registers::edx);
-    
-    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (ecx)
-    mul32(Imm32(sizeof(Register)), X86Registers::ecx, X86Registers::ecx);
-    subPtr(X86Registers::ecx, X86Registers::edx);
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
+    Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
+    Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
+#endif
 
-    // push pointer to arguments
-    storePtr(X86Registers::edx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
-    
-    // ArgList is passed by reference so is stackPointerRegister
-    move(stackPointerRegister, X86Registers::ecx);
-    
-    // edx currently points to the first argument, edx-sizeof(Register) points to 'this'
-    loadPtr(Address(X86Registers::edx, -(int32_t)sizeof(Register)), X86Registers::edx);
-    
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::esi);
+    // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
+    LinkBuffer patchBuffer(*m_globalData, this, m_globalData->executableAllocator);
 
-    move(callFrameRegister, X86Registers::edi); 
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
+    patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
+    patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
+#endif
+#if ENABLE(JIT_OPTIMIZE_CALL)
+    patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
+    patchBuffer.link(callLazyLinkConstruct, FunctionPtr(cti_vm_lazyLinkConstruct));
+#endif
+    patchBuffer.link(callCompileCall, FunctionPtr(cti_op_call_jitCompile));
+    patchBuffer.link(callCompileConstruct, FunctionPtr(cti_op_construct_jitCompile));
 
-    call(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_data)));
-    
-    addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
-#elif CPU(X86)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    CodeRef finalCode = patchBuffer.finalizeCode();
+    *executablePool = finalCode.m_executablePool;
 
-    /* We have two structs that we use to describe the stackframe we set up for our
-     * call to native code.  NativeCallFrameStructure describes the how we set up the stack
-     * in advance of the call.  NativeFunctionCalleeSignature describes the callframe
-     * as the native code expects it.  We do this as we are using the fastcall calling
-     * convention which results in the callee popping its arguments off the stack, but
-     * not the rest of the callframe so we need a nice way to ensure we increment the
-     * stack pointer by the right amount after the call.
-     */
-#if COMPILER(MSVC) || OS(LINUX)
-    struct NativeCallFrameStructure {
-      //  CallFrame* callFrame; // passed in EDX
-        JSObject* callee;
-        JSValue thisValue;
-        ArgList* argPointer;
-        ArgList args;
-        JSValue result;
-    };
-    struct NativeFunctionCalleeSignature {
-        JSObject* callee;
-        JSValue thisValue;
-        ArgList* argPointer;
-    };
-#else
-    struct NativeCallFrameStructure {
-      //  CallFrame* callFrame; // passed in ECX
-      //  JSObject* callee; // passed in EDX
-        JSValue thisValue;
-        ArgList* argPointer;
-        ArgList args;
-    };
-    struct NativeFunctionCalleeSignature {
-        JSValue thisValue;
-        ArgList* argPointer;
-    };
+    trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
+    trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
+    trampolines->ctiVirtualCall = patchBuffer.trampolineAt(virtualCallBegin);
+    trampolines->ctiVirtualConstruct = patchBuffer.trampolineAt(virtualConstructBegin);
+    trampolines->ctiNativeCall = patchBuffer.trampolineAt(nativeCallThunk);
+    trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk);
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
 #endif
-    const int NativeCallFrameSize = (sizeof(NativeCallFrameStructure) + 15) & ~15;
-    // Allocate system stack frame
-    subPtr(Imm32(NativeCallFrameSize), stackPointerRegister);
+}
 
-    // Set up arguments
-    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isConstruct)
+{
+    int executableOffsetToFunction = isConstruct ? OBJECT_OFFSETOF(NativeExecutable, m_constructor) : OBJECT_OFFSETOF(NativeExecutable, m_function);
 
-    // push argcount
-    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_argCount)));
-    
-    // Calculate the start of the callframe header, and store in regT1
-    addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int)sizeof(Register)), callFrameRegister, regT1);
+    Label nativeCallThunk = align();
     
-    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT0)
-    mul32(Imm32(sizeof(Register)), regT0, regT0);
-    subPtr(regT0, regT1);
-    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_args)));
-
-    // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
-    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, args)), stackPointerRegister, regT0);
-    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, argPointer)));
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
 
-    // regT1 currently points to the first argument, regT1 - sizeof(Register) points to 'this'
-    loadPtr(Address(regT1, -(int)sizeof(Register)), regT1);
-    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue)));
-
-#if COMPILER(MSVC) || OS(LINUX)
-    // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
-    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx);
-
-    // Plant callee
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::eax);
-    storePtr(X86Registers::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
+#if CPU(X86_64)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Plant callframe
-    move(callFrameRegister, X86Registers::edx);
+    peek(regT1);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC);
 
-    call(Address(X86Registers::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
+    // Calling convention:      f(edi, esi, edx, ecx, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, X86Registers::edi);
 
-    // JSValue is a non-POD type
-    loadPtr(Address(X86Registers::eax), X86Registers::eax);
-#else
-    // Plant callee
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::edx);
+    subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call.
 
-    // Plant callframe
-    move(callFrameRegister, X86Registers::ecx);
-    call(Address(X86Registers::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
-#endif
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::esi);
+    loadPtr(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_executable)), X86Registers::r9);
+    move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    call(Address(X86Registers::r9, executableOffsetToFunction));
 
-    // We've put a few temporaries on the stack in addition to the actual arguments
-    // so pull them off now
-    addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
+    addPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister);
 
 #elif CPU(ARM)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
-
-    // Allocate stack space for our arglist
-    COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0, ArgList_should_by_8byte_aligned);
-    subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
-
-    // Set up arguments
-    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
-
-    // Push argcount
-    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
-
-    // Calculate the start of the callframe header, and store in regT1
-    move(callFrameRegister, regT1);
-    sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
-
-    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
-    mul32(Imm32(sizeof(Register)), regT0, regT0);
-    subPtr(regT0, regT1);
-
-    // push pointer to arguments
-    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
-
-    // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
-
-#if OS(WINCE)
-    // Setup arg3:
-    loadPtr(Address(regT1, -(int32_t)sizeof(Register)), ARMRegisters::r3);
-
-    // Setup arg2:
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2);
-
-    // Setup arg1:
-    move(callFrameRegister, regT1);
-
-    // Setup arg0:
-    move(stackPointerRegister, regT0);
-    subPtr(Imm32(sizeof(Register)), stackPointerRegister);
-    storePtr(regT0, Address(stackPointerRegister));
-
-    call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data)));
-
-    loadPtr(Address(regT0), regT0);
-
-    addPtr(Imm32(sizeof(Register) + sizeof(ArgList)), stackPointerRegister);
-#else // OS(WINCE)
-    // Setup arg3:
-    loadPtr(Address(regT1, -(int32_t)sizeof(Register)), regT2);
-
-    // Setup arg2:
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT1);
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Setup arg1:
-    move(callFrameRegister, regT0);
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    // Setup arg4: This is a plain hack
-    move(stackPointerRegister, ARMRegisters::r3);
+    // Calling convention:      f(r0 == regT0, r1 == regT1, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, ARMRegisters::r0);
 
-    call(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_data)));
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    call(Address(regT2, executableOffsetToFunction));
 
-    addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
-#endif // OS(WINCE)
+    restoreReturnAddressBeforeReturn(regT3);
 
 #elif CPU(MIPS)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
-
-    // Allocate stack space for our arglist
-    COMPILE_ASSERT(!(sizeof(ArgList) & 0x7), ArgList_should_by_8byte_aligned);
-    subPtr(Imm32(sizeof(ArgList) + 24), stackPointerRegister);
-
-    // Set up arguments
-    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
-
-    // Push argcount to 24 + offset($sp)
-    storePtr(regT0, Address(stackPointerRegister, 24 + OBJECT_OFFSETOF(ArgList, m_argCount)));
-
-    // Calculate the start of the callframe header, and store in regT1
-    move(callFrameRegister, regT1);
-    sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
-
-    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
-    mul32(Imm32(sizeof(Register)), regT0, regT0);
-    subPtr(regT0, regT1);
-
-    // push pointer to arguments to 24 + offset($sp)
-    storePtr(regT1, Address(stackPointerRegister, 24 + OBJECT_OFFSETOF(ArgList, m_args)));
-
-    // Setup arg3: regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
-    loadPtr(Address(regT1, -(int32_t)sizeof(Register)), MIPSRegisters::a3);
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Setup arg2:
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2);
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    // Setup arg1:
-    move(callFrameRegister, MIPSRegisters::a1);
+    // Calling convention:      f(a0, a1, a2, a3);
+    // Host function signature: f(ExecState*);
 
-    // Setup arg4: ArgList is passed by reference.  At 16($sp), store ($sp + 24)
-    addPtr(Imm32(24), stackPointerRegister, regT2);
-    storePtr(regT2, Address(stackPointerRegister, 16));
+    // Allocate stack space for 16 bytes (8-byte aligned)
+    // 16 bytes (unused) for 4 arguments
+    subPtr(TrustedImm32(16), stackPointerRegister);
 
-    // Setup arg0 as 20($sp) to hold the returned structure.
-    ASSERT(sizeof(JSValue) == 4);
-    addPtr(Imm32(20), stackPointerRegister, MIPSRegisters::a0);
+    // Setup arg0
+    move(callFrameRegister, MIPSRegisters::a0);
 
     // Call
-    call(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_data)));
-
-    // Get returned value from 0($v0) which is the same as 20($sp)
-    loadPtr(Address(returnValueRegister, 0), returnValueRegister);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2);
+    loadPtr(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    call(Address(regT2, executableOffsetToFunction));
 
     // Restore stack space
-    addPtr(Imm32(sizeof(ArgList) + 24), stackPointerRegister);
+    addPtr(TrustedImm32(16), stackPointerRegister);
+
+    restoreReturnAddressBeforeReturn(regT3);
 
 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
+    UNUSED_PARAM(executableOffsetToFunction);
     breakpoint();
 #endif
 
@@ -406,65 +277,31 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     loadPtr(&(globalData->exception), regT2);
     Jump exceptionHandler = branchTestPtr(NonZero, regT2);
 
-    // Grab the return address.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
-    
-    // Restore our caller's "r".
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
-    
     // Return.
-    restoreReturnAddressBeforeReturn(regT1);
     ret();
 
     // Handle an exception
     exceptionHandler.link(this);
+
     // Grab the return address.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
-    move(ImmPtr(&globalData->exceptionLocation), regT2);
-    storePtr(regT1, regT2);
-    move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
-    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
-    restoreReturnAddressBeforeReturn(regT2);
-    ret();
-    
+    preserveReturnAddressAfterCall(regT1);
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
-    Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
-    Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
-#endif
+    move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
+    storePtr(regT1, regT2);
+    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
 
-    // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
-    LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
+    // Set the return address.
+    move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
+    restoreReturnAddressBeforeReturn(regT1);
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
-    patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
-    patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
-#endif
-    patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
-#if ENABLE(JIT_OPTIMIZE_CALL)
-    patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
-    patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
-#endif
+    ret();
 
-    CodeRef finalCode = patchBuffer.finalizeCode();
-    *executablePool = finalCode.m_executablePool;
+    return nativeCallThunk;
+}
 
-    trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
-    trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
-    trampolines->ctiNativeCallThunk = adoptRef(new NativeExecutable(JITCode(JITCode::HostFunction(trampolineAt(finalCode, nativeCallThunk)))));
-#if ENABLE(JIT_OPTIMIZE_MOD)
-    trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin);
-#endif
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
-#else
-    UNUSED_PARAM(ctiStringLengthTrampoline);
-#endif
+JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool>, JSGlobalData* globalData, NativeFunction)
+{
+    return globalData->jitStubs->ctiNativeCall();
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
@@ -490,8 +327,6 @@ void JIT::emit_op_mov(Instruction* currentInstruction)
 
 void JIT::emit_op_end(Instruction* currentInstruction)
 {
-    if (m_codeBlock->needsFullScopeChain())
-        JITStubCall(this, cti_op_end).call();
     ASSERT(returnValueRegister != callFrameRegister);
     emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
     restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
@@ -502,7 +337,6 @@ void JIT::emit_op_jmp(Instruction* currentInstruction)
 {
     unsigned target = currentInstruction[1].u.operand;
     addJump(jump(), target);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
@@ -515,11 +349,7 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
-#else
-        int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
-#endif
         addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target);
     } else {
         emitGetVirtualRegisters(op1, regT0, op2, regT1);
@@ -534,6 +364,20 @@ void JIT::emit_op_new_object(Instruction* currentInstruction)
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_check_has_instance(Instruction* currentInstruction)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    emitGetVirtualRegister(baseVal, regT0);
+
+    // Check that baseVal is a cell.
+    emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
+
+    // Check that baseVal 'ImplementsHasInstance'.
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT0);
+    addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsHasInstance)));
+}
+
 void JIT::emit_op_instanceof(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -547,43 +391,40 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     emitGetVirtualRegister(baseVal, regT0);
     emitGetVirtualRegister(proto, regT1);
 
-    // Check that baseVal & proto are cells.
+    // Check that proto are cells.  baseVal must be a cell - this is checked by op_check_has_instance.
     emitJumpSlowCaseIfNotJSCell(regT2, value);
-    emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
     emitJumpSlowCaseIfNotJSCell(regT1, proto);
 
+    // Check that prototype is an object
+    loadPtr(Address(regT1, JSCell::structureOffset()), regT3);
+    addSlowCase(branch8(NotEqual, Address(regT3, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
+    
+    // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT0);
+    addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance)));
 
     // Optimistically load the result true, and start looping.
     // Initially, regT1 still contains proto and regT2 still contains value.
     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
-    move(ImmPtr(JSValue::encode(jsBoolean(true))), regT0);
+    move(TrustedImmPtr(JSValue::encode(jsBoolean(true))), regT0);
     Label loop(this);
 
     // Load the prototype of the object in regT2.  If this is equal to regT1 - WIN!
     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
+    loadPtr(Address(regT2, JSCell::structureOffset()), regT2);
+    loadPtr(Address(regT2, Structure::prototypeOffset()), regT2);
     Jump isInstance = branchPtr(Equal, regT2, regT1);
     emitJumpIfJSCell(regT2).linkTo(loop, this);
 
     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
-    move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0);
+    move(TrustedImmPtr(JSValue::encode(jsBoolean(false))), regT0);
 
     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
     isInstance.link(this);
     emitPutVirtualRegister(dst);
 }
 
-void JIT::emit_op_new_func(Instruction* currentInstruction)
-{
-    JITStubCall stubCall(this, cti_op_new_func);
-    stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
-    stubCall.call(currentInstruction[1].u.operand);
-}
-
 void JIT::emit_op_call(Instruction* currentInstruction)
 {
     compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
@@ -594,18 +435,6 @@ void JIT::emit_op_call_eval(Instruction* currentInstruction)
     compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
 }
 
-void JIT::emit_op_load_varargs(Instruction* currentInstruction)
-{
-    int argCountDst = currentInstruction[1].u.operand;
-    int argsOffset = currentInstruction[2].u.operand;
-
-    JITStubCall stubCall(this, cti_op_load_varargs);
-    stubCall.addArgument(Imm32(argsOffset));
-    stubCall.call();
-    // Stores a naked int32 in the register file.
-    store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register)));
-}
-
 void JIT::emit_op_call_varargs(Instruction* currentInstruction)
 {
     compileOpCallVarargs(currentInstruction);
@@ -618,64 +447,93 @@ void JIT::emit_op_construct(Instruction* currentInstruction)
 
 void JIT::emit_op_get_global_var(Instruction* currentInstruction)
 {
-    JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);
-    move(ImmPtr(globalObject), regT0);
-    emitGetVariableObjectRegister(regT0, currentInstruction[3].u.operand, regT0);
+    JSVariableObject* globalObject = m_codeBlock->globalObject();
+    loadPtr(&globalObject->m_registers, regT0);
+    loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_put_global_var(Instruction* currentInstruction)
 {
-    emitGetVirtualRegister(currentInstruction[3].u.operand, regT1);
-    JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);
-    move(ImmPtr(globalObject), regT0);
-    emitPutVariableObjectRegister(regT1, regT0, currentInstruction[2].u.operand);
+    emitGetVirtualRegister(currentInstruction[2].u.operand, regT1);
+    JSVariableObject* globalObject = m_codeBlock->globalObject();
+    loadPtr(&globalObject->m_registers, regT0);
+    storePtr(regT1, Address(regT0, currentInstruction[1].u.operand * sizeof(Register)));
 }
 
 void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
 {
-    int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
+    int skip = currentInstruction[3].u.operand;
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
 
     loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
-    emitGetVariableObjectRegister(regT0, currentInstruction[2].u.operand, regT0);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT0);
+    loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
 {
-    int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
+    int skip = currentInstruction[2].u.operand;
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
     emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
 
     loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
-    emitPutVariableObjectRegister(regT0, regT1, currentInstruction[1].u.operand);
+    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1);
+    storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
 }
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
 {
+    unsigned activation = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    Jump activationCreated = branchTestPtr(NonZero, addressFor(activation));
+    Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments));
+    activationCreated.link(this);
     JITStubCall stubCall(this, cti_op_tear_off_activation);
-    stubCall.addArgument(currentInstruction[1].u.operand, regT2);
+    stubCall.addArgument(activation, regT2);
+    stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2);
     stubCall.call();
+    argumentsNotCreated.link(this);
 }
 
-void JIT::emit_op_tear_off_arguments(Instruction*)
+void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
 {
-    JITStubCall(this, cti_op_tear_off_arguments).call();
+    unsigned dst = currentInstruction[1].u.operand;
+
+    Jump argsNotCreated = branchTestPtr(Zero, Address(callFrameRegister, sizeof(Register) * (unmodifiedArgumentsRegister(dst))));
+    JITStubCall stubCall(this, cti_op_tear_off_arguments);
+    stubCall.addArgument(unmodifiedArgumentsRegister(dst), regT2);
+    stubCall.call();
+    argsNotCreated.link(this);
 }
 
 void JIT::emit_op_ret(Instruction* currentInstruction)
 {
-    // We could JIT generate the deref, only calling out to C when the refcount hits zero.
-    if (m_codeBlock->needsFullScopeChain())
-        JITStubCall(this, cti_op_ret_scopeChain).call();
-
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -694,31 +552,51 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
     ret();
 }
 
-void JIT::emit_op_new_array(Instruction* currentInstruction)
+void JIT::emit_op_ret_object_or_this(Instruction* currentInstruction)
 {
-    JITStubCall stubCall(this, cti_op_new_array);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
-    stubCall.call(currentInstruction[1].u.operand);
+    ASSERT(callFrameRegister != regT1);
+    ASSERT(regT1 != returnValueRegister);
+    ASSERT(returnValueRegister != callFrameRegister);
+
+    // Return the result in %eax.
+    emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
+    Jump notJSCell = emitJumpIfNotJSCell(returnValueRegister);
+    loadPtr(Address(returnValueRegister, JSCell::structureOffset()), regT2);
+    Jump notObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
+
+    // Grab the return address.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+
+    // Restore our caller's "r".
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+    // Return.
+    restoreReturnAddressBeforeReturn(regT1);
+    ret();
+
+    // Return 'this' in %eax.
+    notJSCell.link(this);
+    notObject.link(this);
+    emitGetVirtualRegister(currentInstruction[2].u.operand, returnValueRegister);
+
+    // Grab the return address.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+
+    // Restore our caller's "r".
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+
+    // Return.
+    restoreReturnAddressBeforeReturn(regT1);
+    ret();
 }
 
 void JIT::emit_op_resolve(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emit_op_construct_verify(Instruction* currentInstruction)
-{
-    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
-
-    emitJumpSlowCaseIfNotJSCell(regT0);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
-
-}
-
 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
@@ -727,7 +605,7 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction)
     emitGetVirtualRegister(src, regT0);
     
     Jump isImm = emitJumpIfNotJSCell(regT0);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
     isImm.link(this);
 
     if (dst != src)
@@ -745,36 +623,44 @@ void JIT::emit_op_strcat(Instruction* currentInstruction)
 
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
-    JITStubCall stubCall(this, cti_op_resolve_base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base);
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
+{
+    JITStubCall stubCall(this, cti_op_ensure_property_exists);
+    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_skip);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain()));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
 {
     // Fast case
-    void* globalObject = currentInstruction[2].u.jsCell;
+    void* globalObject = m_codeBlock->globalObject();
     unsigned currentIndex = m_globalResolveInfoIndex++;
-    void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
-    void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
+    GlobalResolveInfo* resolveInfoAddress = &(m_codeBlock->globalResolveInfo(currentIndex));
 
     // Check Structure of global object
-    move(ImmPtr(globalObject), regT0);
-    loadPtr(structureAddress, regT1);
-    addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)))); // Structures don't match
+    move(TrustedImmPtr(globalObject), regT0);
+    move(TrustedImmPtr(resolveInfoAddress), regT2);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), regT1);
+    addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, JSCell::structureOffset()))); // Structures don't match
 
     // Load cached property
     // Assume that the global object always uses external storage.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT0);
-    load32(offsetAddr, regT1);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT0);
+    load32(Address(regT2, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT1);
     loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
@@ -782,25 +668,29 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool)
 void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
-    void* globalObject = currentInstruction[2].u.jsCell;
-    Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
+    Identifier* ident = &m_codeBlock->identifier(currentInstruction[2].u.operand);
     
     unsigned currentIndex = m_globalResolveInfoIndex++;
     
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_resolve_global);
-    stubCall.addArgument(ImmPtr(globalObject));
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(Imm32(currentIndex));
+    stubCall.addArgument(regT0);
     stubCall.call(dst);
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
 {
     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
-    xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);
-    addSlowCase(branchTestPtr(NonZero, regT0, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue))));
-    xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0);
+
+    // Invert against JSValue(false); if the value was tagged as a boolean, then all bits will be
+    // clear other than the low bit (which will be 0 or 1 for false or true inputs respectively).
+    // Then invert against JSValue(true), which will add the tag back in, and flip the low bit.
+    xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), regT0);
+    addSlowCase(branchTestPtr(NonZero, regT0, TrustedImm32(static_cast<int32_t>(~1))));
+    xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), regT0);
+
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
@@ -809,14 +699,13 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction)
     unsigned target = currentInstruction[2].u.operand;
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target);
+    addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNumber(0)))), target);
     Jump isNonZero = emitJumpIfImmediateInteger(regT0);
 
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target);
-    addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))));
+    addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(false)))), target);
+    addSlowCase(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(true)))));
 
     isNonZero.link(this);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
@@ -828,17 +717,16 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction)
     Jump isImmediate = emitJumpIfNotJSCell(regT0);
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    addJump(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target);
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
-    andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target);            
+    andPtr(TrustedImm32(~TagBitUndefined), regT0);
+    addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target);            
 
     wasNotImmediate.link(this);
-    RECORD_JUMP_TARGET(target);
 };
 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 {
@@ -849,40 +737,36 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
     Jump isImmediate = emitJumpIfNotJSCell(regT0);
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    addJump(branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target);
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
-    andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
-    addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target);            
+    andPtr(TrustedImm32(~TagBitUndefined), regT0);
+    addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsNull()))), target);            
 
     wasNotImmediate.link(this);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
 {
     unsigned src = currentInstruction[1].u.operand;
-    JSCell* ptr = currentInstruction[2].u.jsCell;
+    JSCell* ptr = currentInstruction[2].u.jsCell.get();
     unsigned target = currentInstruction[3].u.operand;
     
     emitGetVirtualRegister(src, regT0);
-    addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target);            
-
-    RECORD_JUMP_TARGET(target);
+    addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target);            
 }
 
 void JIT::emit_op_jsr(Instruction* currentInstruction)
 {
     int retAddrDst = currentInstruction[1].u.operand;
     int target = currentInstruction[2].u.operand;
-    DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
+    DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
     addJump(jump(), target);
     m_jsrSites.append(JSRInfo(storeLocation, label()));
     killLastResultRegister();
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_sret(Instruction* currentInstruction)
@@ -895,7 +779,7 @@ void JIT::emit_op_eq(Instruction* currentInstruction)
 {
     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
     emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
-    set32(Equal, regT1, regT0, regT0);
+    compare32(Equal, regT1, regT0, regT0);
     emitTagAsBoolImmediate(regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
@@ -904,19 +788,15 @@ void JIT::emit_op_bitnot(Instruction* currentInstruction)
 {
     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
     not32(regT0);
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    xorPtr(Imm32(~JSImmediate::TagTypeNumber), regT0);
-#endif
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_with_base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call(currentInstruction[2].u.operand);
 }
@@ -924,7 +804,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func_exp);
-    stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -933,21 +813,20 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction)
     unsigned target = currentInstruction[2].u.operand;
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
-    Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
+    Jump isZero = branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsNumber(0))));
     addJump(emitJumpIfImmediateInteger(regT0), target);
 
-    addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target);
-    addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
+    addJump(branchPtr(Equal, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(true)))), target);
+    addSlowCase(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(jsBoolean(false)))));
 
     isZero.link(this);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_neq(Instruction* currentInstruction)
 {
     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
     emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
-    set32(NotEqual, regT1, regT0, regT0);
+    compare32(NotEqual, regT1, regT0, regT0);
     emitTagAsBoolImmediate(regT0);
 
     emitPutVirtualRegister(currentInstruction[1].u.operand);
@@ -997,9 +876,9 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
     emitGetVirtualRegister(base, regT0);
     if (!m_codeBlock->isKnownNotImmediate(base))
         isNotObject.append(emitJumpIfNotJSCell(regT0));
-    if (base != m_codeBlock->thisRegister()) {
-        loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-        isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+    if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
+        loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+        isNotObject.append(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
     }
 
     // We could inline the case where you have a valid cache, but
@@ -1009,14 +888,15 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
     getPnamesStubCall.addArgument(regT0);
     getPnamesStubCall.call(dst);
     load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
-    store32(Imm32(0), addressFor(i));
-    store32(regT3, addressFor(size));
+    storePtr(tagTypeNumberRegister, payloadFor(i));
+    store32(TrustedImm32(Int32Tag), intTagFor(size));
+    store32(regT3, intPayloadFor(size));
     Jump end = jump();
 
     isNotObject.link(this);
     move(regT0, regT1);
-    and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT1);
-    addJump(branch32(Equal, regT1, Imm32(JSImmediate::FullTagTypeNull)), breakTarget);
+    and32(TrustedImm32(~TagBitUndefined), regT1);
+    addJump(branch32(Equal, regT1, TrustedImm32(ValueNull)), breakTarget);
 
     JITStubCall toObjectStubCall(this, cti_to_object);
     toObjectStubCall.addArgument(regT0);
@@ -1038,30 +918,26 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction)
     JumpList callHasProperty;
 
     Label begin(this);
-    load32(addressFor(i), regT0);
-    Jump end = branch32(Equal, regT0, addressFor(size));
+    load32(intPayloadFor(i), regT0);
+    Jump end = branch32(Equal, regT0, intPayloadFor(size));
 
     // Grab key @ i
     loadPtr(addressFor(it), regT1);
     loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
 
-#if USE(JSVALUE64)
     loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2);
-#else
-    loadPtr(BaseIndex(regT2, regT0, TimesFour), regT2);
-#endif
 
     emitPutVirtualRegister(dst, regT2);
 
     // Increment i
-    add32(Imm32(1), regT0);
-    store32(regT0, addressFor(i));
+    add32(TrustedImm32(1), regT0);
+    store32(regT0, intPayloadFor(i));
 
     // Verify that i is valid:
     emitGetVirtualRegister(base, regT0);
 
     // Test base's structure
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
     callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
 
     // Test base's prototype chain
@@ -1070,11 +946,11 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction)
     addJump(branchTestPtr(Zero, Address(regT3)), target);
 
     Label checkPrototype(this);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
+    loadPtr(Address(regT2, Structure::prototypeOffset()), regT2);
     callHasProperty.append(emitJumpIfNotJSCell(regT2));
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    loadPtr(Address(regT2, JSCell::structureOffset()), regT2);
     callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
-    addPtr(Imm32(sizeof(Structure*)), regT3);
+    addPtr(TrustedImm32(sizeof(Structure*)), regT3);
     branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
 
     // Continue loop.
@@ -1123,9 +999,9 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy
     addSlowCase(emitJumpIfImmediateNumber(regT2));
 
     if (type == OpStrictEq)
-        set32(Equal, regT1, regT0, regT0);
+        compare32(Equal, regT1, regT0, regT0);
     else
-        set32(NotEqual, regT1, regT0, regT0);
+        compare32(NotEqual, regT1, regT0, regT0);
     emitTagAsBoolImmediate(regT0);
 
     emitPutVirtualRegister(dst);
@@ -1149,8 +1025,8 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
     Jump wasImmediate = emitJumpIfImmediateInteger(regT0);
 
     emitJumpSlowCaseIfNotJSCell(regT0, srcVReg);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(NumberType)));
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    addSlowCase(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(NumberType)));
     
     wasImmediate.link(this);
 
@@ -1160,7 +1036,7 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
 void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_push_new_scope);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
     stubCall.call(currentInstruction[1].u.operand);
 }
@@ -1168,7 +1044,10 @@ void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
 void JIT::emit_op_catch(Instruction* currentInstruction)
 {
     killLastResultRegister(); // FIXME: Implicitly treat op_catch as a labeled statement, and remove this line of code.
-    peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+    move(regT0, callFrameRegister);
+    peek(regT3, OBJECT_OFFSETOF(struct JITStackFrame, globalData) / sizeof(void*));
+    loadPtr(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception)), regT0);
+    storePtr(TrustedImmPtr(JSValue::encode(JSValue())), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception)));
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
 
@@ -1178,7 +1057,6 @@ void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call();
     addJump(jump(), currentInstruction[2].u.operand);
-    RECORD_JUMP_TARGET(currentInstruction[2].u.operand);
 }
 
 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
@@ -1189,7 +1067,7 @@ void JIT::emit_op_switch_imm(Instruction* currentInstruction)
 
     // create jump table for switch destinations, track this switch statement.
     SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
-    m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate));
+    m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Immediate));
     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
 
     JITStubCall stubCall(this, cti_op_switch_imm);
@@ -1207,7 +1085,7 @@ void JIT::emit_op_switch_char(Instruction* currentInstruction)
 
     // create jump table for switch destinations, track this switch statement.
     SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
-    m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character));
+    m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Character));
     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
 
     JITStubCall stubCall(this, cti_op_switch_char);
@@ -1225,7 +1103,7 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
 
     // create jump table for switch destinations, track this switch statement.
     StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
-    m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset));
+    m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset));
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee, regT2);
@@ -1234,13 +1112,11 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
     jump(regT0);
 }
 
-void JIT::emit_op_new_error(Instruction* currentInstruction)
+void JIT::emit_op_throw_reference_error(Instruction* currentInstruction)
 {
-    JITStubCall stubCall(this, cti_op_new_error);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[3].u.operand))));
-    stubCall.addArgument(Imm32(m_bytecodeIndex));
-    stubCall.call(currentInstruction[1].u.operand);
+    JITStubCall stubCall(this, cti_op_throw_reference_error);
+    stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[1].u.operand))));
+    stubCall.call();
 }
 
 void JIT::emit_op_debug(Instruction* currentInstruction)
@@ -1265,15 +1141,15 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction)
     emitGetVirtualRegister(src1, regT0);
     Jump isImmediate = emitJumpIfNotJSCell(regT0);
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    setTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    test8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0);
 
     Jump wasNotImmediate = jump();
 
     isImmediate.link(this);
 
-    andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
-    setPtr(Equal, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);
+    andPtr(TrustedImm32(~TagBitUndefined), regT0);
+    comparePtr(Equal, regT0, TrustedImm32(ValueNull), regT0);
 
     wasNotImmediate.link(this);
 
@@ -1290,21 +1166,20 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction)
     emitGetVirtualRegister(src1, regT0);
     Jump isImmediate = emitJumpIfNotJSCell(regT0);
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    setTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    test8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0);
 
     Jump wasNotImmediate = jump();
 
     isImmediate.link(this);
 
-    andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
-    setPtr(NotEqual, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);
+    andPtr(TrustedImm32(~TagBitUndefined), regT0);
+    comparePtr(NotEqual, regT0, TrustedImm32(ValueNull), regT0);
 
     wasNotImmediate.link(this);
 
     emitTagAsBoolImmediate(regT0);
     emitPutVirtualRegister(dst);
-
 }
 
 void JIT::emit_op_enter(Instruction*)
@@ -1318,31 +1193,35 @@ void JIT::emit_op_enter(Instruction*)
 
 }
 
-void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
+void JIT::emit_op_create_activation(Instruction* currentInstruction)
 {
-    // Even though CTI doesn't use them, we initialize our constant
-    // registers to zap stale pointers, to avoid unnecessarily prolonging
-    // object lifetime and increasing GC pressure.
-    size_t count = m_codeBlock->m_numVars;
-    for (size_t j = 0; j < count; ++j)
-        emitInitRegister(j);
-
+    unsigned dst = currentInstruction[1].u.operand;
+    
+    Jump activationCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
     JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
+    emitPutVirtualRegister(dst);
+    activationCreated.link(this);
 }
 
-void JIT::emit_op_create_arguments(Instruction*)
+void JIT::emit_op_create_arguments(Instruction* currentInstruction)
 {
-    Jump argsCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * RegisterFile::ArgumentsRegister));
+    unsigned dst = currentInstruction[1].u.operand;
+
+    Jump argsCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst));
     if (m_codeBlock->m_numParameters == 1)
         JITStubCall(this, cti_op_create_arguments_no_params).call();
     else
         JITStubCall(this, cti_op_create_arguments).call();
+    emitPutVirtualRegister(dst);
+    emitPutVirtualRegister(unmodifiedArgumentsRegister(dst));
     argsCreated.link(this);
 }
-    
-void JIT::emit_op_init_arguments(Instruction*)
+
+void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction)
 {
-    storePtr(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * RegisterFile::ArgumentsRegister));
+    unsigned dst = currentInstruction[1].u.operand;
+
+    storePtr(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * dst));
 }
 
 void JIT::emit_op_convert_this(Instruction* currentInstruction)
@@ -1350,14 +1229,44 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction)
     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
 
     emitJumpSlowCaseIfNotJSCell(regT0);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
-    addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    addSlowCase(branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
+}
 
+void JIT::emit_op_convert_this_strict(Instruction* currentInstruction)
+{
+    emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
+    Jump notNull = branchTestPtr(NonZero, regT0);
+    move(TrustedImmPtr(JSValue::encode(jsNull())), regT0);
+    emitPutVirtualRegister(currentInstruction[1].u.operand, regT0);
+    Jump setThis = jump();
+    notNull.link(this);
+    Jump isImmediate = emitJumpIfNotJSCell(regT0);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    Jump notAnObject = branch8(NotEqual, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
+    addSlowCase(branchTest8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
+    isImmediate.link(this);
+    notAnObject.link(this);
+    setThis.link(this);
+}
+
+void JIT::emit_op_get_callee(Instruction* currentInstruction)
+{
+    unsigned result = currentInstruction[1].u.operand;
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
+    emitPutVirtualRegister(result);
+}
+
+void JIT::emit_op_create_this(Instruction* currentInstruction)
+{
+    JITStubCall stubCall(this, cti_op_create_this);
+    stubCall.addArgument(currentInstruction[2].u.operand, regT1);
+    stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
 {
-    peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+    peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
     Jump noProfiler = branchTestPtr(Zero, Address(regT1));
 
     JITStubCall stubCall(this, cti_op_profile_will_call);
@@ -1369,7 +1278,7 @@ void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
 
 void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
 {
-    peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+    peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
     Jump noProfiler = branchTestPtr(Zero, Address(regT1));
 
     JITStubCall stubCall(this, cti_op_profile_did_call);
@@ -1390,12 +1299,12 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-void JIT::emitSlow_op_construct_verify(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkSlowCase(iter);
-    linkSlowCase(iter);
-    emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
-    emitPutVirtualRegister(currentInstruction[1].u.operand);
+    JITStubCall stubCall(this, cti_op_convert_this_strict);
+    stubCall.addArgument(regT0);
+    stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1450,7 +1359,7 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas
 void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     linkSlowCase(iter);
-    xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);
+    xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), regT0);
     JITStubCall stubCall(this, cti_op_not);
     stubCall.addArgument(regT0);
     stubCall.call(currentInstruction[1].u.operand);
@@ -1518,7 +1427,7 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT1);
     stubCall.call();
-    xor32(Imm32(0x1), regT0);
+    xor32(TrustedImm32(0x1), regT0);
     emitTagAsBoolImmediate(regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
@@ -1543,6 +1452,17 @@ void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCase
     stubCall.call(currentInstruction[1].u.operand);
 }
 
+void JIT::emitSlow_op_check_has_instance(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, baseVal);
+    linkSlowCase(iter);
+    JITStubCall stubCall(this, cti_op_check_has_instance);
+    stubCall.addArgument(baseVal, regT2);
+    stubCall.call();
+}
+
 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -1551,9 +1471,9 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     unsigned proto = currentInstruction[4].u.operand;
 
     linkSlowCaseIfNotJSCell(iter, value);
-    linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
+    linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_instanceof);
     stubCall.addArgument(value, regT2);
     stubCall.addArgument(baseVal, regT2);
@@ -1591,13 +1511,107 @@ void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCa
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-#endif // !USE(JSVALUE32_64)
+void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister)));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    sub32(TrustedImm32(1), regT0);
+    emitFastArithReTagImmediate(regT0, regT0);
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned base = currentInstruction[2].u.operand;
+    Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
+    
+    emitGetVirtualRegister(base, regT0);
+    JITStubCall stubCall(this, cti_op_get_by_id_generic);
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(TrustedImmPtr(ident));
+    stubCall.call(dst);
+}
+
+void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    addSlowCase(branchTestPtr(NonZero, addressFor(argumentsRegister)));
+    emitGetVirtualRegister(property, regT1);
+    addSlowCase(emitJumpIfNotImmediateInteger(regT1));
+    add32(TrustedImm32(1), regT1);
+    // regT1 now contains the integer index of the argument we want, including this
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT2);
+    addSlowCase(branch32(AboveOrEqual, regT1, regT2));
+    
+    Jump skipOutofLineParams;
+    int numArgs = m_codeBlock->m_numParameters;
+    if (numArgs) {
+        Jump notInInPlaceArgs = branch32(AboveOrEqual, regT1, Imm32(numArgs));
+        addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0);
+        loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0);
+        skipOutofLineParams = jump();
+        notInInPlaceArgs.link(this);
+    }
+    
+    addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT0);
+    mul32(TrustedImm32(sizeof(Register)), regT2, regT2);
+    subPtr(regT2, regT0);
+    loadPtr(BaseIndex(regT0, regT1, TimesEight, 0), regT0);
+    if (numArgs)
+        skipOutofLineParams.link(this);
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+    
+    linkSlowCase(iter);
+    Jump skipArgumentsCreation = jump();
+    
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    if (m_codeBlock->m_numParameters == 1)
+        JITStubCall(this, cti_op_create_arguments_no_params).call();
+    else
+        JITStubCall(this, cti_op_create_arguments).call();
+    emitPutVirtualRegister(arguments);
+    emitPutVirtualRegister(unmodifiedArgumentsRegister(arguments));
+    
+    skipArgumentsCreation.link(this);
+    JITStubCall stubCall(this, cti_op_get_by_val);
+    stubCall.addArgument(arguments, regT2);
+    stubCall.addArgument(property, regT2);
+    stubCall.call(dst);
+}
+
+#endif // USE(JSVALUE64)
 
 void JIT::emit_op_resolve_global_dynamic(Instruction* currentInstruction)
 {
-    int skip = currentInstruction[6].u.operand + m_codeBlock->needsFullScopeChain();
+    int skip = currentInstruction[5].u.operand;
     
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
+    
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
+        addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get()));
+        loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
+        activationNotCreated.link(this);
+    }
     while (skip--) {
         loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
         addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get()));
@@ -1609,13 +1623,12 @@ void JIT::emit_op_resolve_global_dynamic(Instruction* currentInstruction)
 void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
-    void* globalObject = currentInstruction[2].u.jsCell;
-    Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
-    int skip = currentInstruction[6].u.operand + m_codeBlock->needsFullScopeChain();
+    Identifier* ident = &m_codeBlock->identifier(currentInstruction[2].u.operand);
+    int skip = currentInstruction[5].u.operand;
     while (skip--)
         linkSlowCase(iter);
     JITStubCall resolveStubCall(this, cti_op_resolve);
-    resolveStubCall.addArgument(ImmPtr(ident));
+    resolveStubCall.addArgument(TrustedImmPtr(ident));
     resolveStubCall.call(dst);
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_resolve_global_dynamic));
     
@@ -1623,94 +1636,123 @@ void JIT::emitSlow_op_resolve_global_dynamic(Instruction* currentInstruction, Ve
     
     linkSlowCase(iter); // We managed to skip all the nodes in the scope chain, but the cache missed.
     JITStubCall stubCall(this, cti_op_resolve_global);
-    stubCall.addArgument(ImmPtr(globalObject));
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(Imm32(currentIndex));
+    stubCall.addArgument(regT0);
     stubCall.call(dst);
 }
 
 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_regexp);
-    stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
-// For both JSValue32_64 and JSValue32
-#if ENABLE(JIT_OPTIMIZE_MOD)
-#if CPU(ARM_TRADITIONAL)
-void JIT::softModulo()
+void JIT::emit_op_load_varargs(Instruction* currentInstruction)
 {
-    push(regS0);
-    push(regS1);
-    push(regT1);
-    push(regT3);
+    int argCountDst = currentInstruction[1].u.operand;
+    int argsOffset = currentInstruction[2].u.operand;
+    int registerOffset = currentInstruction[3].u.operand;
+    ASSERT(argsOffset <= registerOffset);
+    
+    int expectedParams = m_codeBlock->m_numParameters - 1;
+    // Don't do inline copying if we aren't guaranteed to have a single stream
+    // of arguments
+    if (expectedParams) {
+        JITStubCall stubCall(this, cti_op_load_varargs);
+        stubCall.addArgument(Imm32(argsOffset));
+        stubCall.call();
+        // Stores a naked int32 in the register file.
+        store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register)));
+        return;
+    }
+
 #if USE(JSVALUE32_64)
-    m_assembler.mov_r(regT3, regT2);
-    m_assembler.mov_r(regT2, regT0);
+    addSlowCase(branch32(NotEqual, tagFor(argsOffset), TrustedImm32(JSValue::EmptyValueTag)));
 #else
-    m_assembler.mov_r(regT3, m_assembler.asr(regT2, 1));
-    m_assembler.mov_r(regT2, m_assembler.asr(regT0, 1));
+    addSlowCase(branchTestPtr(NonZero, addressFor(argsOffset)));
 #endif
-    m_assembler.mov_r(regT1, ARMAssembler::getOp2(0));
-    
-    m_assembler.teq_r(regT3, ARMAssembler::getOp2(0));
-    m_assembler.rsb_r(regT3, regT3, ARMAssembler::getOp2(0), ARMAssembler::MI);
-    m_assembler.eor_r(regT1, regT1, ARMAssembler::getOp2(1), ARMAssembler::MI);
-    
-    m_assembler.teq_r(regT2, ARMAssembler::getOp2(0));
-    m_assembler.rsb_r(regT2, regT2, ARMAssembler::getOp2(0), ARMAssembler::MI);
-    m_assembler.eor_r(regT1, regT1, ARMAssembler::getOp2(2), ARMAssembler::MI);
+    // Load arg count into regT0
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    store32(TrustedImm32(Int32Tag), intTagFor(argCountDst));
+    store32(regT0, intPayloadFor(argCountDst));
+    Jump endBranch = branch32(Equal, regT0, TrustedImm32(1));
+
+    mul32(TrustedImm32(sizeof(Register)), regT0, regT3);
+    addPtr(TrustedImm32(static_cast<unsigned>(sizeof(Register) - RegisterFile::CallFrameHeaderSize * sizeof(Register))), callFrameRegister, regT1);
+    subPtr(regT3, regT1); // regT1 is now the start of the out of line arguments
+    addPtr(Imm32(argsOffset * sizeof(Register)), callFrameRegister, regT2); // regT2 is the target buffer
     
-    Jump exitBranch = branch32(LessThan, regT2, regT3);
+    // Bounds check the registerfile
+    addPtr(regT2, regT3);
+    addPtr(Imm32((registerOffset - argsOffset) * sizeof(Register)), regT3);
+    addSlowCase(branchPtr(Below, AbsoluteAddress(m_globalData->interpreter->registerFile().addressOfEnd()), regT3));
+
+    sub32(TrustedImm32(1), regT0);
+    Label loopStart = label();
+    loadPtr(BaseIndex(regT1, regT0, TimesEight, static_cast<unsigned>(0 - 2 * sizeof(Register))), regT3);
+    storePtr(regT3, BaseIndex(regT2, regT0, TimesEight, static_cast<unsigned>(0 - sizeof(Register))));
+#if USE(JSVALUE32_64)
+    loadPtr(BaseIndex(regT1, regT0, TimesEight, static_cast<unsigned>(sizeof(void*) - 2 * sizeof(Register))), regT3);
+    storePtr(regT3, BaseIndex(regT2, regT0, TimesEight, static_cast<unsigned>(sizeof(void*) - sizeof(Register))));
+#endif
+    branchSubPtr(NonZero, TrustedImm32(1), regT0).linkTo(loopStart, this);
+    endBranch.link(this);
+}
 
-    m_assembler.sub_r(regS1, regT3, ARMAssembler::getOp2(1));
-    m_assembler.tst_r(regS1, regT3);
-    m_assembler.and_r(regT2, regT2, regS1, ARMAssembler::EQ);
-    m_assembler.and_r(regT0, regS1, regT3);
-    Jump exitBranch2 = branchTest32(Zero, regT0);
+void JIT::emitSlow_op_load_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    int argCountDst = currentInstruction[1].u.operand;
+    int argsOffset = currentInstruction[2].u.operand;
+    int expectedParams = m_codeBlock->m_numParameters - 1;
+    if (expectedParams)
+        return;
     
-    m_assembler.clz_r(regS1, regT2);
-    m_assembler.clz_r(regS0, regT3);
-    m_assembler.sub_r(regS0, regS0, regS1);
-
-    m_assembler.rsbs_r(regS0, regS0, ARMAssembler::getOp2(31));
-
-    m_assembler.mov_r(regS0, m_assembler.lsl(regS0, 1), ARMAssembler::NE);
-
-    m_assembler.add_r(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(regS0, 2), ARMAssembler::NE);
-    m_assembler.mov_r(regT0, regT0);
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    JITStubCall stubCall(this, cti_op_load_varargs);
+    stubCall.addArgument(Imm32(argsOffset));
+    stubCall.call();
     
-    for (int i = 31; i > 0; --i) {
-        m_assembler.cmp_r(regT2, m_assembler.lsl(regT3, i));
-        m_assembler.sub_r(regT2, regT2, m_assembler.lsl(regT3, i), ARMAssembler::CS);
-    }
+    store32(TrustedImm32(Int32Tag), intTagFor(argCountDst));
+    store32(returnValueRegister, intPayloadFor(argCountDst));
+}
 
-    m_assembler.cmp_r(regT2, regT3);
-    m_assembler.sub_r(regT2, regT2, regT3, ARMAssembler::CS);
-    
-    exitBranch.link(this);
-    exitBranch2.link(this);
-    
-    m_assembler.teq_r(regT1, ARMAssembler::getOp2(0));
-    m_assembler.rsb_r(regT2, regT2, ARMAssembler::getOp2(0), ARMAssembler::GT);
-    
+void JIT::emit_op_new_func(Instruction* currentInstruction)
+{
+    Jump lazyJump;
+    int dst = currentInstruction[1].u.operand;
+    if (currentInstruction[3].u.operand) {
 #if USE(JSVALUE32_64)
-    m_assembler.mov_r(regT0, regT2);
+        lazyJump = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
 #else
-    m_assembler.mov_r(regT0, m_assembler.lsl(regT2, 1));
-    m_assembler.eor_r(regT0, regT0, ARMAssembler::getOp2(1));
+        lazyJump = branchTestPtr(NonZero, addressFor(dst));
 #endif
-    pop(regT3);
-    pop(regT1);
-    pop(regS1);
-    pop(regS0);
-    ret();
+    }
+    JITStubCall stubCall(this, cti_op_new_func);
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
+    stubCall.call(currentInstruction[1].u.operand);
+    if (currentInstruction[3].u.operand)
+        lazyJump.link(this);
 }
-#else
-#error "JIT_OPTIMIZE_MOD not yet supported on this platform."
-#endif // CPU(ARM_TRADITIONAL)
-#endif
+
+void JIT::emit_op_new_array(Instruction* currentInstruction)
+{
+    JITStubCall stubCall(this, cti_op_new_array);
+    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_new_array_buffer(Instruction* currentInstruction)
+{
+    JITStubCall stubCall(this, cti_op_new_array_buffer);
+    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index ccc0900326f1fa353ce4c5b2e5ddeca523d902da..4f4c5c0b186f7149e96a9368034a7fcab7f29803 100644 (file)
  */
 
 #include "config.h"
-#include "JIT.h"
 
-#if ENABLE(JIT) && USE(JSVALUE32_64)
+#if ENABLE(JIT)
+#if USE(JSVALUE32_64)
+#include "JIT.h"
 
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -41,7 +42,7 @@ namespace JSC {
 
 void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
 {
-#if ENABLE(JIT_OPTIMIZE_MOD)
+#if ENABLE(JIT_USE_SOFT_MODULO)
     Label softModBegin = align();
     softModulo();
 #endif
@@ -51,370 +52,426 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
 
     // regT0 holds payload, regT1 holds tag
 
-    Jump string_failureCases1 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
-    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
+    Jump string_failureCases1 = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
 
     // Checks out okay! - get the length from the Ustring.
     load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_length)), regT2);
 
-    Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX));
+    Jump string_failureCases3 = branch32(Above, regT2, TrustedImm32(INT_MAX));
     move(regT2, regT0);
-    move(Imm32(JSValue::Int32Tag), regT1);
+    move(TrustedImm32(JSValue::Int32Tag), regT1);
 
     ret();
 #endif
-
+    
+    JumpList callLinkFailures;
     // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
-
 #if ENABLE(JIT_OPTIMIZE_CALL)
     // VirtualCallLink Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallLinkBegin = align();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-
-    Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
-
-    Jump hasCodeBlock2 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
-    preserveReturnAddressAfterCall(regT3);
-    restoreArgumentReference();
-    Call callJSFunction2 = call();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-    emitGetJITStubArg(2, regT1); // argCount
-    restoreReturnAddressBeforeReturn(regT3);
-    hasCodeBlock2.link(this);
-
-    // Check argCount matches callee arity.
-    Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
+    compileOpCallInitializeCallFrame();
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
-    Call callArityCheck2 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callLazyLinkCall = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
-    arityCheckOkay2.link(this);
-
-    isNativeFunc2.link(this);
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
+    jump(regT0);
 
+    // VirtualConstructLink Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    Label virtualConstructLinkBegin = align();
     compileOpCallInitializeCallFrame();
-
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
-    Call callLazyLinkCall = call();
+    Call callLazyLinkConstruct = call();
     restoreReturnAddressBeforeReturn(regT3);
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
+
 #endif // ENABLE(JIT_OPTIMIZE_CALL)
 
     // VirtualCall Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    compileOpCallInitializeCallFrame();
 
-    Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
-    Jump hasCodeBlock3 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
+    Jump hasCodeBlock3 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForCall)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
     restoreArgumentReference();
-    Call callJSFunction1 = call();
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callCompileCall = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     restoreReturnAddressBeforeReturn(regT3);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
     hasCodeBlock3.link(this);
 
-    // Check argCount matches callee arity.
-    Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForCallWithArityCheck)), regT0);
+    jump(regT0);
+
+    // VirtualConstruct Trampoline
+    // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    Label virtualConstructBegin = align();
+    compileOpCallInitializeCallFrame();
+
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+
+    Jump hasCodeBlock4 = branch32(GreaterThanOrEqual, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParametersForConstruct)), TrustedImm32(0));
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
-    Call callArityCheck1 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callCompileCconstruct = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     restoreReturnAddressBeforeReturn(regT3);
     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
-    arityCheckOkay3.link(this);
-
-    isNativeFunc3.link(this);
+    hasCodeBlock4.link(this);
 
-    compileOpCallInitializeCallFrame();
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCodeForConstructWithArityCheck)), regT0);
     jump(regT0);
+    
+    // If the parser fails we want to be able to be able to keep going,
+    // So we handle this as a parse failure.
+    callLinkFailures.link(this);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+    restoreReturnAddressBeforeReturn(regT1);
+    move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
+    storePtr(regT1, regT2);
+    poke(callFrameRegister, 1 + OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    poke(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()));
+    ret();
+
+    // NativeCall Trampoline
+    Label nativeCallThunk = privateCompileCTINativeCall(globalData);    
+    Label nativeConstructThunk = privateCompileCTINativeCall(globalData, true);    
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
+    Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
+    Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
+#endif
+
+    // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
+    LinkBuffer patchBuffer(*m_globalData, this, m_globalData->executableAllocator);
+
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
+    patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
+    patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
+#endif
+#if ENABLE(JIT_OPTIMIZE_CALL)
+    patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
+    patchBuffer.link(callLazyLinkConstruct, FunctionPtr(cti_vm_lazyLinkConstruct));
+#endif
+    patchBuffer.link(callCompileCall, FunctionPtr(cti_op_call_jitCompile));
+    patchBuffer.link(callCompileCconstruct, FunctionPtr(cti_op_construct_jitCompile));
+
+    CodeRef finalCode = patchBuffer.finalizeCode();
+    *executablePool = finalCode.m_executablePool;
+
+    trampolines->ctiVirtualCall = patchBuffer.trampolineAt(virtualCallBegin);
+    trampolines->ctiVirtualConstruct = patchBuffer.trampolineAt(virtualConstructBegin);
+#if ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
+    trampolines->ctiNativeCall = patchBuffer.trampolineAt(nativeCallThunk);
+    trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk);
+#endif
+#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
+    trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
+#endif
+#if ENABLE(JIT_OPTIMIZE_CALL)
+    trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
+    trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
+#endif
+#if ENABLE(JIT_USE_SOFT_MODULO)
+    trampolines->ctiSoftModulo = patchBuffer.trampolineAt(softModBegin);
+#endif
+}
+
+JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isConstruct)
+{
+    int executableOffsetToFunction = isConstruct ? OBJECT_OFFSETOF(NativeExecutable, m_constructor) : OBJECT_OFFSETOF(NativeExecutable, m_function);
 
-#if CPU(X86) || CPU(ARM_TRADITIONAL)
     Label nativeCallThunk = align();
-    preserveReturnAddressAfterCall(regT0);
-    emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
 
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
+
+#if CPU(X86)
     // Load caller frame's scope chain into this callframe so that whatever we call can
     // get to its global data.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT1);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
-    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-#if CPU(X86)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    peek(regT1);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC);
 
-    /* We have two structs that we use to describe the stackframe we set up for our
-     * call to native code.  NativeCallFrameStructure describes the how we set up the stack
-     * in advance of the call.  NativeFunctionCalleeSignature describes the callframe
-     * as the native code expects it.  We do this as we are using the fastcall calling
-     * convention which results in the callee popping its arguments off the stack, but
-     * not the rest of the callframe so we need a nice way to ensure we increment the
-     * stack pointer by the right amount after the call.
-     */
-
-#if COMPILER(MSVC) || OS(LINUX)
-#if COMPILER(MSVC)
-#pragma pack(push)
-#pragma pack(4)
-#endif // COMPILER(MSVC)
-    struct NativeCallFrameStructure {
-        //  CallFrame* callFrame; // passed in EDX
-        JSObject* callee;
-        JSValue thisValue;
-        ArgList* argPointer;
-        ArgList args;
-        JSValue result;
-    };
-    struct NativeFunctionCalleeSignature {
-        JSObject* callee;
-        JSValue thisValue;
-        ArgList* argPointer;
-    };
-#if COMPILER(MSVC)
-#pragma pack(pop)
-#endif // COMPILER(MSVC)
-#else
-    struct NativeCallFrameStructure {
-        //  CallFrame* callFrame; // passed in ECX
-        //  JSObject* callee; // passed in EDX
-        JSValue thisValue;
-        ArgList* argPointer;
-        ArgList args;
-    };
-    struct NativeFunctionCalleeSignature {
-        JSValue thisValue;
-        ArgList* argPointer;
-    };
-#endif
+    // Calling convention:      f(ecx, edx, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, X86Registers::ecx);
 
-    const int NativeCallFrameSize = (sizeof(NativeCallFrameStructure) + 15) & ~15;
-    // Allocate system stack frame
-    subPtr(Imm32(NativeCallFrameSize), stackPointerRegister);
+    subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call.
 
-    // Set up arguments
-    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+    // call the function
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT1);
+    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT1);
+    move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    call(Address(regT1, executableOffsetToFunction));
 
-    // push argcount
-    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_argCount)));
+    addPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister);
 
-    // Calculate the start of the callframe header, and store in regT1
-    addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int)sizeof(Register)), callFrameRegister, regT1);
+#elif CPU(ARM)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT0)
-    mul32(Imm32(sizeof(Register)), regT0, regT0);
-    subPtr(regT0, regT1);
-    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_args)));
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
-    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, args)), stackPointerRegister, regT0);
-    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, argPointer)));
+    // Calling convention:      f(r0 == regT0, r1 == regT1, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, ARMRegisters::r0);
 
-    // regT1 currently points to the first argument, regT1 - sizeof(Register) points to 'this'
-    loadPtr(Address(regT1, -(int)sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
-    loadPtr(Address(regT1, -(int)sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT3);
-    storePtr(regT2, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
-    storePtr(regT3, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+    // call the function
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    call(Address(regT2, executableOffsetToFunction));
 
-#if COMPILER(MSVC) || OS(LINUX)
-    // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
-    addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx);
+    restoreReturnAddressBeforeReturn(regT3);
+#elif CPU(SH4)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+
+    // Calling convention: f(r0 == regT4, r1 == regT5, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, regT4);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT5);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(regT5, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+
+    call(Address(regT2, executableOffsetToFunction), regT0);
+    restoreReturnAddressBeforeReturn(regT3);
+#elif CPU(MIPS)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Plant callee
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::eax);
-    storePtr(X86Registers::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    // Plant callframe
-    move(callFrameRegister, X86Registers::edx);
+    // Calling convention:      f(a0, a1, a2, a3);
+    // Host function signature: f(ExecState*);
 
-    call(Address(X86Registers::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
+    // Allocate stack space for 16 bytes (8-byte aligned)
+    // 16 bytes (unused) for 4 arguments
+    subPtr(TrustedImm32(16), stackPointerRegister);
 
-    // JSValue is a non-POD type, so eax points to it
-    emitLoad(0, regT1, regT0, X86Registers::eax);
+    // Setup arg0
+    move(callFrameRegister, MIPSRegisters::a0);
+
+    // Call
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2);
+    loadPtr(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    call(Address(regT2, executableOffsetToFunction));
+
+    // Restore stack space
+    addPtr(TrustedImm32(16), stackPointerRegister);
+
+    restoreReturnAddressBeforeReturn(regT3);
+
+#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
+#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::edx); // callee
-    move(callFrameRegister, X86Registers::ecx); // callFrame
-    call(Address(X86Registers::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
-#endif
+    UNUSED_PARAM(executableOffsetToFunction);
+    breakpoint();
+#endif // CPU(X86)
 
-    // We've put a few temporaries on the stack in addition to the actual arguments
-    // so pull them off now
-    addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
+    // Check for an exception
+    Jump sawException = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
 
-#elif CPU(ARM_TRADITIONAL)
-    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    // Return.
+    ret();
+
+    // Handle an exception
+    sawException.link(this);
+
+    // Grab the return address.
+    preserveReturnAddressAfterCall(regT1);
+
+    move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
+    storePtr(regT1, regT2);
+    poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+
+    // Set the return address.
+    move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
+    restoreReturnAddressBeforeReturn(regT1);
+
+    ret();
 
-    // Allocate stack space for our arglist
-    COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0 && sizeof(JSValue) == 8 && sizeof(Register) == 8, ArgList_should_by_8byte_aligned);
-    subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
+    return nativeCallThunk;
+}
 
-    // Set up arguments
-    subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
+JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executablePool, JSGlobalData* globalData, NativeFunction func)
+{
+    Call nativeCall;
+    Label nativeCallThunk = align();
 
-    // Push argcount
-    storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
+    emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock);
 
-    // Calculate the start of the callframe header, and store in regT1
-    move(callFrameRegister, regT1);
-    sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
+#if CPU(X86)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
-    mul32(Imm32(sizeof(Register)), regT0, regT0);
-    subPtr(regT0, regT1);
+    peek(regT1);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ReturnPC);
 
-    // push pointer to arguments
-    storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
+    // Calling convention:      f(ecx, edx, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, X86Registers::ecx);
 
-    // Argument passing method:
-    // r0 - points to return value
-    // r1 - callFrame
-    // r2 - callee
-    // stack: this(JSValue) and a pointer to ArgList
+    subPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister); // Align stack after call.
 
-#if OS(WINCE)
-    // Setup arg4:
-    push(stackPointerRegister);
+    move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
 
-    // Setup arg3:
-    // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
-    load32(Address(regT1, -(int32_t)sizeof(void*) * 2), ARMRegisters::r3);
-    push(ARMRegisters::r3);
-    load32(Address(regT1, -(int32_t)sizeof(void*)), regT3);
-    storePtr(regT3, Address(stackPointerRegister));
+    // call the function
+    nativeCall = call();
 
-    // Setup arg2:
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2);
+    addPtr(TrustedImm32(16 - sizeof(void*)), stackPointerRegister);
 
-    // Setup arg1:
-    move(callFrameRegister, regT1);
+#elif CPU(ARM)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Setup arg0:
-    move(stackPointerRegister, regT0);
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data)));
+    // Calling convention:      f(r0 == regT0, r1 == regT1, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, ARMRegisters::r0);
 
-    load32(Address(stackPointerRegister, 0), regT0);
-    load32(Address(stackPointerRegister, 4), regT1);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, ARMRegisters::r1);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(ARMRegisters::r1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
 
-    addPtr(Imm32(sizeof(ArgList) + 8), stackPointerRegister);
-#else // OS(WINCE)
-    move(stackPointerRegister, regT3);
-    subPtr(Imm32(8), stackPointerRegister);
-    move(stackPointerRegister, regT0);
-    subPtr(Imm32(8 + 4 + 4 /* padding */), stackPointerRegister);
+    // call the function
+    nativeCall = call();
 
-    // Setup arg4:
-    storePtr(regT3, Address(stackPointerRegister, 8));
+    restoreReturnAddressBeforeReturn(regT3);
 
-    // Setup arg3:
-    // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
-    load32(Address(regT1, -(int32_t)sizeof(void*) * 2), regT3);
-    storePtr(regT3, Address(stackPointerRegister, 0));
-    load32(Address(regT1, -(int32_t)sizeof(void*)), regT3);
-    storePtr(regT3, Address(stackPointerRegister, 4));
+#elif CPU(MIPS)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT0);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT0);
+    emitPutCellToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Setup arg2:
-    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2);
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    // Setup arg1:
-    move(callFrameRegister, regT1);
+    // Calling convention:      f(a0, a1, a2, a3);
+    // Host function signature: f(ExecState*);
 
-    call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data)));
+    // Allocate stack space for 16 bytes (8-byte aligned)
+    // 16 bytes (unused) for 4 arguments
+    subPtr(TrustedImm32(16), stackPointerRegister);
 
-    // Load return value
-    load32(Address(stackPointerRegister, 16), regT0);
-    load32(Address(stackPointerRegister, 20), regT1);
+    // Setup arg0
+    move(callFrameRegister, MIPSRegisters::a0);
 
-    addPtr(Imm32(sizeof(ArgList) + 16 + 8), stackPointerRegister);
-#endif // OS(WINCE)
+    // Call
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2);
+    loadPtr(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+    move(regT0, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    
+    // call the function
+    nativeCall = call();
 
-#endif
+    // Restore stack space
+    addPtr(TrustedImm32(16), stackPointerRegister);
 
-    // Check for an exception
-    move(ImmPtr(&globalData->exception), regT2);
-    Jump sawException = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::EmptyValueTag));
+    restoreReturnAddressBeforeReturn(regT3);
+#elif CPU(SH4)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
 
-    // Grab the return address.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT3);
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
-    // Restore our caller's "r".
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
+    // Calling convention: f(r0 == regT4, r1 == regT5, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, regT4);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT5);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(regT5, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+
+    // call the function
+    nativeCall = call();
 
-    // Return.
     restoreReturnAddressBeforeReturn(regT3);
+#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
+#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
+#else
+    breakpoint();
+#endif // CPU(X86)
+
+    // Check for an exception
+    Jump sawException = branch32(NotEqual, AbsoluteAddress(reinterpret_cast<char*>(&globalData->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
+
+    // Return.
     ret();
 
     // Handle an exception
     sawException.link(this);
+
     // Grab the return address.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
-    move(ImmPtr(&globalData->exceptionLocation), regT2);
+    preserveReturnAddressAfterCall(regT1);
+
+    move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
-    move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
-    restoreReturnAddressBeforeReturn(regT2);
-    ret();
 
-#elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-#error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
-#else
-    UNUSED_PARAM(globalData);
-    breakpoint();
-#endif
+    // Set the return address.
+    move(TrustedImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT1);
+    restoreReturnAddressBeforeReturn(regT1);
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
-    Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
-    Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
-#endif
+    ret();
 
     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
-    LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, executablePool);
 
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
-    patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
-    patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
-#endif
-    patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
-#if ENABLE(JIT_OPTIMIZE_CALL)
-    patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
-    patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
-    patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
-#endif
-
-    CodeRef finalCode = patchBuffer.finalizeCode();
-    *executablePool = finalCode.m_executablePool;
+    patchBuffer.link(nativeCall, FunctionPtr(func));
+    patchBuffer.finalizeCode();
 
-    trampolines->ctiVirtualCall = patchBuffer.trampolineAt(virtualCallBegin);
-#if ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-    trampolines->ctiNativeCallThunk = adoptRef(new NativeExecutable(JITCode(JITCode::HostFunction(patchBuffer.trampolineAt(nativeCallThunk)))));
-#endif
-#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
-    trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
-#else
-    UNUSED_PARAM(ctiStringLengthTrampoline);
-#endif
-#if ENABLE(JIT_OPTIMIZE_CALL)
-    trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
-#else
-    UNUSED_PARAM(ctiVirtualCallLink);
-#endif
-#if ENABLE(JIT_OPTIMIZE_MOD)
-    trampolines->ctiSoftModulo = patchBuffer.trampolineAt(softModBegin);
-#endif
+    return patchBuffer.trampolineAt(nativeCallThunk);
 }
 
 void JIT::emit_op_mov(Instruction* currentInstruction)
@@ -427,14 +484,12 @@ void JIT::emit_op_mov(Instruction* currentInstruction)
     else {
         emitLoad(src, regT1, regT0);
         emitStore(dst, regT1, regT0);
-        map(m_bytecodeIndex + OPCODE_LENGTH(op_mov), dst, regT1, regT0);
+        map(m_bytecodeOffset + OPCODE_LENGTH(op_mov), dst, regT1, regT0);
     }
 }
 
 void JIT::emit_op_end(Instruction* currentInstruction)
 {
-    if (m_codeBlock->needsFullScopeChain())
-        JITStubCall(this, cti_op_end).call();
     ASSERT(returnValueRegister != callFrameRegister);
     emitLoad(currentInstruction[1].u.operand, regT1, regT0);
     restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
@@ -457,21 +512,21 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
 
     if (isOperandConstantImmediateInt(op1)) {
         emitLoad(op2, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target);
         return;
     }
 
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
-        addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
+        addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
         addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
         return;
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     addJump(branch32(LessThanOrEqual, regT0, regT2), target);
 }
 
@@ -497,6 +552,20 @@ void JIT::emit_op_new_object(Instruction* currentInstruction)
     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
 }
 
+void JIT::emit_op_check_has_instance(Instruction* currentInstruction)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    emitLoadPayload(baseVal, regT0);
+
+    // Check that baseVal is a cell.
+    emitJumpSlowCaseIfNotJSCell(baseVal);
+    
+    // Check that baseVal 'ImplementsHasInstance'.
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT0);
+    addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsHasInstance)));
+}
+
 void JIT::emit_op_instanceof(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -510,36 +579,52 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction)
     emitLoadPayload(baseVal, regT0);
     emitLoadPayload(proto, regT1);
 
-    // Check that value, baseVal, and proto are cells.
+    // Check that proto are cells.  baseVal must be a cell - this is checked by op_check_has_instance.
     emitJumpSlowCaseIfNotJSCell(value);
-    emitJumpSlowCaseIfNotJSCell(baseVal);
     emitJumpSlowCaseIfNotJSCell(proto);
+    
+    // Check that prototype is an object
+    loadPtr(Address(regT1, JSCell::structureOffset()), regT3);
+    addSlowCase(branch8(NotEqual, Address(regT3, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
 
+    // Fixme: this check is only needed because the JSC API allows HasInstance to be overridden; we should deprecate this.
     // Check that baseVal 'ImplementsDefaultHasInstance'.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
-    addSlowCase(branchTest8(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT0);
+    addSlowCase(branchTest8(Zero, Address(regT0, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance)));
 
     // Optimistically load the result true, and start looping.
     // Initially, regT1 still contains proto and regT2 still contains value.
     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
-    move(Imm32(JSValue::TrueTag), regT0);
+    move(TrustedImm32(1), regT0);
     Label loop(this);
 
     // Load the prototype of the cell in regT2.  If this is equal to regT1 - WIN!
     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
+    loadPtr(Address(regT2, JSCell::structureOffset()), regT2);
+    load32(Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
     Jump isInstance = branchPtr(Equal, regT2, regT1);
     branchTest32(NonZero, regT2).linkTo(loop, this);
 
     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
-    move(Imm32(JSValue::FalseTag), regT0);
+    move(TrustedImm32(0), regT0);
 
     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
     isInstance.link(this);
     emitStoreBool(dst, regT0);
 }
 
+void JIT::emitSlow_op_check_has_instance(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned baseVal = currentInstruction[1].u.operand;
+
+    linkSlowCaseIfNotJSCell(iter, baseVal);
+    linkSlowCase(iter);
+
+    JITStubCall stubCall(this, cti_op_check_has_instance);
+    stubCall.addArgument(baseVal);
+    stubCall.call();
+}
+
 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
@@ -548,9 +633,9 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     unsigned proto = currentInstruction[4].u.operand;
 
     linkSlowCaseIfNotJSCell(iter, value);
-    linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
+    linkSlowCase(iter);
 
     JITStubCall stubCall(this, cti_op_instanceof);
     stubCall.addArgument(value);
@@ -559,104 +644,118 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas
     stubCall.call(dst);
 }
 
-void JIT::emit_op_new_func(Instruction* currentInstruction)
-{
-    JITStubCall stubCall(this, cti_op_new_func);
-    stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
-    stubCall.call(currentInstruction[1].u.operand);
-}
-
 void JIT::emit_op_get_global_var(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
-    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(currentInstruction[2].u.jsCell);
+    JSGlobalObject* globalObject = m_codeBlock->globalObject();
     ASSERT(globalObject->isGlobalObject());
-    int index = currentInstruction[3].u.operand;
+    int index = currentInstruction[2].u.operand;
 
-    loadPtr(&globalObject->d()->registers, regT2);
+    loadPtr(&globalObject->m_registers, regT2);
 
     emitLoad(index, regT1, regT0, regT2);
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
 }
 
 void JIT::emit_op_put_global_var(Instruction* currentInstruction)
 {
-    JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(currentInstruction[1].u.jsCell);
+    JSGlobalObject* globalObject = m_codeBlock->globalObject();
     ASSERT(globalObject->isGlobalObject());
-    int index = currentInstruction[2].u.operand;
-    int value = currentInstruction[3].u.operand;
+    int index = currentInstruction[1].u.operand;
+    int value = currentInstruction[2].u.operand;
 
     emitLoad(value, regT1, regT0);
 
-    loadPtr(&globalObject->d()->registers, regT2);
+    loadPtr(&globalObject->m_registers, regT2);
     emitStore(index, regT1, regT0, regT2);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
 }
 
 void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
 {
     int dst = currentInstruction[1].u.operand;
     int index = currentInstruction[2].u.operand;
-    int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
+    int skip = currentInstruction[3].u.operand;
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag));
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
 
     loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
 
     emitLoad(index, regT1, regT0, regT2);
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
 }
 
 void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
 {
     int index = currentInstruction[1].u.operand;
-    int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
+    int skip = currentInstruction[2].u.operand;
     int value = currentInstruction[3].u.operand;
 
     emitLoad(value, regT1, regT0);
 
     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
+    bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        Jump activationNotCreated;
+        if (checkTopLevel)
+            activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), TrustedImm32(JSValue::EmptyValueTag));
+        loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
+        activationNotCreated.link(this);
+    }
     while (skip--)
         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
 
     loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2);
+    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
 
     emitStore(index, regT1, regT0, regT2);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
 }
 
 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
 {
+    unsigned activation = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    Jump activationCreated = branch32(NotEqual, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag));
+    Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), TrustedImm32(JSValue::EmptyValueTag));
+    activationCreated.link(this);
     JITStubCall stubCall(this, cti_op_tear_off_activation);
     stubCall.addArgument(currentInstruction[1].u.operand);
+    stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand));
     stubCall.call();
+    argumentsNotCreated.link(this);
 }
 
-void JIT::emit_op_tear_off_arguments(Instruction*)
+void JIT::emit_op_tear_off_arguments(Instruction* currentInstruction)
 {
-    JITStubCall(this, cti_op_tear_off_arguments).call();
-}
+    int dst = currentInstruction[1].u.operand;
 
-void JIT::emit_op_new_array(Instruction* currentInstruction)
-{
-    JITStubCall stubCall(this, cti_op_new_array);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
-    stubCall.call(currentInstruction[1].u.operand);
+    Jump argsNotCreated = branch32(Equal, tagFor(unmodifiedArgumentsRegister(dst)), TrustedImm32(JSValue::EmptyValueTag));
+    JITStubCall stubCall(this, cti_op_tear_off_arguments);
+    stubCall.addArgument(unmodifiedArgumentsRegister(dst));
+    stubCall.call();
+    argsNotCreated.link(this);
 }
 
 void JIT::emit_op_resolve(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -667,13 +766,13 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
-    Jump isImm = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
+    Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
     isImm.link(this);
 
     if (dst != src)
         emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_to_primitive), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_to_primitive), dst, regT1, regT0);
 }
 
 void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -697,16 +796,24 @@ void JIT::emit_op_strcat(Instruction* currentInstruction)
 
 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
 {
-    JITStubCall stubCall(this, cti_op_resolve_base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    JITStubCall stubCall(this, currentInstruction[3].u.operand ? cti_op_resolve_base_strict_put : cti_op_resolve_base);
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.call(currentInstruction[1].u.operand);
+}
+
+void JIT::emit_op_ensure_property_exists(Instruction* currentInstruction)
+{
+    JITStubCall stubCall(this, cti_op_ensure_property_exists);
+    stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_skip);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
-    stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain()));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -715,38 +822,37 @@ void JIT::emit_op_resolve_global(Instruction* currentInstruction, bool dynamic)
     // FIXME: Optimize to use patching instead of so many memory accesses.
 
     unsigned dst = currentInstruction[1].u.operand;
-    void* globalObject = currentInstruction[2].u.jsCell;
+    void* globalObject = m_codeBlock->globalObject();
 
     unsigned currentIndex = m_globalResolveInfoIndex++;
-    void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
-    void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
+    GlobalResolveInfo* resolveInfoAddress = &m_codeBlock->globalResolveInfo(currentIndex);
+
 
     // Verify structure.
-    move(ImmPtr(globalObject), regT0);
-    loadPtr(structureAddress, regT1);
-    addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))));
+    move(TrustedImmPtr(globalObject), regT0);
+    move(TrustedImmPtr(resolveInfoAddress), regT3);
+    loadPtr(Address(regT3, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), regT1);
+    addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, JSCell::structureOffset())));
 
     // Load property.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT2);
-    load32(offsetAddr, regT3);
-    load32(BaseIndex(regT2, regT3, TimesEight), regT0); // payload
-    load32(BaseIndex(regT2, regT3, TimesEight, 4), regT1); // tag
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_propertyStorage)), regT2);
+    load32(Address(regT3, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), regT3);
+    load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
+    load32(BaseIndex(regT2, regT3, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global), dst, regT1, regT0);
+    map(m_bytecodeOffset + (dynamic ? OPCODE_LENGTH(op_resolve_global_dynamic) : OPCODE_LENGTH(op_resolve_global)), dst, regT1, regT0);
 }
 
 void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
 {
     unsigned dst = currentInstruction[1].u.operand;
-    void* globalObject = currentInstruction[2].u.jsCell;
-    Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
+    Identifier* ident = &m_codeBlock->identifier(currentInstruction[2].u.operand);
 
     unsigned currentIndex = m_globalResolveInfoIndex++;
 
     linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_resolve_global);
-    stubCall.addArgument(ImmPtr(globalObject));
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(Imm32(currentIndex));
     stubCall.call(dst);
 }
@@ -758,9 +864,9 @@ void JIT::emit_op_not(Instruction* currentInstruction)
 
     emitLoadTag(src, regT0);
 
-    xor32(Imm32(JSValue::FalseTag), regT0);
-    addSlowCase(branchTest32(NonZero, regT0, Imm32(~1)));
-    xor32(Imm32(JSValue::TrueTag), regT0);
+    emitLoad(src, regT1, regT0);
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::BooleanTag)));
+    xor32(TrustedImm32(1), regT0);
 
     emitStoreBool(dst, regT0, (dst == src));
 }
@@ -784,25 +890,9 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction)
 
     emitLoad(cond, regT1, regT0);
 
-    Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag));
-    addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target);
-
-    Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
-    Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0));
-    addJump(jump(), target);
-
-    if (supportsFloatingPoint()) {
-        isNotInteger.link(this);
-
-        addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
-
-        emitLoadDouble(cond, fpRegT0);
-        addJump(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target);
-    } else
-        addSlowCase(isNotInteger);
-
-    isTrue.link(this);
-    isTrue2.link(this);
+    ASSERT((JSValue::BooleanTag + 1 == JSValue::Int32Tag) && !(JSValue::Int32Tag + 1));
+    addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::BooleanTag)));
+    addJump(branchTest32(Zero, regT0), target);
 }
 
 void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -811,6 +901,18 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt
     unsigned target = currentInstruction[2].u.operand;
 
     linkSlowCase(iter);
+
+    if (supportsFloatingPoint()) {
+        // regT1 contains the tag from the hot path.
+        Jump notNumber = branch32(Above, regT1, Imm32(JSValue::LowestTag));
+
+        emitLoadDouble(cond, fpRegT0);
+        emitJumpSlowToHot(branchDoubleZeroOrNaN(fpRegT0, fpRegT1), target);
+        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jfalse));
+
+        notNumber.link(this);
+    }
+
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(cond);
     stubCall.call();
@@ -824,25 +926,9 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction)
 
     emitLoad(cond, regT1, regT0);
 
-    Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag));
-    addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target);
-
-    Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
-    Jump isFalse2 = branch32(Equal, regT0, Imm32(0));
-    addJump(jump(), target);
-
-    if (supportsFloatingPoint()) {
-        isNotInteger.link(this);
-
-        addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
-
-        emitLoadDouble(cond, fpRegT0);
-        addJump(branchDoubleNonZero(fpRegT0, fpRegT1), target);
-    } else
-        addSlowCase(isNotInteger);
-
-    isFalse.link(this);
-    isFalse2.link(this);
+    ASSERT((JSValue::BooleanTag + 1 == JSValue::Int32Tag) && !(JSValue::Int32Tag + 1));
+    addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::BooleanTag)));
+    addJump(branchTest32(NonZero, regT0), target);
 }
 
 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -851,6 +937,18 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr
     unsigned target = currentInstruction[2].u.operand;
 
     linkSlowCase(iter);
+
+    if (supportsFloatingPoint()) {
+        // regT1 contains the tag from the hot path.
+        Jump notNumber = branch32(Above, regT1, Imm32(JSValue::LowestTag));
+
+        emitLoadDouble(cond, fpRegT0);
+        emitJumpSlowToHot(branchDoubleNonZero(fpRegT0, fpRegT1), target);
+        emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jtrue));
+
+        notNumber.link(this);
+    }
+
     JITStubCall stubCall(this, cti_op_jtrue);
     stubCall.addArgument(cond);
     stubCall.call();
@@ -864,22 +962,20 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
-    Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+    Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    addJump(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target);
 
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
 
-    set32(Equal, regT1, Imm32(JSValue::NullTag), regT2);
-    set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
-    or32(regT2, regT1);
-
-    addJump(branchTest32(NonZero, regT1), target);
+    ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1));
+    or32(TrustedImm32(1), regT1);
+    addJump(branch32(Equal, regT1, TrustedImm32(JSValue::NullTag)), target);
 
     wasNotImmediate.link(this);
 }
@@ -891,22 +987,20 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
-    Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+    Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
 
     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addJump(branchTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    addJump(branchTest8(Zero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target);
 
     Jump wasNotImmediate = jump();
 
     // Now handle the immediate cases - undefined & null
     isImmediate.link(this);
 
-    set32(Equal, regT1, Imm32(JSValue::NullTag), regT2);
-    set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
-    or32(regT2, regT1);
-
-    addJump(branchTest32(Zero, regT1), target);
+    ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1));
+    or32(TrustedImm32(1), regT1);
+    addJump(branch32(NotEqual, regT1, TrustedImm32(JSValue::NullTag)), target);
 
     wasNotImmediate.link(this);
 }
@@ -914,19 +1008,19 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
 {
     unsigned src = currentInstruction[1].u.operand;
-    JSCell* ptr = currentInstruction[2].u.jsCell;
+    JSCell* ptr = currentInstruction[2].u.jsCell.get();
     unsigned target = currentInstruction[3].u.operand;
 
     emitLoad(src, regT1, regT0);
-    addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target);
-    addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target);
+    addJump(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)), target);
+    addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target);
 }
 
 void JIT::emit_op_jsr(Instruction* currentInstruction)
 {
     int retAddrDst = currentInstruction[1].u.operand;
     int target = currentInstruction[2].u.operand;
-    DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
+    DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
     addJump(jump(), target);
     m_jsrSites.append(JSRInfo(storeLocation, label()));
 }
@@ -944,11 +1038,10 @@ void JIT::emit_op_eq(Instruction* currentInstruction)
 
     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
     addSlowCase(branch32(NotEqual, regT1, regT3));
-    addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag)));
-    addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag)));
+    addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::CellTag)));
+    addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag)));
 
-    set8(Equal, regT0, regT2, regT0);
-    or32(Imm32(JSValue::FalseTag), regT0);
+    compare32(Equal, regT0, regT2, regT0);
 
     emitStoreBool(dst, regT0);
 }
@@ -965,8 +1058,8 @@ void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>:
     genericCase.append(getSlowCase(iter)); // tags not equal
 
     linkSlowCase(iter); // tags equal and JSCell
-    genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
-    genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr)));
+    genericCase.append(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+    genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
 
     // String case.
     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
@@ -984,7 +1077,6 @@ void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>:
     stubCallEq.call(regT0);
 
     storeResult.link(this);
-    or32(Imm32(JSValue::FalseTag), regT0);
     emitStoreBool(dst, regT0);
 }
 
@@ -996,11 +1088,10 @@ void JIT::emit_op_neq(Instruction* currentInstruction)
 
     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
     addSlowCase(branch32(NotEqual, regT1, regT3));
-    addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag)));
-    addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag)));
+    addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::CellTag)));
+    addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag)));
 
-    set8(NotEqual, regT0, regT2, regT0);
-    or32(Imm32(JSValue::FalseTag), regT0);
+    compare32(NotEqual, regT0, regT2, regT0);
 
     emitStoreBool(dst, regT0);
 }
@@ -1015,8 +1106,8 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>
     genericCase.append(getSlowCase(iter)); // tags not equal
 
     linkSlowCase(iter); // tags equal and JSCell
-    genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
-    genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr)));
+    genericCase.append(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr)));
+    genericCase.append(branchPtr(NotEqual, Address(regT2), TrustedImmPtr(m_globalData->jsStringVPtr)));
 
     // String case.
     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
@@ -1034,8 +1125,7 @@ void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>
     stubCallEq.call(regT0);
 
     storeResult.link(this);
-    xor32(Imm32(0x1), regT0);
-    or32(Imm32(JSValue::FalseTag), regT0);
+    xor32(TrustedImm32(0x1), regT0);
     emitStoreBool(dst, regT0);
 }
 
@@ -1052,15 +1142,13 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy
     // cells and/or Int32s.
     move(regT0, regT2);
     and32(regT1, regT2);
-    addSlowCase(branch32(Below, regT2, Imm32(JSValue::LowestTag)));
-    addSlowCase(branch32(AboveOrEqual, regT2, Imm32(JSValue::CellTag)));
+    addSlowCase(branch32(Below, regT2, TrustedImm32(JSValue::LowestTag)));
+    addSlowCase(branch32(AboveOrEqual, regT2, TrustedImm32(JSValue::CellTag)));
 
     if (type == OpStrictEq)
-        set8(Equal, regT0, regT1, regT0);
+        compare32(Equal, regT0, regT1, regT0);
     else
-        set8(NotEqual, regT0, regT1, regT0);
-
-    or32(Imm32(JSValue::FalseTag), regT0);
+        compare32(NotEqual, regT0, regT1, regT0);
 
     emitStoreBool(dst, regT0);
 }
@@ -1111,23 +1199,21 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction)
     unsigned src = currentInstruction[2].u.operand;
 
     emitLoad(src, regT1, regT0);
-    Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+    Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
-    setTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT1);
 
     Jump wasNotImmediate = jump();
 
     isImmediate.link(this);
 
-    set8(Equal, regT1, Imm32(JSValue::NullTag), regT2);
-    set8(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
+    compare32(Equal, regT1, TrustedImm32(JSValue::NullTag), regT2);
+    compare32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag), regT1);
     or32(regT2, regT1);
 
     wasNotImmediate.link(this);
 
-    or32(Imm32(JSValue::FalseTag), regT1);
-
     emitStoreBool(dst, regT1);
 }
 
@@ -1137,30 +1223,28 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction)
     unsigned src = currentInstruction[2].u.operand;
 
     emitLoad(src, regT1, regT0);
-    Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
+    Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
-    setTest8(Zero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
+    test8(Zero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT1);
 
     Jump wasNotImmediate = jump();
 
     isImmediate.link(this);
 
-    set8(NotEqual, regT1, Imm32(JSValue::NullTag), regT2);
-    set8(NotEqual, regT1, Imm32(JSValue::UndefinedTag), regT1);
+    compare32(NotEqual, regT1, TrustedImm32(JSValue::NullTag), regT2);
+    compare32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag), regT1);
     and32(regT2, regT1);
 
     wasNotImmediate.link(this);
 
-    or32(Imm32(JSValue::FalseTag), regT1);
-
     emitStoreBool(dst, regT1);
 }
 
 void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_resolve_with_base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
     stubCall.call(currentInstruction[2].u.operand);
 }
@@ -1168,7 +1252,7 @@ void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_func_exp);
-    stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -1198,10 +1282,10 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
 
     emitLoad(base, regT1, regT0);
     if (!m_codeBlock->isKnownNotImmediate(base))
-        isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
-    if (base != m_codeBlock->thisRegister()) {
-        loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-        isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
+        isNotObject.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    if (base != m_codeBlock->thisRegister() || m_codeBlock->isStrictMode()) {
+        loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+        isNotObject.append(branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)));
     }
 
     // We could inline the case where you have a valid cache, but
@@ -1211,13 +1295,15 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction)
     getPnamesStubCall.addArgument(regT0);
     getPnamesStubCall.call(dst);
     load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
-    store32(Imm32(0), addressFor(i));
-    store32(regT3, addressFor(size));
+    store32(TrustedImm32(Int32Tag), intTagFor(i));
+    store32(TrustedImm32(0), intPayloadFor(i));
+    store32(TrustedImm32(Int32Tag), intTagFor(size));
+    store32(regT3, payloadFor(size));
     Jump end = jump();
 
     isNotObject.link(this);
-    addJump(branch32(Equal, regT1, Imm32(JSValue::NullTag)), breakTarget);
-    addJump(branch32(Equal, regT1, Imm32(JSValue::UndefinedTag)), breakTarget);
+    addJump(branch32(Equal, regT1, TrustedImm32(JSValue::NullTag)), breakTarget);
+    addJump(branch32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag)), breakTarget);
     JITStubCall toObjectStubCall(this, cti_to_object);
     toObjectStubCall.addArgument(regT1, regT0);
     toObjectStubCall.call(base);
@@ -1238,25 +1324,25 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction)
     JumpList callHasProperty;
 
     Label begin(this);
-    load32(addressFor(i), regT0);
-    Jump end = branch32(Equal, regT0, addressFor(size));
+    load32(intPayloadFor(i), regT0);
+    Jump end = branch32(Equal, regT0, intPayloadFor(size));
 
     // Grab key @ i
-    loadPtr(addressFor(it), regT1);
+    loadPtr(payloadFor(it), regT1);
     loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
     load32(BaseIndex(regT2, regT0, TimesEight), regT2);
-    store32(Imm32(JSValue::CellTag), tagFor(dst));
+    store32(TrustedImm32(JSValue::CellTag), tagFor(dst));
     store32(regT2, payloadFor(dst));
 
     // Increment i
-    add32(Imm32(1), regT0);
-    store32(regT0, addressFor(i));
+    add32(TrustedImm32(1), regT0);
+    store32(regT0, intPayloadFor(i));
 
     // Verify that i is valid:
-    loadPtr(addressFor(base), regT0);
+    loadPtr(payloadFor(base), regT0);
 
     // Test base's structure
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
     callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
 
     // Test base's prototype chain
@@ -1265,11 +1351,11 @@ void JIT::emit_op_next_pname(Instruction* currentInstruction)
     addJump(branchTestPtr(Zero, Address(regT3)), target);
 
     Label checkPrototype(this);
-    callHasProperty.append(branch32(Equal, Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::NullTag)));
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    callHasProperty.append(branch32(Equal, Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::NullTag)));
+    loadPtr(Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
+    loadPtr(Address(regT2, JSCell::structureOffset()), regT2);
     callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
-    addPtr(Imm32(sizeof(Structure*)), regT3);
+    addPtr(TrustedImm32(sizeof(Structure*)), regT3);
     branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
 
     // Continue loop.
@@ -1310,13 +1396,13 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
-    Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag));
-    addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::EmptyValueTag)));
+    Jump isInt32 = branch32(Equal, regT1, TrustedImm32(JSValue::Int32Tag));
+    addSlowCase(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::EmptyValueTag)));
     isInt32.link(this);
 
     if (src != dst)
         emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_to_jsnumber), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_to_jsnumber), dst, regT1, regT0);
 }
 
 void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1333,24 +1419,26 @@ void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCa
 void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_push_new_scope);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(currentInstruction[3].u.operand);
     stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_catch(Instruction* currentInstruction)
 {
-    unsigned exception = currentInstruction[1].u.operand;
-
-    // This opcode only executes after a return from cti_op_throw.
-
-    // cti_op_throw may have taken us to a call frame further up the stack; reload
-    // the call frame pointer to adjust.
-    peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+    // cti_op_throw returns the callFrame for the handler.
+    move(regT0, callFrameRegister);
 
     // Now store the exception returned by cti_op_throw.
+    loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(struct JITStackFrame, globalData)), regT3);
+    load32(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    load32(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    store32(TrustedImm32(JSValue().payload()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+    store32(TrustedImm32(JSValue().tag()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+
+    unsigned exception = currentInstruction[1].u.operand;
     emitStore(exception, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_catch), exception, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_catch), exception, regT1, regT0);
 }
 
 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
@@ -1369,7 +1457,7 @@ void JIT::emit_op_switch_imm(Instruction* currentInstruction)
 
     // create jump table for switch destinations, track this switch statement.
     SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
-    m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate));
+    m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Immediate));
     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
 
     JITStubCall stubCall(this, cti_op_switch_imm);
@@ -1387,7 +1475,7 @@ void JIT::emit_op_switch_char(Instruction* currentInstruction)
 
     // create jump table for switch destinations, track this switch statement.
     SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
-    m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character));
+    m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Character));
     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
 
     JITStubCall stubCall(this, cti_op_switch_char);
@@ -1405,7 +1493,7 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
 
     // create jump table for switch destinations, track this switch statement.
     StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
-    m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset));
+    m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset));
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee);
@@ -1414,17 +1502,13 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
     jump(regT0);
 }
 
-void JIT::emit_op_new_error(Instruction* currentInstruction)
+void JIT::emit_op_throw_reference_error(Instruction* currentInstruction)
 {
-    unsigned dst = currentInstruction[1].u.operand;
-    unsigned type = currentInstruction[2].u.operand;
-    unsigned message = currentInstruction[3].u.operand;
+    unsigned message = currentInstruction[1].u.operand;
 
-    JITStubCall stubCall(this, cti_op_new_error);
-    stubCall.addArgument(Imm32(type));
+    JITStubCall stubCall(this, cti_op_throw_reference_error);
     stubCall.addArgument(m_codeBlock->getConstant(message));
-    stubCall.addArgument(Imm32(m_bytecodeIndex));
-    stubCall.call(dst);
+    stubCall.call();
 }
 
 void JIT::emit_op_debug(Instruction* currentInstruction)
@@ -1451,29 +1535,53 @@ void JIT::emit_op_enter(Instruction*)
         emitStore(i, jsUndefined());
 }
 
-void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
+void JIT::emit_op_create_activation(Instruction* currentInstruction)
 {
-    emit_op_enter(currentInstruction);
-
-    JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
+    unsigned activation = currentInstruction[1].u.operand;
+    
+    Jump activationCreated = branch32(NotEqual, tagFor(activation), TrustedImm32(JSValue::EmptyValueTag));
+    JITStubCall(this, cti_op_push_activation).call(activation);
+    activationCreated.link(this);
 }
 
-void JIT::emit_op_create_arguments(Instruction*)
+void JIT::emit_op_create_arguments(Instruction* currentInstruction)
 {
-    Jump argsCreated = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::EmptyValueTag));
+    unsigned dst = currentInstruction[1].u.operand;
+
+    Jump argsCreated = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
 
-    // If we get here the arguments pointer is a null cell - i.e. arguments need lazy creation.
     if (m_codeBlock->m_numParameters == 1)
         JITStubCall(this, cti_op_create_arguments_no_params).call();
     else
         JITStubCall(this, cti_op_create_arguments).call();
 
+    emitStore(dst, regT1, regT0);
+    emitStore(unmodifiedArgumentsRegister(dst), regT1, regT0);
+
     argsCreated.link(this);
 }
 
-void JIT::emit_op_init_arguments(Instruction*)
+void JIT::emit_op_init_lazy_reg(Instruction* currentInstruction)
 {
-    emitStore(RegisterFile::ArgumentsRegister, JSValue(), callFrameRegister);
+    unsigned dst = currentInstruction[1].u.operand;
+
+    emitStore(dst, JSValue());
+}
+
+void JIT::emit_op_get_callee(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT0);
+    emitStoreCell(dst, regT0);
+}
+
+void JIT::emit_op_create_this(Instruction* currentInstruction)
+{
+    unsigned protoRegister = currentInstruction[2].u.operand;
+    emitLoad(protoRegister, regT1, regT0);
+    JITStubCall stubCall(this, cti_op_create_this);
+    stubCall.addArgument(regT1, regT0);
+    stubCall.call(currentInstruction[1].u.operand);
 }
 
 void JIT::emit_op_convert_this(Instruction* currentInstruction)
@@ -1482,12 +1590,32 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction)
 
     emitLoad(thisRegister, regT1, regT0);
 
-    addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
-    addSlowCase(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
+}
 
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
+void JIT::emit_op_convert_this_strict(Instruction* currentInstruction)
+{
+    unsigned thisRegister = currentInstruction[1].u.operand;
+    
+    emitLoad(thisRegister, regT1, regT0);
+    
+    Jump notNull = branch32(NotEqual, regT1, TrustedImm32(JSValue::EmptyValueTag));
+    emitStore(thisRegister, jsNull());
+    Jump setThis = jump();
+    notNull.link(this);
+    Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+    Jump notAnObject = branch8(NotEqual, Address(regT2, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType));
+    addSlowCase(branchTest8(NonZero, Address(regT2, Structure::typeInfoFlagsOffset()), TrustedImm32(NeedsThisConversion)));
+    isImmediate.link(this);
+    notAnObject.link(this);
+    setThis.link(this);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_convert_this_strict), thisRegister, regT1, regT0);
 }
 
 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1502,6 +1630,17 @@ void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowC
     stubCall.call(thisRegister);
 }
 
+void JIT::emitSlow_op_convert_this_strict(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned thisRegister = currentInstruction[1].u.operand;
+    
+    linkSlowCase(iter);
+    
+    JITStubCall stubCall(this, cti_op_convert_this_strict);
+    stubCall.addArgument(regT1, regT0);
+    stubCall.call(thisRegister);
+}
+
 void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
 {
     peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
@@ -1524,6 +1663,180 @@ void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
     noProfiler.link(this);
 }
 
+void JIT::emit_op_get_arguments_length(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag)));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
+    sub32(TrustedImm32(1), regT0);
+    emitStoreInt32(dst, regT0);
 }
 
-#endif // ENABLE(JIT) && USE(JSVALUE32_64)
+void JIT::emitSlow_op_get_arguments_length(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    linkSlowCase(iter);
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int ident = currentInstruction[3].u.operand;
+    
+    JITStubCall stubCall(this, cti_op_get_by_id_generic);
+    stubCall.addArgument(base);
+    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
+    stubCall.call(dst);
+}
+
+void JIT::emit_op_get_argument_by_val(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int argumentsRegister = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    addSlowCase(branch32(NotEqual, tagFor(argumentsRegister), TrustedImm32(JSValue::EmptyValueTag)));
+    emitLoad(property, regT1, regT2);
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    add32(TrustedImm32(1), regT2);
+    // regT2 now contains the integer index of the argument we want, including this
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT3);
+    addSlowCase(branch32(AboveOrEqual, regT2, regT3));
+    
+    Jump skipOutofLineParams;
+    int numArgs = m_codeBlock->m_numParameters;
+    if (numArgs) {
+        Jump notInInPlaceArgs = branch32(AboveOrEqual, regT2, Imm32(numArgs));
+        addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1);
+        loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+        loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+        skipOutofLineParams = jump();
+        notInInPlaceArgs.link(this);
+    }
+
+    addPtr(Imm32(static_cast<unsigned>(-(RegisterFile::CallFrameHeaderSize + numArgs) * sizeof(Register))), callFrameRegister, regT1);
+    mul32(TrustedImm32(sizeof(Register)), regT3, regT3);
+    subPtr(regT3, regT1);
+    loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    loadPtr(BaseIndex(regT1, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    if (numArgs)
+        skipOutofLineParams.link(this);
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned arguments = currentInstruction[2].u.operand;
+    unsigned property = currentInstruction[3].u.operand;
+
+    linkSlowCase(iter);
+    Jump skipArgumentsCreation = jump();
+
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    if (m_codeBlock->m_numParameters == 1)
+        JITStubCall(this, cti_op_create_arguments_no_params).call();
+    else
+        JITStubCall(this, cti_op_create_arguments).call();
+    
+    emitStore(arguments, regT1, regT0);
+    emitStore(unmodifiedArgumentsRegister(arguments), regT1, regT0);
+    
+    skipArgumentsCreation.link(this);
+    JITStubCall stubCall(this, cti_op_get_by_val);
+    stubCall.addArgument(arguments);
+    stubCall.addArgument(property);
+    stubCall.call(dst);
+}
+
+#if ENABLE(JIT_USE_SOFT_MODULO)
+void JIT::softModulo()
+{
+    push(regT1);
+    push(regT3);
+    move(regT2, regT3);
+    move(regT0, regT2);
+    move(TrustedImm32(0), regT1);
+
+    // Check for negative result reminder
+    Jump positiveRegT3 = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0));
+    neg32(regT3);
+    xor32(TrustedImm32(1), regT1);
+    positiveRegT3.link(this);
+
+    Jump positiveRegT2 = branch32(GreaterThanOrEqual, regT2, TrustedImm32(0));
+    neg32(regT2);
+    xor32(TrustedImm32(2), regT1);
+    positiveRegT2.link(this);
+
+    // Save the condition for negative reminder
+    push(regT1);
+
+    Jump exitBranch = branch32(LessThan, regT2, regT3);
+
+    // Power of two fast case
+    move(regT3, regT0);
+    sub32(TrustedImm32(1), regT0);
+    Jump powerOfTwo = branchTest32(NonZero, regT0, regT3);
+    and32(regT0, regT2);
+    powerOfTwo.link(this);
+
+    and32(regT3, regT0);
+
+    Jump exitBranch2 = branchTest32(Zero, regT0);
+
+    countLeadingZeros32(regT2, regT0);
+    countLeadingZeros32(regT3, regT1);
+    sub32(regT0, regT1);
+
+    Jump useFullTable = branch32(Equal, regT1, TrustedImm32(31));
+
+    neg32(regT1);
+    add32(TrustedImm32(31), regT1);
+
+    int elementSizeByShift = -1;
+#if CPU(ARM)
+    elementSizeByShift = 3;
+#else
+#error "JIT_OPTIMIZE_MOD not yet supported on this platform."
+#endif
+    relativeTableJump(regT1, elementSizeByShift);
+
+    useFullTable.link(this);
+    // Modulo table
+    for (int i = 31; i > 0; --i) {
+#if CPU(ARM_TRADITIONAL)
+        m_assembler.cmp_r(regT2, m_assembler.lsl(regT3, i));
+        m_assembler.sub_r(regT2, regT2, m_assembler.lsl(regT3, i), ARMAssembler::CS);
+#elif CPU(ARM_THUMB2)
+        ShiftTypeAndAmount shift(SRType_LSL, i);
+        m_assembler.sub_S(regT1, regT2, regT3, shift);
+        m_assembler.it(ARMv7Assembler::ConditionCS);
+        m_assembler.mov(regT2, regT1);
+#else
+#error "JIT_OPTIMIZE_MOD not yet supported on this platform."
+#endif
+    }
+
+    Jump lower = branch32(Below, regT2, regT3);
+    sub32(regT3, regT2);
+    lower.link(this);
+
+    exitBranch.link(this);
+    exitBranch2.link(this);
+
+    // Check for negative reminder
+    pop(regT1);
+    Jump positiveResult = branch32(Equal, regT1, TrustedImm32(0));
+    neg32(regT2);
+    positiveResult.link(this);
+
+    move(regT2, regT0);
+
+    pop(regT3);
+    pop(regT1);
+    ret();
+}
+#endif // ENABLE(JIT_USE_SOFT_MODULO)
+
+} // namespace JSC
+
+#endif // USE(JSVALUE32_64)
+#endif // ENABLE(JIT)
index 1b2b4dd005927a0a63c8eca5dc4e222a26e8ac8b..ce3d3c1f385504a83359a1aeecee9f665a430256 100644 (file)
 
 #include "config.h"
 
-#if !USE(JSVALUE32_64)
-
-#include "JIT.h"
-
 #if ENABLE(JIT)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "GetterSetter.h"
 using namespace std;
 
 namespace JSC {
+#if USE(JSVALUE64)
 
-PassRefPtr<NativeExecutable> JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
     JSInterfaceJIT jit;
     JumpList failures;
-    failures.append(jit.branchPtr(NotEqual, Address(regT0), ImmPtr(globalData->jsStringVPtr)));
+    failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr)));
     failures.append(jit.branchTest32(NonZero, Address(regT0, OBJECT_OFFSETOF(JSString, m_fiberCount))));
-#if USE(JSVALUE64)
-    jit.zeroExtend32ToPtr(regT1, regT1);
-#else
-    jit.emitFastArithImmToInt(regT1);
-#endif
 
-    // Load string length to regT1, and start the process of loading the data pointer into regT0
+    // Load string length to regT2, and start the process of loading the data pointer into regT0
     jit.load32(Address(regT0, ThunkHelpers::jsStringLengthOffset()), regT2);
     jit.loadPtr(Address(regT0, ThunkHelpers::jsStringValueOffset()), regT0);
     jit.loadPtr(Address(regT0, ThunkHelpers::stringImplDataOffset()), regT0);
@@ -75,17 +68,17 @@ PassRefPtr<NativeExecutable> JIT::stringGetByValStubGenerator(JSGlobalData* glob
     // Load the character
     jit.load16(BaseIndex(regT0, regT1, TimesTwo, 0), regT0);
     
-    failures.append(jit.branch32(AboveOrEqual, regT0, Imm32(0x100)));
-    jit.move(ImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
+    failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
+    jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
     jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
     jit.ret();
     
     failures.link(&jit);
-    jit.move(Imm32(0), regT0);
+    jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
-    LinkBuffer patchBuffer(&jit, pool, 0);
-    return adoptRef(new NativeExecutable(patchBuffer.finalizeCode()));
+    LinkBuffer patchBuffer(*globalData, &jit, pool);
+    return patchBuffer.finalizeCode().m_code;
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -96,7 +89,7 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
 
     emitGetVirtualRegisters(base, regT0, property, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
+
     // This is technically incorrect - we're zero-extending an int32.  On the hot path this doesn't matter.
     // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
     // number was signed since m_vectorLength is always less than intmax (since the total allocation
@@ -104,14 +97,12 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     // to 64-bits is necessary since it's used in the address calculation.  We zero extend rather than sign
     // extending since it makes it easier to re-tag the value in the slow case.
     zeroExtend32ToPtr(regT1, regT1);
-#else
-    emitFastArithImmToInt(regT1);
-#endif
+
     emitJumpSlowCaseIfNotJSCell(regT0, base);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
 
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
-    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
+    loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
+    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
 
     loadPtr(BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0);
     addSlowCase(branchTestPtr(Zero, regT0));
@@ -129,8 +120,8 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     linkSlowCaseIfNotJSCell(iter, base); // base cell check
     Jump nonCell = jump();
     linkSlowCase(iter); // base array check
-    Jump notString = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
-    emitNakedCall(m_globalData->getThunk(stringGetByValStubGenerator)->generatedJITCode().addressForCall());
+    Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+    emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator));
     Jump failed = branchTestPtr(Zero, regT0);
     emitPutVirtualRegister(dst, regT0);
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
@@ -147,18 +138,10 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
     stubCall.call(dst);
 }
 
-void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch)
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch)
 {
-    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
-    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
-
-    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
-    loadPtr(BaseIndex(base, offset, ScalePtr, OBJECT_OFFSETOF(JSObject, m_inlineStorage)), result);
-    Jump finishedLoad = jump();
-    notUsingInlineStorage.link(this);
-    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), scratch);
+    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), scratch);
     loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
-    finishedLoad.link(this);
 }
 
 void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
@@ -176,12 +159,12 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
     emitJumpSlowCaseIfNotJSCell(regT0, base);
 
     // Test base's structure
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
+    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
     addSlowCase(branchPtr(NotEqual, regT2, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
     load32(addressFor(i), regT3);
-    sub32(Imm32(1), regT3);
+    sub32(TrustedImm32(1), regT3);
     addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
-    compileGetDirectOffset(regT0, regT0, regT2, regT3, regT1);
+    compileGetDirectOffset(regT0, regT0, regT3, regT1);
 
     emitPutVirtualRegister(dst, regT0);
 }
@@ -211,18 +194,13 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 
     emitGetVirtualRegisters(base, regT0, property, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
     // See comment in op_get_by_val.
     zeroExtend32ToPtr(regT1, regT1);
-#else
-    emitFastArithImmToInt(regT1);
-#endif
     emitJumpSlowCaseIfNotJSCell(regT0, base);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
-    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
-
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
 
+    loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
     Jump empty = branchTestPtr(Zero, BaseIndex(regT2, regT1, ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
     Label storeResult(this);
@@ -231,11 +209,11 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
     Jump end = jump();
     
     empty.link(this);
-    add32(Imm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+    add32(TrustedImm32(1), Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     branch32(Below, regT1, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
 
     move(regT1, regT0);
-    add32(Imm32(1), regT0);
+    add32(TrustedImm32(1), regT0);
     store32(regT0, Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)));
     jump().linkTo(storeResult, this);
 
@@ -246,7 +224,7 @@ void JIT::emit_op_put_by_index(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_put_by_index);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
-    stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
+    stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand));
     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
     stubCall.call();
 }
@@ -255,7 +233,7 @@ void JIT::emit_op_put_getter(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_put_getter);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
     stubCall.call();
 }
@@ -264,7 +242,7 @@ void JIT::emit_op_put_setter(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_put_setter);
     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
     stubCall.call();
 }
@@ -273,7 +251,7 @@ void JIT::emit_op_del_by_id(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_del_by_id);
     stubCall.addArgument(currentInstruction[2].u.operand, regT2);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -298,7 +276,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     emitGetVirtualRegister(baseVReg, regT0);
     JITStubCall stubCall(this, cti_op_get_by_id_generic);
     stubCall.addArgument(regT0);
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.call(resultVReg);
 
     m_propertyAccessInstructionIndex++;
@@ -320,7 +298,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 
     JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct_generic, cti_op_put_by_id_generic);
     stubCall.addArgument(regT0);
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(regT1);
     stubCall.call();
 
@@ -358,20 +336,20 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
 
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
 
-    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
-    DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT1);
-    Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), info.structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(TrustedImmPtr(0), regT1);
+    Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT1, JSCell::structureOffset()), protoStructureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
 
     // This will be relinked to load the function without doing a load.
-    DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
+    DataLabelPtr putFunction = moveWithPatch(TrustedImmPtr(0), regT0);
 
     END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
 
     Jump match = jump();
 
-    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj);
+    ASSERT_JIT_OFFSET_UNUSED(protoObj, differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj);
     ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct);
-    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction);
+    ASSERT_JIT_OFFSET_UNUSED(putFunction, differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction);
 
     // Link the failure cases here.
     notCell.link(this);
@@ -386,7 +364,7 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     emitPutVirtualRegister(resultVReg);
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
-    m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+    m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
 void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -399,7 +377,7 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
     compileGetByIdSlowCase(resultVReg, baseVReg, ident, iter, true);
 
     // We've already generated the following get_by_id, so make sure it's skipped over.
-    m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+    m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
 #else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
@@ -436,18 +414,14 @@ void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propert
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     DataLabelPtr structureToCompare;
-    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     addSlowCase(structureCheck);
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase)
 
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
-    Label externalLoadComplete(this);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetGetByIdExternalLoad);
-    ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthGetByIdExternalLoad);
-
-    DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
+    DataLabelCompact displacementLabel = loadPtrWithCompactAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);
+    ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset);
 
     Label putResult(this);
 
@@ -483,7 +457,7 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident
 #endif
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT0);
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     Call call = stubCall.call(resultVReg);
 
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
@@ -518,20 +492,15 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
 
     // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
     DataLabelPtr structureToCompare;
-    addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
+    addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
     ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
 
-    // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
-    Label externalLoadComplete(this);
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetPutByIdExternalLoad);
-    ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthPutByIdExternalLoad);
-
-    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
+    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchPutByIdDefaultOffset));
 
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
 
-    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset);
+    ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset);
 }
 
 void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -547,7 +516,7 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
 
     JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
     stubCall.addArgument(regT0);
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     stubCall.addArgument(regT1);
     Call call = stubCall.call();
 
@@ -561,9 +530,9 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* s
 {
     int offset = cachedOffset * sizeof(JSValue);
     if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
+        offset += JSObject::offsetOfInlineStorage();
     else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     storePtr(value, Address(base, offset));
 }
 
@@ -571,32 +540,18 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID value, Structure* s
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset)
 {
     int offset = cachedOffset * sizeof(JSValue);
-    if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
-    else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
-    loadPtr(Address(base, offset), result);
-}
-
-void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset)
-{
-    if (base->isUsingInlineStorage())
-        loadPtr(static_cast<void*>(&base->m_inlineStorage[cachedOffset]), result);
-    else {
-        PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
-        loadPtr(static_cast<void*>(protoPropertyStorage), temp);
-        loadPtr(Address(temp, cachedOffset * sizeof(JSValue)), result);
-    } 
+    if (structure->isUsingInlineStorage()) {
+        offset += JSObject::offsetOfInlineStorage();
+        loadPtr(Address(base, offset), result);
+    } else {
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), result);
+        loadPtr(Address(result, offset), result);
+    }
 }
 
-void JIT::testPrototype(Structure* structure, JumpList& failureCases)
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID result, size_t cachedOffset)
 {
-    if (structure->m_prototype.isNull())
-        return;
-
-    move(ImmPtr(&asCell(structure->m_prototype)->m_structure), regT2);
-    move(ImmPtr(asCell(structure->m_prototype)->m_structure), regT3);
-    failureCases.append(branchPtr(NotEqual, Address(regT2), regT3));
+    loadPtr(static_cast<void*>(&base->m_propertyStorage[cachedOffset]), result);
 }
 
 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
@@ -604,13 +559,13 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     JumpList failureCases;
     // Check eax is an object of the right Structure.
     failureCases.append(emitJumpIfNotJSCell(regT0));
-    failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
-    testPrototype(oldStructure, failureCases);
+    failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure)));
+    testPrototype(oldStructure->storedPrototype(), failureCases);
 
     // ecx = baseObject->m_structure
     if (!direct) {
-        for (RefPtr<Structure>* it = chain->head(); *it; ++it)
-            testPrototype(it->get(), failureCases);
+        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it)
+            testPrototype((*it)->storedPrototype(), failureCases);
     }
 
     Call callTarget;
@@ -626,19 +581,15 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         stubCall.skipArgument(); // base
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
-        stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity()));
-        stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity()));
+        stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
+        stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
         stubCall.call(regT0);
         emitGetJITStubArg(2, regT1);
 
         restoreReturnAddressBeforeReturn(regT3);
     }
 
-    // Assumes m_refCount can be decremented easily, refcount decrement is safe as 
-    // codeblock should ensure oldStructure->m_refCount > 0
-    sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount()));
-    add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount()));
-    storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)));
+    storePtrWithWriteBarrier(TrustedImmPtr(newStructure), regT0, Address(regT0, JSCell::structureOffset()));
 
     // write the value
     compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset);
@@ -650,7 +601,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
 
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
 
     patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
 
@@ -675,34 +626,9 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
 
     int offset = sizeof(JSValue) * cachedOffset;
 
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
-
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
-}
-
-void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
-{
-    RepatchBuffer repatchBuffer(codeBlock);
-
-    ASSERT(!methodCallLinkInfo.cachedStructure);
-    methodCallLinkInfo.cachedStructure = structure;
-    structure->ref();
-
-    Structure* prototypeStructure = proto->structure();
-    methodCallLinkInfo.cachedPrototypeStructure = prototypeStructure;
-    prototypeStructure->ref();
-
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
-
-    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset), offset);
 }
 
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
@@ -715,11 +641,6 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
 
     int offset = sizeof(JSValue) * cachedOffset;
 
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
-
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset), offset);
@@ -730,18 +651,17 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
 
     // Check eax is an array
-    Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr));
+    Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr));
 
     // Checks out okay! - get the length from the storage
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
-    load32(Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2);
-
-    Jump failureCases2 = branch32(Above, regT2, Imm32(JSImmediate::maxImmediateInt));
+    loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
+    load32(Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2);
+    Jump failureCases2 = branch32(LessThan, regT2, TrustedImm32(0));
 
     emitFastArithIntToImmNoCheck(regT2, regT0);
     Jump success = jump();
 
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
 
     // Use the patch information to link the failure cases back to the original slow case routine.
     CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -774,37 +694,32 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     Jump failureCases1 = checkStructure(regT0, structure);
 
     // Check the prototype object's Structure had not changed.
-    Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-    move(ImmPtr(prototypeStructure), regT3);
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
-#else
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
-#endif
+    move(TrustedImmPtr(protoObject), regT3);
+    Jump failureCases2 = branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototypeStructure));
 
     bool needsStubLink = false;
     
     // Checks out okay!
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
 
     // Use the patch information to link the failure cases back to the original slow case routine.
     CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -839,29 +754,25 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        if (!structure->isUsingInlineStorage()) {
-            move(regT0, regT1);
-            compileGetDirectOffset(regT1, regT1, structure, cachedOffset);
-        } else
-            compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
+        compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
         compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
     Jump success = jump();
 
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
 
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -882,8 +793,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
 
     CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
 
-    structure->ref();
-    polymorphicStructures->list[currentIndex].set(entryLabel, structure);
+    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -901,38 +811,33 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     Jump failureCases1 = checkStructure(regT0, structure);
 
     // Check the prototype object's Structure had not changed.
-    Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-    move(ImmPtr(prototypeStructure), regT3);
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
-#else
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
-#endif
+    move(TrustedImmPtr(protoObject), regT3);
+    Jump failureCases2 = branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototypeStructure));
 
     // Checks out okay!
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
 
     Jump success = jump();
 
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
 
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -950,10 +855,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
 
     CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-
-    structure->ref();
-    prototypeStructure->ref();
-    prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
+    prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure, prototypeStructure);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -971,45 +873,37 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     bucketsOfFail.append(baseObjectCheck);
 
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
-        currStructure = chainEntries[i].get();
-
-        // Check the prototype object's Structure had not changed.
-        Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-        move(ImmPtr(currStructure), regT3);
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
-#else
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
-#endif
+        currStructure = it->get();
+        testPrototype(protoObject, bucketsOfFail);
     }
     ASSERT(protoObject);
     
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -1029,9 +923,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
 
     // Track the stub we have created so that it will be deleted later.
-    structure->ref();
-    chain->ref();
-    prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
+    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
 
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -1049,45 +941,37 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     bucketsOfFail.append(checkStructure(regT0, structure));
 
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
-        currStructure = chainEntries[i].get();
-
-        // Check the prototype object's Structure had not changed.
-        Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-        move(ImmPtr(currStructure), regT3);
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
-#else
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
-#endif
+        currStructure = it->get();
+        testPrototype(protoObject, bucketsOfFail);
     }
     ASSERT(protoObject);
 
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
 
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
@@ -1119,8 +1003,33 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
 #endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
+#endif // USE(JSVALUE64)
+
+void JIT::testPrototype(JSValue prototype, JumpList& failureCases)
+{
+    if (prototype.isNull())
+        return;
+
+    ASSERT(prototype.isCell());
+    move(TrustedImmPtr(prototype.asCell()), regT3);
+    failureCases.append(branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototype.asCell()->structure())));
+}
+
+void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSObjectWithGlobalObject* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
+{
+    RepatchBuffer repatchBuffer(codeBlock);
+    
+    ASSERT(!methodCallLinkInfo.cachedStructure);
+    CodeLocationDataLabelPtr structureLocation = methodCallLinkInfo.cachedStructure.location();
+    methodCallLinkInfo.cachedStructure.set(globalData, structureLocation, codeBlock->ownerExecutable(), structure);
+    
+    Structure* prototypeStructure = proto->structure();
+    methodCallLinkInfo.cachedPrototypeStructure.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), codeBlock->ownerExecutable(), prototypeStructure);
+    methodCallLinkInfo.cachedPrototype.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), codeBlock->ownerExecutable(), proto);
+    methodCallLinkInfo.cachedFunction.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), codeBlock->ownerExecutable(), callee);
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
-
-#endif // !USE(JSVALUE32_64)
index 059c9c5c9382264503ef6ebd744e58e16787004b..3b3050e0bdd75b9c6c342fc54e38c4c185602e9d 100644 (file)
 
 #include "config.h"
 
+#if ENABLE(JIT)
 #if USE(JSVALUE32_64)
-
 #include "JIT.h"
 
-#if ENABLE(JIT)
-
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -72,7 +70,7 @@ void JIT::emit_op_put_getter(Instruction* currentInstruction)
     
     JITStubCall stubCall(this, cti_op_put_getter);
     stubCall.addArgument(base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
     stubCall.addArgument(function);
     stubCall.call();
 }
@@ -85,7 +83,7 @@ void JIT::emit_op_put_setter(Instruction* currentInstruction)
     
     JITStubCall stubCall(this, cti_op_put_setter);
     stubCall.addArgument(base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
     stubCall.addArgument(function);
     stubCall.call();
 }
@@ -98,7 +96,7 @@ void JIT::emit_op_del_by_id(Instruction* currentInstruction)
     
     JITStubCall stubCall(this, cti_op_del_by_id);
     stubCall.addArgument(base);
-    stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(property)));
+    stubCall.addArgument(TrustedImmPtr(&m_codeBlock->identifier(property)));
     stubCall.call(dst);
 }
 
@@ -157,7 +155,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     
     JITStubCall stubCall(this, cti_op_get_by_id_generic);
     stubCall.addArgument(base);
-    stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
     stubCall.call(dst);
     
     m_propertyAccessInstructionIndex++;
@@ -177,7 +175,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     
     JITStubCall stubCall(this, cti_op_put_by_id_generic);
     stubCall.addArgument(base);
-    stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
     stubCall.addArgument(value);
     stubCall.call();
     
@@ -215,21 +213,21 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
     
-    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
-    DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT2);
-    Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), info.structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(TrustedImmPtr(0), regT2);
+    Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, JSCell::structureOffset()), protoStructureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     
     // This will be relinked to load the function without doing a load.
-    DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0);
+    DataLabelPtr putFunction = moveWithPatch(TrustedImmPtr(0), regT0);
     
     END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
     
-    move(Imm32(JSValue::CellTag), regT1);
+    move(TrustedImm32(JSValue::CellTag), regT1);
     Jump match = jump();
     
-    ASSERT(differenceBetween(info.structureToCompare, protoObj) == patchOffsetMethodCheckProtoObj);
-    ASSERT(differenceBetween(info.structureToCompare, protoStructureToCompare) == patchOffsetMethodCheckProtoStruct);
-    ASSERT(differenceBetween(info.structureToCompare, putFunction) == patchOffsetMethodCheckPutFunction);
+    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj);
+    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct);
+    ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction);
     
     // Link the failure cases here.
     structureCheck.link(this);
@@ -241,10 +239,10 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     
     match.link(this);
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_method_check), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_method_check), dst, regT1, regT0);
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
-    m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+    m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
 void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -258,7 +256,7 @@ void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowC
     compileGetByIdSlowCase(dst, base, &(m_codeBlock->identifier(ident)), iter, true);
     
     // We've already generated the following get_by_id, so make sure it's skipped over.
-    m_bytecodeIndex += OPCODE_LENGTH(op_get_by_id);
+    m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id);
 }
 
 #else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
@@ -269,11 +267,11 @@ void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator
 
 #endif
 
-PassRefPtr<NativeExecutable> JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
     JSInterfaceJIT jit;
     JumpList failures;
-    failures.append(jit.branchPtr(NotEqual, Address(regT0), ImmPtr(globalData->jsStringVPtr)));
+    failures.append(jit.branchPtr(NotEqual, Address(regT0), TrustedImmPtr(globalData->jsStringVPtr)));
     failures.append(jit.branchTest32(NonZero, Address(regT0, OBJECT_OFFSETOF(JSString, m_fiberCount))));
     
     // Load string length to regT1, and start the process of loading the data pointer into regT0
@@ -287,18 +285,18 @@ PassRefPtr<NativeExecutable> JIT::stringGetByValStubGenerator(JSGlobalData* glob
     // Load the character
     jit.load16(BaseIndex(regT0, regT2, TimesTwo, 0), regT0);
     
-    failures.append(jit.branch32(AboveOrEqual, regT0, Imm32(0x100)));
-    jit.move(ImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
+    failures.append(jit.branch32(AboveOrEqual, regT0, TrustedImm32(0x100)));
+    jit.move(TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), regT1);
     jit.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
-    jit.move(Imm32(JSValue::CellTag), regT1); // We null check regT0 on return so this is safe
+    jit.move(TrustedImm32(JSValue::CellTag), regT1); // We null check regT0 on return so this is safe
     jit.ret();
 
     failures.link(&jit);
-    jit.move(Imm32(0), regT0);
+    jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
-    LinkBuffer patchBuffer(&jit, pool, 0);
-    return adoptRef(new NativeExecutable(patchBuffer.finalizeCode()));
+    LinkBuffer patchBuffer(*globalData, &jit, pool);
+    return patchBuffer.finalizeCode().m_code;
 }
 
 void JIT::emit_op_get_by_val(Instruction* currentInstruction)
@@ -309,19 +307,19 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction)
     
     emitLoad2(base, regT1, regT0, property, regT3, regT2);
     
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
     
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
-    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
+    loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
+    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
     
-    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), regT1); // tag
-    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), regT0); // payload
-    addSlowCase(branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag)));
+    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
+    load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
+    addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
     
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_val), dst, regT1, regT0);
 }
 
 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -335,8 +333,8 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas
 
     Jump nonCell = jump();
     linkSlowCase(iter); // base array check
-    Jump notString = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
-    emitNakedCall(m_globalData->getThunk(stringGetByValStubGenerator)->generatedJITCode().addressForCall());
+    Jump notString = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsStringVPtr));
+    emitNakedCall(m_globalData->getCTIStub(stringGetByValStubGenerator));
     Jump failed = branchTestPtr(Zero, regT0);
     emitStore(dst, regT1, regT0);
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
@@ -361,26 +359,26 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
     
     emitLoad2(base, regT1, regT0, property, regT3, regT2);
     
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
-    addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr)));
-    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, OBJECT_OFFSETOF(JSArray, m_vectorLength))));
+    addSlowCase(branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr)));
+    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
     
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT3);
+    loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
     
-    Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4), Imm32(JSValue::EmptyValueTag));
+    Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
     
     Label storeResult(this);
     emitLoad(value, regT1, regT0);
-    store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))); // payload
-    store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + 4)); // tag
+    store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); // payload
+    store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); // tag
     Jump end = jump();
     
     empty.link(this);
-    add32(Imm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
+    add32(TrustedImm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
     branch32(Below, regT2, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length))).linkTo(storeResult, this);
     
-    add32(Imm32(1), regT2, regT0);
+    add32(TrustedImm32(1), regT2, regT0);
     store32(regT0, Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_length)));
     jump().linkTo(storeResult, this);
     
@@ -414,7 +412,7 @@ void JIT::emit_op_get_by_id(Instruction* currentInstruction)
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     compileGetByIdHotPath();
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_id), dst, regT1, regT0);
 }
 
 void JIT::compileGetByIdHotPath()
@@ -431,23 +429,19 @@ void JIT::compileGetByIdHotPath()
     m_propertyAccessInstructionIndex++;
     
     DataLabelPtr structureToCompare;
-    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
+    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));
     addSlowCase(structureCheck);
-    ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);
-    ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase);
     
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT2);
-    Label externalLoadComplete(this);
-    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad);
-    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad);
-    
-    DataLabel32 displacementLabel1 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
-    ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetGetByIdPropertyMapOffset1);
-    DataLabel32 displacementLabel2 = loadPtrWithAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
-    ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetGetByIdPropertyMapOffset2);
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT2);
+    DataLabelCompact displacementLabel1 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel1), patchOffsetGetByIdPropertyMapOffset1);
+    DataLabelCompact displacementLabel2 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel2), patchOffsetGetByIdPropertyMapOffset2);
     
     Label putResult(this);
-    ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult);
     
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 }
@@ -478,12 +472,12 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl
 #endif
     JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id);
     stubCall.addArgument(regT1, regT0);
-    stubCall.addArgument(ImmPtr(ident));
+    stubCall.addArgument(TrustedImmPtr(ident));
     Call call = stubCall.call(dst);
     
-    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
+    END_UNINTERRUPTED_SEQUENCE_FOR_PUT(sequenceGetByIdSlowCase, dst);
     
-    ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);
+    ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall);
     
     // Track the location of the call; this will be used to recover patch information.
     m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call;
@@ -511,22 +505,17 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction)
     
     // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
     DataLabelPtr structureToCompare;
-    addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
-    ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure);
-    
-    // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
-    Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0);
-    Label externalLoadComplete(this);
-    ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad);
-    ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad);
+    addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure);
     
-    DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload
-    DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag
+    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), regT0);
+    DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchPutByIdDefaultOffset)); // payload
+    DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchPutByIdDefaultOffset)); // tag
     
     END_UNINTERRUPTED_SEQUENCE(sequencePutById);
     
-    ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetPutByIdPropertyMapOffset1);
-    ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetPutByIdPropertyMapOffset2);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel1), patchOffsetPutByIdPropertyMapOffset1);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel2), patchOffsetPutByIdPropertyMapOffset2);
 }
 
 void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -540,7 +529,7 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase
     
     JITStubCall stubCall(this, direct ? cti_op_put_by_id_direct : cti_op_put_by_id);
     stubCall.addArgument(regT1, regT0);
-    stubCall.addArgument(ImmPtr(&(m_codeBlock->identifier(ident))));
+    stubCall.addArgument(TrustedImmPtr(&(m_codeBlock->identifier(ident))));
     stubCall.addArgument(regT3, regT2); 
     Call call = stubCall.call();
     
@@ -554,9 +543,9 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterI
 {
     int offset = cachedOffset;
     if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) /  sizeof(Register);
+        offset += JSObject::offsetOfInlineStorage() /  sizeof(Register);
     else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     emitStore(offset, valueTag, valuePayload, base);
 }
 
@@ -564,50 +553,44 @@ void JIT::compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterI
 void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset)
 {
     int offset = cachedOffset;
-    if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) / sizeof(Register);
-    else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
-    emitLoad(offset, resultTag, resultPayload, base);
-}
-
-void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
-{
-    if (base->isUsingInlineStorage()) {
-        load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]), resultPayload);
-        load32(reinterpret_cast<char*>(&base->m_inlineStorage[cachedOffset]) + 4, resultTag);
-        return;
+    if (structure->isUsingInlineStorage()) {
+        offset += JSObject::offsetOfInlineStorage() / sizeof(Register);
+        emitLoad(offset, resultTag, resultPayload, base);
+    } else {
+        RegisterID temp = resultPayload;
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), temp);
+        emitLoad(offset, resultTag, resultPayload, temp);
     }
-    
-    size_t offset = cachedOffset * sizeof(JSValue);
-    
-    PropertyStorage* protoPropertyStorage = &base->m_externalStorage;
-    loadPtr(static_cast<void*>(protoPropertyStorage), temp);
-    load32(Address(temp, offset), resultPayload);
-    load32(Address(temp, offset + 4), resultTag);
 }
 
-void JIT::testPrototype(Structure* structure, JumpList& failureCases)
+void JIT::compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset)
 {
-    if (structure->m_prototype.isNull())
-        return;
-    
-    failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(structure->m_prototype)->m_structure), ImmPtr(asCell(structure->m_prototype)->m_structure)));
+    load32(reinterpret_cast<char*>(&base->m_propertyStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload), resultPayload);
+    load32(reinterpret_cast<char*>(&base->m_propertyStorage[cachedOffset]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag), resultTag);
 }
 
 void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress, bool direct)
 {
-    // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag.  The value can be found on the stack.
-    
+    // The code below assumes that regT0 contains the basePayload and regT1 contains the baseTag.  Restore them from the stack.
+#if CPU(MIPS) || CPU(SH4) || CPU(ARM)
+    // For MIPS, we don't add sizeof(void*) to the stack offset.
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    // For MIPS, we don't add sizeof(void*) to the stack offset.
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+#else
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+#endif
+
     JumpList failureCases;
-    failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
-    failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure)));
-    testPrototype(oldStructure, failureCases);
+    failureCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
+    failureCases.append(branchPtr(NotEqual, Address(regT0, JSCell::structureOffset()), TrustedImmPtr(oldStructure)));
+    testPrototype(oldStructure->storedPrototype(), failureCases);
     
     if (!direct) {
         // Verify that nothing in the prototype chain has a setter for this property. 
-        for (RefPtr<Structure>* it = chain->head(); *it; ++it)
-            testPrototype(it->get(), failureCases);
+        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it)
+            testPrototype((*it)->storedPrototype(), failureCases);
     }
 
     // Reallocate property storage if needed.
@@ -622,23 +605,37 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         stubCall.skipArgument(); // base
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
-        stubCall.addArgument(Imm32(oldStructure->propertyStorageCapacity()));
-        stubCall.addArgument(Imm32(newStructure->propertyStorageCapacity()));
+        stubCall.addArgument(TrustedImm32(oldStructure->propertyStorageCapacity()));
+        stubCall.addArgument(TrustedImm32(newStructure->propertyStorageCapacity()));
         stubCall.call(regT0);
         
         restoreReturnAddressBeforeReturn(regT3);
+
+#if CPU(MIPS) || CPU(SH4) || CPU(ARM)
+        // For MIPS, we don't add sizeof(void*) to the stack offset.
+        load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+        // For MIPS, we don't add sizeof(void*) to the stack offset.
+        load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+#else
+        load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+        load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[0]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+#endif
     }
+
+    storePtrWithWriteBarrier(TrustedImmPtr(newStructure), regT0, Address(regT0, JSCell::structureOffset()));
     
-    sub32(Imm32(1), AbsoluteAddress(oldStructure->addressOfCount()));
-    add32(Imm32(1), AbsoluteAddress(newStructure->addressOfCount()));
-    storePtr(ImmPtr(newStructure), Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)));
-    
-    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(struct JITStackFrame, args[2]) + sizeof(void*)), regT3);
-    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(struct JITStackFrame, args[2]) + sizeof(void*) + 4), regT2);
-    
+#if CPU(MIPS) || CPU(SH4) || CPU(ARM)
+    // For MIPS, we don't add sizeof(void*) to the stack offset.
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT3);
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT2);
+#else
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT3);
+    load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + sizeof(void*) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT2);
+#endif
+
     // Write the value
     compilePutDirectOffset(regT0, regT2, regT3, newStructure, cachedOffset);
-    
+
     ret();
     
     ASSERT(!failureCases.empty());
@@ -646,7 +643,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     
     patchBuffer.link(failureCall, FunctionPtr(direct ? cti_op_put_by_id_direct_fail : cti_op_put_by_id_fail));
     
@@ -670,36 +667,11 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
     
     int offset = sizeof(JSValue) * cachedOffset;
-    
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetGetByIdExternalLoad));
-    
+
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure);
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset1), offset); // payload
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + 4); // tag
-}
-
-void JIT::patchMethodCallProto(CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSFunction* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress)
-{
-    RepatchBuffer repatchBuffer(codeBlock);
-    
-    ASSERT(!methodCallLinkInfo.cachedStructure);
-    methodCallLinkInfo.cachedStructure = structure;
-    structure->ref();
-    
-    Structure* prototypeStructure = proto->structure();
-    methodCallLinkInfo.cachedPrototypeStructure = prototypeStructure;
-    prototypeStructure->ref();
-    
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel, structure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), proto);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), prototypeStructure);
-    repatchBuffer.repatch(methodCallLinkInfo.structureLabel.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), callee);
-    
-    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id));
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
 }
 
 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct)
@@ -711,16 +683,11 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo,
     repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
     
     int offset = sizeof(JSValue) * cachedOffset;
-    
-    // If we're patching to use inline storage, convert the initial load to a lea; this avoids the extra load
-    // and makes the subsequent load's offset automatically correct
-    if (structure->isUsingInlineStorage())
-        repatchBuffer.repatchLoadPtrToLEA(stubInfo->hotPathBegin.instructionAtOffset(patchOffsetPutByIdExternalLoad));
-    
+
     // Patch the offset into the propoerty map to load from, then patch the Structure to look for.
     repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure);
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset); // payload
-    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + 4); // tag
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload
+    repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag
 }
 
 void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
@@ -730,18 +697,18 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     // regT0 holds a JSCell*
     
     // Check for array
-    Jump failureCases1 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsArrayVPtr));
+    Jump failureCases1 = branchPtr(NotEqual, Address(regT0), TrustedImmPtr(m_globalData->jsArrayVPtr));
     
     // Checks out okay! - get the length from the storage
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSArray, m_storage)), regT2);
+    loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
     load32(Address(regT2, OBJECT_OFFSETOF(ArrayStorage, m_length)), regT2);
     
-    Jump failureCases2 = branch32(Above, regT2, Imm32(INT_MAX));
+    Jump failureCases2 = branch32(Above, regT2, TrustedImm32(INT_MAX));
     move(regT2, regT0);
-    move(Imm32(JSValue::Int32Tag), regT1);
+    move(TrustedImm32(JSValue::Int32Tag), regT1);
     Jump success = jump();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     
     // Use the patch information to link the failure cases back to the original slow case routine.
     CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -775,37 +742,33 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
     Jump failureCases1 = checkStructure(regT0, structure);
     
     // Check the prototype object's Structure had not changed.
-    Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-    move(ImmPtr(prototypeStructure), regT3);
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
-#else
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
-#endif
+    move(TrustedImmPtr(protoObject), regT3);
+    Jump failureCases2 = branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototypeStructure));
+
     bool needsStubLink = false;
     // Checks out okay!
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
     Jump success = jump();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     
     // Use the patch information to link the failure cases back to the original slow case routine.
     CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall);
@@ -843,30 +806,26 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        if (!structure->isUsingInlineStorage()) {
-            move(regT0, regT1);
-            compileGetDirectOffset(regT1, regT2, regT1, structure, cachedOffset);
-        } else
-            compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset);
+        compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
         compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset);
 
     Jump success = jump();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
             if (iter->to)
@@ -884,9 +843,8 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
 
     CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    
-    structure->ref();
-    polymorphicStructures->list[currentIndex].set(entryLabel, structure);
+
+    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), entryLabel, structure);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -906,37 +864,32 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     Jump failureCases1 = checkStructure(regT0, structure);
     
     // Check the prototype object's Structure had not changed.
-    Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-    move(ImmPtr(prototypeStructure), regT3);
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3);
-#else
-    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
-#endif
+    move(TrustedImmPtr(protoObject), regT3);
+    Jump failureCases2 = branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototypeStructure));
     
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
     Jump success = jump();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
             if (iter->to)
@@ -952,10 +905,8 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
     
     CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
-    
-    structure->ref();
-    prototypeStructure->ref();
-    prototypeStructures->list[currentIndex].set(entryLabel, structure, prototypeStructure);
+
+    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, prototypeStructure);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -974,46 +925,38 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     bucketsOfFail.append(checkStructure(regT0, structure));
     
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
-        currStructure = chainEntries[i].get();
-        
-        // Check the prototype object's Structure had not changed.
-        Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-        move(ImmPtr(currStructure), regT3);
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
-#else
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
-#endif
+        currStructure = it->get();
+        testPrototype(protoObject, bucketsOfFail);
     }
     ASSERT(protoObject);
     
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
 
     Jump success = jump();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
             if (iter->to)
@@ -1031,9 +974,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
     CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
     
     // Track the stub we have created so that it will be deleted later.
-    structure->ref();
-    chain->ref();
-    prototypeStructures->list[currentIndex].set(entryLabel, structure, chain);
+    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), entryLabel, structure, chain);
     
     // Finally patch the jump to slow case back in the hot path to jump here instead.
     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
@@ -1052,45 +993,37 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
     bucketsOfFail.append(checkStructure(regT0, structure));
     
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
-        currStructure = chainEntries[i].get();
-        
-        // Check the prototype object's Structure had not changed.
-        Structure** prototypeStructureAddress = &(protoObject->m_structure);
-#if CPU(X86_64)
-        move(ImmPtr(currStructure), regT3);
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3));
-#else
-        bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(currStructure)));
-#endif
+        currStructure = it->get();
+        testPrototype(protoObject, bucketsOfFail);
     }
     ASSERT(protoObject);
     
     bool needsStubLink = false;
     if (slot.cachedPropertyType() == PropertySlot::Getter) {
         needsStubLink = true;
-        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
+        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
         stubCall.addArgument(regT1);
         stubCall.addArgument(regT0);
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
         needsStubLink = true;
         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
-        stubCall.addArgument(ImmPtr(protoObject));
-        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
-        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
-        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(protoObject));
+        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
+        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
+        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     Jump success = jump();
     
-    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
+    LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock->executablePool());
     if (needsStubLink) {
         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
             if (iter->to)
@@ -1120,21 +1053,13 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
 #endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
-void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset)
+void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset)
 {
-    ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t));
-    ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t));
     ASSERT(sizeof(JSValue) == 8);
     
-    Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity));
-    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
-    loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
-    Jump finishedLoad = jump();
-    notUsingInlineStorage.link(this);
-    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+    loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload);
     loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag);
-    finishedLoad.link(this);
 }
 
 void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
@@ -1154,15 +1079,15 @@ void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
     emitLoadPayload(iter, regT1);
     
     // Test base's structure
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
+    loadPtr(Address(regT2, JSCell::structureOffset()), regT0);
     addSlowCase(branchPtr(NotEqual, regT0, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))));
     load32(addressFor(i), regT3);
-    sub32(Imm32(1), regT3);
+    sub32(TrustedImm32(1), regT3);
     addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots))));
-    compileGetDirectOffset(regT2, regT1, regT0, regT0, regT3);    
+    compileGetDirectOffset(regT2, regT1, regT0, regT3);    
     
     emitStore(dst, regT1, regT0);
-    map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0);
+    map(m_bytecodeOffset + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0);
 }
 
 void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
@@ -1185,7 +1110,5 @@ void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowC
 
 } // namespace JSC
 
+#endif // USE(JSVALUE32_64)
 #endif // ENABLE(JIT)
-
-#endif // ENABLE(JSVALUE32_64)
-
index 70d289350bd7674681c8331ed33b20a99f0625dc..a0341d6b44cb7c4228ce2b6c76fcd06ba16a1fae 100644 (file)
@@ -99,13 +99,13 @@ namespace JSC {
             m_stackIndex += stackIndexStep;
         }
 
-        void addArgument(JIT::Imm32 argument)
+        void addArgument(JIT::TrustedImm32 argument)
         {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
         }
 
-        void addArgument(JIT::ImmPtr argument)
+        void addArgument(JIT::TrustedImmPtr argument)
         {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
@@ -167,17 +167,17 @@ namespace JSC {
         JIT::Call call()
         {
 #if ENABLE(OPCODE_SAMPLING)
-            if (m_jit->m_bytecodeIndex != (unsigned)-1)
-                m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, true);
+            if (m_jit->m_bytecodeOffset != (unsigned)-1)
+                m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, true);
 #endif
 
             m_jit->restoreArgumentReference();
             JIT::Call call = m_jit->call();
-            m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub.value()));
+            m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeOffset, m_stub.value()));
 
 #if ENABLE(OPCODE_SAMPLING)
-            if (m_jit->m_bytecodeIndex != (unsigned)-1)
-                m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, false);
+            if (m_jit->m_bytecodeOffset != (unsigned)-1)
+                m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeOffset, false);
 #endif
 
 #if USE(JSVALUE32_64)
index a104faf6605b677c477e05b407dfcd24f65905b4..2aee6a1b7765a059fc0e6658ac55d65118c0ae27 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
+ * Copyright (C) Research In Motion Limited 2010, 2011. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
-#include "JITStubs.h"
 
 #if ENABLE(JIT)
+#include "JITStubs.h"
 
 #include "Arguments.h"
 #include "CallFrame.h"
 #include "CodeBlock.h"
-#include "Collector.h"
+#include "Heap.h"
 #include "Debugger.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
-#include "GlobalEvalFunction.h"
+#include "Strong.h"
 #include "JIT.h"
 #include "JSActivation.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
 #include "JSFunction.h"
+#include "JSGlobalObjectFunctions.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
@@ -65,22 +67,26 @@ using namespace std;
 
 namespace JSC {
 
-#if OS(DARWIN) || OS(WINDOWS)
+#if OS(DARWIN) || (OS(WINDOWS) && CPU(X86))
 #define SYMBOL_STRING(name) "_" #name
 #else
 #define SYMBOL_STRING(name) #name
 #endif
 
-#if OS(IPHONE_OS)
+#if OS(IOS)
 #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name)
 #else
 #define THUMB_FUNC_PARAM(name)
 #endif
 
-#if OS(LINUX) && CPU(X86_64)
+#if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64)
 #define SYMBOL_STRING_RELOCATION(name) #name "@plt"
+#elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0))
+#define SYMBOL_STRING_RELOCATION(name) "_" #name
+#elif CPU(X86) && COMPILER(MINGW)
+#define SYMBOL_STRING_RELOCATION(name) "@" #name "@4"
 #else
-#define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
+#define SYMBOL_STRING_RELOCATION(name) #name
 #endif
 
 #if OS(DARWIN)
@@ -113,7 +119,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x3c, JITStackFrame_s
 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline);
 
-asm volatile (
+asm (
 ".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
@@ -135,23 +141,16 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ret" "\n"
 );
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
-#if !USE(JIT_STUB_ARGUMENT_VA_LIST)
     "movl %esp, %ecx" "\n"
-#endif
     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
-    "addl $0x3c, %esp" "\n"
-    "popl %ebx" "\n"
-    "popl %edi" "\n"
-    "popl %esi" "\n"
-    "popl %ebp" "\n"
-    "ret" "\n"
+    "int3" "\n"
 );
     
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
@@ -165,10 +164,6 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     
 #elif COMPILER(GCC) && CPU(X86_64)
 
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
-#endif
-
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 32 == 0x0, JITStackFrame_maintains_32byte_stack_alignment);
@@ -176,7 +171,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x48, JITStackFrame_s
 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x90, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x80, JITStackFrame_code_offset_matches_ctiTrampoline);
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
@@ -203,23 +198,16 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ret" "\n"
 );
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "movq %rsp, %rdi" "\n"
     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
-    "addq $0x48, %rsp" "\n"
-    "popq %rbx" "\n"
-    "popq %r15" "\n"
-    "popq %r14" "\n"
-    "popq %r13" "\n"
-    "popq %r12" "\n"
-    "popq %rbp" "\n"
-    "ret" "\n"
+    "int3" "\n"
 );
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
@@ -233,33 +221,27 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\n"
 );
 
-#elif COMPILER(GCC) && CPU(ARM_THUMB2)
-
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
-#endif
+#elif (COMPILER(GCC) || COMPILER(RVCT)) && CPU(ARM_THUMB2)
 
-#define THUNK_RETURN_ADDRESS_OFFSET      0x3C
-#define PRESERVED_RETURN_ADDRESS_OFFSET  0x40
-#define PRESERVED_R4_OFFSET              0x44
-#define PRESERVED_R5_OFFSET              0x48
-#define PRESERVED_R6_OFFSET              0x4C
-#define REGISTER_FILE_OFFSET             0x50
-#define CALLFRAME_OFFSET                 0x54
-#define EXCEPTION_OFFSET                 0x58
-#define ENABLE_PROFILER_REFERENCE_OFFSET 0x60
+#define THUNK_RETURN_ADDRESS_OFFSET      0x38
+#define PRESERVED_RETURN_ADDRESS_OFFSET  0x3C
+#define PRESERVED_R4_OFFSET              0x40
+#define PRESERVED_R5_OFFSET              0x44
+#define PRESERVED_R6_OFFSET              0x48
+#define REGISTER_FILE_OFFSET             0x4C
+#define CALLFRAME_OFFSET                 0x50
+#define EXCEPTION_OFFSET                 0x54
+#define ENABLE_PROFILER_REFERENCE_OFFSET 0x58
 
-#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
+#elif (COMPILER(GCC) || COMPILER(MSVC) || COMPILER(RVCT)) && CPU(ARM_TRADITIONAL)
 
+// Also update the MSVC section (defined at DEFINE_STUB_FUNCTION)
+// when changing one of the following values.
 #define THUNK_RETURN_ADDRESS_OFFSET 64
 #define PRESERVEDR4_OFFSET          68
 
 #elif COMPILER(MSVC) && CPU(X86)
 
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
-#endif
-
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) % 16 == 0x0, JITStackFrame_maintains_16byte_stack_alignment);
@@ -269,7 +251,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_
 
 extern "C" {
 
-    __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
+    __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
     {
         __asm {
             push ebp;
@@ -318,83 +300,108 @@ extern "C" {
     }
 }
 
-#else
-    #error "JIT not supported on this platform."
-#endif
-
-#else // USE(JSVALUE32_64)
-
-#if COMPILER(GCC) && CPU(X86)
+#elif CPU(MIPS)
 
-// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
-// need to change the assembly trampolines below to match.
-COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
-COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
-COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
+#define PRESERVED_GP_OFFSET         60
+#define PRESERVED_S0_OFFSET         64
+#define PRESERVED_S1_OFFSET         68
+#define PRESERVED_S2_OFFSET         72
+#define PRESERVED_RETURN_ADDRESS_OFFSET 76
+#define THUNK_RETURN_ADDRESS_OFFSET 80
+#define REGISTER_FILE_OFFSET        84
+#define CALLFRAME_OFFSET            88
+#define EXCEPTION_OFFSET            92
+#define ENABLE_PROFILER_REFERENCE_OFFSET 96
+#define GLOBAL_DATA_OFFSET         100
+#define STACK_LENGTH               104
+#elif CPU(SH4)
+#define SYMBOL_STRING(name) #name
+/* code (r4), RegisterFile* (r5), CallFrame* (r6), JSValue* exception (r7), Profiler**(sp), JSGlobalData (sp)*/
 
 asm volatile (
 ".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
-    "pushl %ebp" "\n"
-    "movl %esp, %ebp" "\n"
-    "pushl %esi" "\n"
-    "pushl %edi" "\n"
-    "pushl %ebx" "\n"
-    "subl $0x1c, %esp" "\n"
-    "movl $512, %esi" "\n"
-    "movl 0x38(%esp), %edi" "\n"
-    "call *0x30(%esp)" "\n"
-    "addl $0x1c, %esp" "\n"
-    "popl %ebx" "\n"
-    "popl %edi" "\n"
-    "popl %esi" "\n"
-    "popl %ebp" "\n"
-    "ret" "\n"
+    "mov.l r7, @-r15" "\n"
+    "mov.l r6, @-r15" "\n"
+    "mov.l r5, @-r15" "\n"
+    "mov.l r8, @-r15" "\n"
+    "mov #127, r8" "\n"
+    "mov.l r14, @-r15" "\n"
+    "sts.l pr, @-r15" "\n"
+    "mov.l r13, @-r15" "\n"
+    "mov.l r11, @-r15" "\n"
+    "mov.l r10, @-r15" "\n"
+    "add #-60, r15" "\n"
+    "mov r6, r14" "\n"
+    "jsr @r4" "\n"
+    "nop" "\n"
+    "add #60, r15" "\n"
+    "mov.l @r15+,r10" "\n"
+    "mov.l @r15+,r11" "\n"
+    "mov.l @r15+,r13" "\n"
+    "lds.l @r15+,pr" "\n"
+    "mov.l @r15+,r14" "\n"
+    "mov.l @r15+,r8" "\n"
+    "add #12, r15" "\n"
+    "rts" "\n"
+    "nop" "\n"
 );
 
 asm volatile (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
-#if !USE(JIT_STUB_ARGUMENT_VA_LIST)
-    "movl %esp, %ecx" "\n"
-#endif
-    "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
-    "addl $0x1c, %esp" "\n"
-    "popl %ebx" "\n"
-    "popl %edi" "\n"
-    "popl %esi" "\n"
-    "popl %ebp" "\n"
-    "ret" "\n"
+    "mov.l .L2"SYMBOL_STRING(cti_vm_throw)",r0" "\n"
+    "mov r15, r4" "\n"
+    "mov.l @(r0,r12),r11" "\n"
+    "jsr @r11" "\n"
+    "nop" "\n"
+    "add #60, r15" "\n"
+    "mov.l @r15+,r10" "\n"
+    "mov.l @r15+,r11" "\n"
+    "mov.l @r15+,r13" "\n"
+    "lds.l @r15+,pr" "\n"
+    "mov.l @r15+,r14" "\n"
+    "mov.l @r15+,r8" "\n"
+    "add #12, r15" "\n"
+    "rts" "\n"
+    "nop" "\n"
+    ".align 2" "\n"
+    ".L2"SYMBOL_STRING(cti_vm_throw)":.long " SYMBOL_STRING(cti_vm_throw)"@GOT \n"
 );
-    
+
 asm volatile (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
-    "addl $0x1c, %esp" "\n"
-    "popl %ebx" "\n"
-    "popl %edi" "\n"
-    "popl %esi" "\n"
-    "popl %ebp" "\n"
-    "ret" "\n"
+    "add #60, r15" "\n"
+    "mov.l @r15+,r10" "\n"
+    "mov.l @r15+,r11" "\n"
+    "mov.l @r15+,r13" "\n"
+    "lds.l @r15+,pr" "\n"
+    "mov.l @r15+,r14" "\n"
+    "mov.l @r15+,r8" "\n"
+    "add #12, r15" "\n"
+    "rts" "\n"
+    "nop" "\n"
 );
-    
-#elif COMPILER(GCC) && CPU(X86_64)
-
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64."
+#else
+    #error "JIT not supported on this platform."
 #endif
 
+#else // USE(JSVALUE32_64)
+
+#if COMPILER(GCC) && CPU(X86_64)
+
 // These ASSERTs remind you that, if you change the layout of JITStackFrame, you
 // need to change the assembly trampolines below to match.
 COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
 COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_offset_matches_ctiTrampoline);
 COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
 
-asm volatile (
+asm (
 ".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
@@ -429,23 +436,16 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ret" "\n"
 );
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "movq %rsp, %rdi" "\n"
     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
-    "addq $0x78, %rsp" "\n"
-    "popq %rbx" "\n"
-    "popq %r15" "\n"
-    "popq %r14" "\n"
-    "popq %r13" "\n"
-    "popq %r12" "\n"
-    "popq %rbp" "\n"
-    "ret" "\n"
+    "int3" "\n"
 );
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
@@ -459,34 +459,14 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\n"
 );
 
-#elif COMPILER(GCC) && CPU(ARM_THUMB2)
-
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7."
+#else
+    #error "JIT not supported on this platform."
 #endif
 
-#define THUNK_RETURN_ADDRESS_OFFSET      0x1C
-#define PRESERVED_RETURN_ADDRESS_OFFSET  0x20
-#define PRESERVED_R4_OFFSET              0x24
-#define PRESERVED_R5_OFFSET              0x28
-#define PRESERVED_R6_OFFSET              0x2C
-#define REGISTER_FILE_OFFSET             0x30
-#define CALLFRAME_OFFSET                 0x34
-#define EXCEPTION_OFFSET                 0x38
-#define ENABLE_PROFILER_REFERENCE_OFFSET 0x40
-
-#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
-
-#define THUNK_RETURN_ADDRESS_OFFSET 32
-#define PRESERVEDR4_OFFSET          36
-
-#elif CPU(MIPS)
-
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST not supported on MIPS."
-#endif
+#endif // USE(JSVALUE32_64)
 
-asm volatile(
+#if CPU(MIPS)
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".set noreorder" "\n"
@@ -495,37 +475,37 @@ asm volatile(
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".ent " SYMBOL_STRING(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
-    "addiu $29,$29,-72" "\n"
-    "sw    $31,44($29)" "\n"
-    "sw    $18,40($29)" "\n"
-    "sw    $17,36($29)" "\n"
-    "sw    $16,32($29)" "\n"
+    "addiu $29,$29,-" STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
+    "sw    $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
+    "sw    $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
+    "sw    $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
+    "sw    $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
 #if WTF_MIPS_PIC
-    "sw    $28,28($29)" "\n"
+    "sw    $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
 #endif
     "move  $16,$6       # set callFrameRegister" "\n"
     "li    $17,512      # set timeoutCheckRegister" "\n"
     "move  $25,$4       # move executableAddress to t9" "\n"
-    "sw    $5,52($29)   # store registerFile to current stack" "\n"
-    "sw    $6,56($29)   # store callFrame to curent stack" "\n"
-    "sw    $7,60($29)   # store exception to current stack" "\n"
-    "lw    $8,88($29)   # load enableProfilerReference from previous stack" "\n"
-    "lw    $9,92($29)   # load globalData from previous stack" "\n"
-    "sw    $8,64($29)   # store enableProfilerReference to current stack" "\n"
+    "sw    $5," STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "($29) # store registerFile to current stack" "\n"
+    "sw    $6," STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "($29)     # store callFrame to curent stack" "\n"
+    "sw    $7," STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "($29)     # store exception to current stack" "\n"
+    "lw    $8," STRINGIZE_VALUE_OF(STACK_LENGTH + 16) "($29)    # load enableProfilerReference from previous stack" "\n"
+    "lw    $9," STRINGIZE_VALUE_OF(STACK_LENGTH + 20) "($29)    # load globalData from previous stack" "\n"
+    "sw    $8," STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "($29)   # store enableProfilerReference to current stack" "\n"
     "jalr  $25" "\n"
-    "sw    $9,68($29)   # store globalData to current stack" "\n"
-    "lw    $16,32($29)" "\n"
-    "lw    $17,36($29)" "\n"
-    "lw    $18,40($29)" "\n"
-    "lw    $31,44($29)" "\n"
+    "sw    $9," STRINGIZE_VALUE_OF(GLOBAL_DATA_OFFSET) "($29)   # store globalData to current stack" "\n"
+    "lw    $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
+    "lw    $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
+    "lw    $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
+    "lw    $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
     "jr    $31" "\n"
-    "addiu $29,$29,72" "\n"
+    "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
 ".set reorder" "\n"
 ".set macro" "\n"
 ".end " SYMBOL_STRING(ctiTrampoline) "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".set noreorder" "\n"
@@ -535,7 +515,7 @@ asm volatile(
 ".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 #if WTF_MIPS_PIC
-    "lw    $28,28($29)" "\n"
+    "lw    $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n"
 ".set macro" "\n"
     "la    $25," SYMBOL_STRING(cti_vm_throw) "\n"
 ".set nomacro" "\n"
@@ -545,18 +525,18 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "jal " SYMBOL_STRING(cti_vm_throw) "\n"
     "move  $4,$29" "\n"
 #endif
-    "lw    $16,32($29)" "\n"
-    "lw    $17,36($29)" "\n"
-    "lw    $18,40($29)" "\n"
-    "lw    $31,44($29)" "\n"
+    "lw    $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
+    "lw    $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
+    "lw    $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
+    "lw    $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
     "jr    $31" "\n"
-    "addiu $29,$29,72" "\n"
+    "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
 ".set reorder" "\n"
 ".set macro" "\n"
 ".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".set noreorder" "\n"
@@ -565,131 +545,21 @@ asm volatile(
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 ".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
-    "lw    $16,32($29)" "\n"
-    "lw    $17,36($29)" "\n"
-    "lw    $18,40($29)" "\n"
-    "lw    $31,44($29)" "\n"
+    "lw    $16," STRINGIZE_VALUE_OF(PRESERVED_S0_OFFSET) "($29)" "\n"
+    "lw    $17," STRINGIZE_VALUE_OF(PRESERVED_S1_OFFSET) "($29)" "\n"
+    "lw    $18," STRINGIZE_VALUE_OF(PRESERVED_S2_OFFSET) "($29)" "\n"
+    "lw    $31," STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "($29)" "\n"
     "jr    $31" "\n"
-    "addiu $29,$29,72" "\n"
+    "addiu $29,$29," STRINGIZE_VALUE_OF(STACK_LENGTH) "\n"
 ".set reorder" "\n"
 ".set macro" "\n"
 ".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 );
-
-#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
-
-#define THUNK_RETURN_ADDRESS_OFFSET 32
-#define PRESERVEDR4_OFFSET          36
-
-__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
-{
-    ARM
-    stmdb sp!, {r1-r3}
-    stmdb sp!, {r4-r8, lr}
-    sub sp, sp, #36
-    mov r4, r2
-    mov r5, #512
-    mov lr, pc
-    bx r0
-    add sp, sp, #36
-    ldmia sp!, {r4-r8, lr}
-    add sp, sp, #12
-    bx lr
-}
-
-__asm void ctiVMThrowTrampoline()
-{
-    ARM
-    PRESERVE8
-    mov r0, sp
-    bl cti_vm_throw
-    add sp, sp, #36
-    ldmia sp!, {r4-r8, lr}
-    add sp, sp, #12
-    bx lr
-}
-
-__asm void ctiOpThrowNotCaught()
-{
-    ARM
-    add sp, sp, #36
-    ldmia sp!, {r4-r8, lr}
-    add sp, sp, #12
-    bx lr
-}
-
-#elif COMPILER(MSVC) && CPU(X86)
-
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC."
-#endif
-
-// These ASSERTs remind you that, if you change the layout of JITStackFrame, you
-// need to change the assembly trampolines below to match.
-COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x38, JITStackFrame_callFrame_offset_matches_ctiTrampoline);
-COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_offset_matches_ctiTrampoline);
-COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline);
-
-extern "C" {
-
-    __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
-    {
-        __asm {
-            push ebp;
-            mov ebp, esp;
-            push esi;
-            push edi;
-            push ebx;
-            sub esp, 0x1c;
-            mov esi, 512;
-            mov ecx, esp;
-            mov edi, [esp + 0x38];
-            call [esp + 0x30];
-            add esp, 0x1c;
-            pop ebx;
-            pop edi;
-            pop esi;
-            pop ebp;
-            ret;
-        }
-    }
-
-    __declspec(naked) void ctiVMThrowTrampoline()
-    {
-        __asm {
-            mov ecx, esp;
-            call cti_vm_throw;
-            add esp, 0x1c;
-            pop ebx;
-            pop edi;
-            pop esi;
-            pop ebp;
-            ret;
-        }
-    }
-     
-     __declspec(naked) void ctiOpThrowNotCaught()
-     {
-         __asm {
-             add esp, 0x1c;
-             pop ebx;
-             pop edi;
-             pop esi;
-             pop ebp;
-             ret;
-         }
-     }
-}
-
-#else
-    #error "JIT not supported on this platform."
 #endif
 
-#endif // USE(JSVALUE32_64)
-
 #if COMPILER(GCC) && CPU(ARM_THUMB2)
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
@@ -716,7 +586,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "bx lr" "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
@@ -734,7 +604,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "bx lr" "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
@@ -752,7 +622,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 
 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
 
-asm volatile(
+asm (
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
@@ -770,7 +640,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "mov pc, lr" "\n"
 );
 
-asm volatile(
+asm (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
@@ -787,6 +657,92 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "mov pc, lr" "\n"
 );
 
+#elif COMPILER(RVCT) && CPU(ARM_THUMB2)
+
+__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
+{
+    PRESERVE8
+    sub sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+    str lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
+    str r4, [sp, # PRESERVED_R4_OFFSET ]
+    str r5, [sp, # PRESERVED_R5_OFFSET ]
+    str r6, [sp, # PRESERVED_R6_OFFSET ]
+    str r1, [sp, # REGISTER_FILE_OFFSET ]
+    str r2, [sp, # CALLFRAME_OFFSET ]
+    str r3, [sp, # EXCEPTION_OFFSET ]
+    cpy r5, r2
+    mov r6, #512
+    blx r0
+    ldr r6, [sp, # PRESERVED_R6_OFFSET ]
+    ldr r5, [sp, # PRESERVED_R5_OFFSET ]
+    ldr r4, [sp, # PRESERVED_R4_OFFSET ]
+    ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
+    add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+    bx lr
+}
+
+__asm void ctiVMThrowTrampoline()
+{
+    PRESERVE8
+    cpy r0, sp
+    bl cti_vm_throw
+    ldr r6, [sp, # PRESERVED_R6_OFFSET ]
+    ldr r5, [sp, # PRESERVED_R5_OFFSET ]
+    ldr r4, [sp, # PRESERVED_R4_OFFSET ]
+    ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
+    add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+    bx lr
+}
+
+__asm void ctiOpThrowNotCaught()
+{
+    PRESERVE8
+    ldr r6, [sp, # PRESERVED_R6_OFFSET ]
+    ldr r5, [sp, # PRESERVED_R5_OFFSET ]
+    ldr r4, [sp, # PRESERVED_R4_OFFSET ]
+    ldr lr, [sp, # PRESERVED_RETURN_ADDRESS_OFFSET ]
+    add sp, sp, # ENABLE_PROFILER_REFERENCE_OFFSET
+    bx lr
+}
+
+#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
+
+__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
+{
+    ARM
+    stmdb sp!, {r1-r3}
+    stmdb sp!, {r4-r8, lr}
+    sub sp, sp, # PRESERVEDR4_OFFSET
+    mov r4, r2
+    mov r5, #512
+    mov lr, pc
+    bx r0
+    add sp, sp, # PRESERVEDR4_OFFSET
+    ldmia sp!, {r4-r8, lr}
+    add sp, sp, #12
+    bx lr
+}
+
+__asm void ctiVMThrowTrampoline()
+{
+    ARM
+    PRESERVE8
+    mov r0, sp
+    bl cti_vm_throw
+    add sp, sp, # PRESERVEDR4_OFFSET
+    ldmia sp!, {r4-r8, lr}
+    add sp, sp, #12
+    bx lr
+}
+
+__asm void ctiOpThrowNotCaught()
+{
+    ARM
+    add sp, sp, # PRESERVEDR4_OFFSET
+    ldmia sp!, {r4-r8, lr}
+    add sp, sp, #12
+    bx lr
+}
 #endif
 
 #if ENABLE(OPCODE_SAMPLING)
@@ -796,9 +752,13 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 #endif
 
 JITThunks::JITThunks(JSGlobalData* globalData)
+    : m_hostFunctionStubMap(adoptPtr(new HostFunctionStubMap))
 {
-    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure);
+    if (!globalData->executableAllocator.isValid())
+        return;
 
+    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_trampolineStructure);
+    ASSERT(m_executablePool);
 #if CPU(ARM_THUMB2)
     // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types),
     // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT
@@ -810,7 +770,6 @@ JITThunks::JITThunks(JSGlobalData* globalData)
 
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == EXCEPTION_OFFSET);
     // The fifth argument is the first item already on the stack.
     ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
 
@@ -823,17 +782,17 @@ JITThunks::JITThunks(JSGlobalData* globalData)
 
 
 #elif CPU(MIPS)
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == 28);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == 32);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == 36);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == 40);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 44);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 48);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 52);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 56);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 60);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 64);
-    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == 68);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == PRESERVED_GP_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == PRESERVED_S0_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == PRESERVED_S1_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == PRESERVED_S2_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, unused1) == EXCEPTION_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET);
+    ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == GLOBAL_DATA_OFFSET);
 
 #endif
 }
@@ -857,10 +816,10 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
         return;
     }
     
-    JSCell* baseCell = asCell(baseValue);
+    JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
 
-    if (structure->isUncacheableDictionary()) {
+    if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
         return;
     }
@@ -884,12 +843,12 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
         normalizePrototypeChain(callFrame, baseCell);
 
         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
-        stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain);
+        stubInfo->initPutByIdTransition(callFrame->globalData(), codeBlock->ownerExecutable(), structure->previousID(), structure, prototypeChain);
         JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress, direct);
         return;
     }
     
-    stubInfo->initPutByIdReplace(structure);
+    stubInfo->initPutByIdReplace(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
 
     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
 }
@@ -925,10 +884,10 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
         return;
     }
 
-    JSCell* baseCell = asCell(baseValue);
+    JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
 
-    if (structure->isUncacheableDictionary()) {
+    if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
         return;
     }
@@ -937,8 +896,8 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
 
     if (slot.slotBase() == baseValue) {
         // set this up, so derefStructures can do it's job.
-        stubInfo->initGetByIdSelf(structure);
-        if (slot.cachedPropertyType() != PropertySlot::Value)
+        stubInfo->initGetByIdSelf(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
+        if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
             ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
         else
             JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
@@ -959,11 +918,11 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (slotBaseObject->structure()->isDictionary()) {
-            slotBaseObject->flattenDictionaryObject();
-            offset = slotBaseObject->structure()->get(propertyName);
+            slotBaseObject->flattenDictionaryObject(callFrame->globalData());
+            offset = slotBaseObject->structure()->get(callFrame->globalData(), propertyName);
         }
         
-        stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
+        stubInfo->initGetByIdProto(callFrame->globalData(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure());
 
         ASSERT(!structure->isDictionary());
         ASSERT(!slotBaseObject->structure()->isDictionary());
@@ -979,18 +938,12 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
     }
 
     StructureChain* prototypeChain = structure->prototypeChain(callFrame);
-    stubInfo->initGetByIdChain(structure, prototypeChain);
+    stubInfo->initGetByIdChain(callFrame->globalData(), codeBlock->ownerExecutable(), structure, prototypeChain);
     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
 }
 
 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-#define SETUP_VA_LISTL_ARGS va_list vl_args; va_start(vl_args, args)
-#else
-#define SETUP_VA_LISTL_ARGS
-#endif
-
 #ifndef NDEBUG
 
 extern "C" {
@@ -1021,13 +974,13 @@ struct StackHack {
     ReturnAddressPtr savedReturnAddress;
 };
 
-#define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
+#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS); StackHack stackHack(stackFrame)
 #define STUB_SET_RETURN_ADDRESS(returnAddress) stackHack.savedReturnAddress = ReturnAddressPtr(returnAddress)
 #define STUB_RETURN_ADDRESS stackHack.savedReturnAddress
 
 #else
 
-#define STUB_INIT_STACK_FRAME(stackFrame) SETUP_VA_LISTL_ARGS; JITStackFrame& stackFrame = *reinterpret_cast<JITStackFrame*>(STUB_ARGS)
+#define STUB_INIT_STACK_FRAME(stackFrame) JITStackFrame& stackFrame = *reinterpret_cast_ptr<JITStackFrame*>(STUB_ARGS)
 #define STUB_SET_RETURN_ADDRESS(returnAddress) *stackFrame.returnAddressSlot() = ReturnAddressPtr(returnAddress)
 #define STUB_RETURN_ADDRESS *stackFrame.returnAddressSlot()
 
@@ -1056,7 +1009,9 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         return 0; \
     } while (0)
 #define VM_THROW_EXCEPTION_AT_END() \
-    returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS)
+    do {\
+        returnToThrowTrampoline(stackFrame.globalData, STUB_RETURN_ADDRESS, STUB_RETURN_ADDRESS);\
+    } while (0)
 
 #define CHECK_FOR_EXCEPTION() \
     do { \
@@ -1076,13 +1031,32 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         } \
     } while (0)
 
-#if CPU(ARM_THUMB2)
+struct ExceptionHandler {
+    void* catchRoutine;
+    CallFrame* callFrame;
+};
+static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation)
+{
+    ASSERT(exceptionValue);
+
+    unsigned vPCIndex = callFrame->codeBlock()->bytecodeOffset(faultLocation);
+    globalData->exception = JSValue();
+    HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex); // This may update callFrame & exceptionValue!
+    globalData->exception = exceptionValue;
+
+    void* catchRoutine = handler ? handler->nativeCode.executableAddress() : FunctionPtr(ctiOpThrowNotCaught).value();
+    ASSERT(catchRoutine);
+    ExceptionHandler exceptionHandler = { catchRoutine, callFrame };
+    return exceptionHandler;
+}
+
+#if CPU(ARM_THUMB2) && COMPILER(GCC)
 
 #define DEFINE_STUB_FUNCTION(rtype, op) \
     extern "C" { \
         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
     }; \
-    asm volatile ( \
+    asm ( \
         ".text" "\n" \
         ".align 2" "\n" \
         ".globl " SYMBOL_STRING(cti_##op) "\n" \
@@ -1103,7 +1077,7 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
     extern "C" { \
         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
     }; \
-    asm volatile( \
+    asm ( \
         ".text" "\n" \
         ".align 2" "\n" \
         ".set noreorder" "\n" \
@@ -1112,14 +1086,14 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         ".globl " SYMBOL_STRING(cti_##op) "\n" \
         ".ent " SYMBOL_STRING(cti_##op) "\n" \
         SYMBOL_STRING(cti_##op) ":" "\n" \
-        "lw    $28,28($29)" "\n" \
-        "sw    $31,48($29)" "\n" \
+        "lw    $28," STRINGIZE_VALUE_OF(PRESERVED_GP_OFFSET) "($29)" "\n" \
+        "sw    $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
         ".set macro" "\n" \
         "la    $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \
         ".set nomacro" "\n" \
         "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
         "nop" "\n" \
-        "lw    $31,48($29)" "\n" \
+        "lw    $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
         "jr    $31" "\n" \
         "nop" "\n" \
         ".set reorder" "\n" \
@@ -1133,7 +1107,7 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
     extern "C" { \
         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
     }; \
-    asm volatile( \
+    asm ( \
         ".text" "\n" \
         ".align 2" "\n" \
         ".set noreorder" "\n" \
@@ -1142,10 +1116,10 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         ".globl " SYMBOL_STRING(cti_##op) "\n" \
         ".ent " SYMBOL_STRING(cti_##op) "\n" \
         SYMBOL_STRING(cti_##op) ":" "\n" \
-        "sw    $31,48($29)" "\n" \
+        "sw    $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
         "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \
         "nop" "\n" \
-        "lw    $31,48($29)" "\n" \
+        "lw    $31," STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "($29)" "\n" \
         "jr    $31" "\n" \
         "nop" "\n" \
         ".set reorder" "\n" \
@@ -1162,7 +1136,7 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
     extern "C" { \
         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
     }; \
-    asm volatile ( \
+    asm ( \
         ".globl " SYMBOL_STRING(cti_##op) "\n" \
         SYMBOL_STRING(cti_##op) ":" "\n" \
         "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \
@@ -1172,7 +1146,7 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         ); \
     rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
 
-#elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT)
+#elif (CPU(ARM_THUMB2) || CPU(ARM_TRADITIONAL)) && COMPILER(RVCT)
 
 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
 
@@ -1185,11 +1159,11 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
 RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);)
 RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION))
 RVCT({)
-RVCT(    ARM)
+RVCT(    PRESERVE8)
 RVCT(    IMPORT JITStubThunked_#op#)
-RVCT(    str lr, [sp, ##offset#])
+RVCT(    str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
 RVCT(    bl JITStubThunked_#op#)
-RVCT(    ldr lr, [sp, ##offset#])
+RVCT(    ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
 RVCT(    bx lr)
 RVCT(})
 RVCT()
@@ -1198,10 +1172,111 @@ RVCT()
 /* Include the generated file */
 #include "GeneratedJITStubs_RVCT.h"
 
+#elif CPU(ARM_TRADITIONAL) && COMPILER(MSVC)
+
+#define DEFINE_STUB_FUNCTION(rtype, op) extern "C" rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
+
+/* The following is a workaround for MSVC toolchain; inline assembler is not supported */
+
+/* The following section is a template to generate code for GeneratedJITStubs_MSVC.asm */
+/* The pattern "#xxx#" will be replaced with "xxx" */
+
+/*
+MSVC_BEGIN(    AREA Trampoline, CODE)
+MSVC_BEGIN()
+MSVC_BEGIN(    EXPORT ctiTrampoline)
+MSVC_BEGIN(    EXPORT ctiVMThrowTrampoline)
+MSVC_BEGIN(    EXPORT ctiOpThrowNotCaught)
+MSVC_BEGIN()
+MSVC_BEGIN(ctiTrampoline PROC)
+MSVC_BEGIN(    stmdb sp!, {r1-r3})
+MSVC_BEGIN(    stmdb sp!, {r4-r8, lr})
+MSVC_BEGIN(    sub sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
+MSVC_BEGIN(    mov r4, r2)
+MSVC_BEGIN(    mov r5, #512)
+MSVC_BEGIN(    ; r0 contains the code)
+MSVC_BEGIN(    mov lr, pc)
+MSVC_BEGIN(    bx r0)
+MSVC_BEGIN(    add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
+MSVC_BEGIN(    ldmia sp!, {r4-r8, lr})
+MSVC_BEGIN(    add sp, sp, #12)
+MSVC_BEGIN(    bx lr)
+MSVC_BEGIN(ctiTrampoline ENDP)
+MSVC_BEGIN()
+MSVC_BEGIN(ctiVMThrowTrampoline PROC)
+MSVC_BEGIN(    mov r0, sp)
+MSVC_BEGIN(    mov lr, pc)
+MSVC_BEGIN(    bl cti_vm_throw)
+MSVC_BEGIN(ctiOpThrowNotCaught)
+MSVC_BEGIN(    add sp, sp, #68 ; sync with PRESERVEDR4_OFFSET)
+MSVC_BEGIN(    ldmia sp!, {r4-r8, lr})
+MSVC_BEGIN(    add sp, sp, #12)
+MSVC_BEGIN(    bx lr)
+MSVC_BEGIN(ctiVMThrowTrampoline ENDP)
+MSVC_BEGIN()
+
+MSVC(    EXPORT cti_#op#)
+MSVC(    IMPORT JITStubThunked_#op#)
+MSVC(cti_#op# PROC)
+MSVC(    str lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
+MSVC(    bl JITStubThunked_#op#)
+MSVC(    ldr lr, [sp, #64] ; sync with THUNK_RETURN_ADDRESS_OFFSET)
+MSVC(    bx lr)
+MSVC(cti_#op# ENDP)
+MSVC()
+
+MSVC_END(    END)
+*/
+
+#elif CPU(SH4)
+#define DEFINE_STUB_FUNCTION(rtype, op) \
+    extern "C" { \
+        rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
+    }; \
+    asm volatile( \
+    ".align 2" "\n" \
+    ".globl " SYMBOL_STRING(cti_##op) "\n" \
+    SYMBOL_STRING(cti_##op) ":" "\n" \
+    "sts pr, r11" "\n" \
+    "mov.l r11, @(0x38, r15)" "\n" \
+    "mov.l .L2"SYMBOL_STRING(JITStubThunked_##op)",r0" "\n" \
+    "mov.l @(r0,r12),r11" "\n" \
+    "jsr @r11" "\n" \
+    "nop" "\n" \
+    "mov.l @(0x38, r15), r11 " "\n" \
+    "lds r11, pr " "\n" \
+    "rts" "\n" \
+    "nop" "\n" \
+    ".align 2" "\n" \
+    ".L2"SYMBOL_STRING(JITStubThunked_##op)":.long " SYMBOL_STRING(JITStubThunked_##op)"@GOT \n" \
+    ); \
+    rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
 #else
 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
 #endif
 
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+    CallFrame* callFrame = stackFrame.callFrame;
+
+    JSFunction* constructor = asFunction(callFrame->callee());
+#if !ASSERT_DISABLED
+    ConstructData constructData;
+    ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
+#endif
+
+    Structure* structure;
+    JSValue proto = stackFrame.args[0].jsValue();
+    if (proto.isObject())
+        structure = asObject(proto)->inheritorID(*stackFrame.globalData);
+    else
+        structure = constructor->scope()->globalObject->emptyObjectStructure();
+    JSValue result = constructEmptyObject(callFrame, structure);
+
+    return JSValue::encode(result);
+}
+
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1214,13 +1289,16 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this)
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(void, op_end)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
-    ScopeChainNode* scopeChain = stackFrame.callFrame->scopeChain();
-    ASSERT(scopeChain->refCount > 1);
-    scopeChain->deref();
+    
+    JSValue v1 = stackFrame.args[0].jsValue();
+    CallFrame* callFrame = stackFrame.callFrame;
+    ASSERT(v1.asCell()->structure()->typeInfo().needsThisConversion());
+    JSValue result = v1.toStrictThisObject(callFrame);
+    CHECK_FOR_EXCEPTION_AT_END();
+    return JSValue::encode(result);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
@@ -1241,7 +1319,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add)
 
     double left = 0.0, right;
     if (v1.getNumber(left) && v2.getNumber(right))
-        return JSValue::encode(jsNumber(stackFrame.globalData, left + right));
+        return JSValue::encode(jsNumber(left + right));
 
     // All other cases are pretty uncommon
     JSValue result = jsAddSlowCase(callFrame, v1, v2);
@@ -1256,7 +1334,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc)
     JSValue v = stackFrame.args[0].jsValue();
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) + 1);
+    JSValue result = jsNumber(v.toNumber(callFrame) + 1);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -1279,18 +1357,21 @@ DEFINE_STUB_FUNCTION(int, timeout_check)
     return timeoutChecker.ticksUntilNextCheck();
 }
 
-DEFINE_STUB_FUNCTION(void, register_file_check)
+DEFINE_STUB_FUNCTION(void*, register_file_check)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
+    CallFrame* callFrame = stackFrame.callFrame;
 
-    if (LIKELY(stackFrame.registerFile->grow(&stackFrame.callFrame->registers()[stackFrame.callFrame->codeBlock()->m_numCalleeRegisters])))
-        return;
+    if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
+        // Rewind to the previous call frame because op_call already optimistically
+        // moved the call frame forward.
+        CallFrame* oldCallFrame = callFrame->callerFrame();
+        ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(callFrame->returnPC()));
+        STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+        callFrame = handler.callFrame;
+    }
 
-    // Rewind to the previous call frame because op_call already optimistically
-    // moved the call frame forward.
-    CallFrame* oldCallFrame = stackFrame.callFrame->callerFrame();
-    stackFrame.callFrame = oldCallFrame;
-    throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
+    return callFrame;
 }
 
 DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
@@ -1317,7 +1398,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_generic)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    PutPropertySlot slot;
+    PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
     CHECK_FOR_EXCEPTION_AT_END();
 }
@@ -1326,7 +1407,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_generic)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
     
-    PutPropertySlot slot;
+    PutPropertySlot slot(stackFrame.callFrame->codeBlock()->isStrictMode());
     stackFrame.args[0].jsValue().putDirect(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
     CHECK_FOR_EXCEPTION_AT_END();
 }
@@ -1354,7 +1435,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id)
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
     
-    PutPropertySlot slot;
+    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
     
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
@@ -1373,7 +1454,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct)
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
     
-    PutPropertySlot slot;
+    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
     
     CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
@@ -1392,8 +1473,8 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_fail)
 
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
-
-    PutPropertySlot slot;
+    
+    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
 
     CHECK_FOR_EXCEPTION_AT_END();
@@ -1406,7 +1487,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_id_direct_fail)
     CallFrame* callFrame = stackFrame.callFrame;
     Identifier& ident = stackFrame.args[1].identifier();
     
-    PutPropertySlot slot;
+    PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
     stackFrame.args[0].jsValue().putDirect(callFrame, ident, stackFrame.args[2].jsValue(), slot);
     
     CHECK_FOR_EXCEPTION_AT_END();
@@ -1462,24 +1543,24 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
     JSObject* slotBaseObject;
     if (baseValue.isCell()
         && slot.isCacheableValue()
-        && !(structure = asCell(baseValue)->structure())->isUncacheableDictionary()
+        && !(structure = baseValue.asCell()->structure())->isUncacheableDictionary()
         && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
         && specific
         ) {
 
-        JSFunction* callee = (JSFunction*)specific;
+        JSObjectWithGlobalObject* callee = (JSObjectWithGlobalObject*)specific;
 
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (slotBaseObject->structure()->isDictionary())
-            slotBaseObject->flattenDictionaryObject();
+            slotBaseObject->flattenDictionaryObject(callFrame->globalData());
 
         // The result fetched should always be the callee!
         ASSERT(result == JSValue(callee));
 
         // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
         if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
-            JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
+            JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
             return JSValue::encode(result);
         }
 
@@ -1490,7 +1571,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
         // for now.  For now it performs a check on a special object on the global object only used for this
         // purpose.  The object is in no way exposed, and as such the check will always pass.
         if (slot.slotBase() == baseValue) {
-            JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
+            JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS);
             return JSValue::encode(result);
         }
     }
@@ -1536,7 +1617,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
 
     if (baseValue.isCell()
         && slot.isCacheable()
-        && !asCell(baseValue)->structure()->isUncacheableDictionary()
+        && !baseValue.asCell()->structure()->isUncacheableDictionary()
         && slot.slotBase() == baseValue) {
 
         CodeBlock* codeBlock = callFrame->codeBlock();
@@ -1549,7 +1630,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
 
         if (stubInfo->accessType == access_get_by_id_self) {
             ASSERT(!stubInfo->stubRoutine);
-            polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
+            polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure.get());
             stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
         } else {
             polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
@@ -1557,7 +1638,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
         }
         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
             stubInfo->u.getByIdSelfList.listSize++;
-            JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), ident, slot, slot.cachedOffset());
+            JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, baseValue.asCell()->structure(), ident, slot, slot.cachedOffset());
 
             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
@@ -1567,19 +1648,19 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
     return JSValue::encode(result);
 }
 
-static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
+static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(JSGlobalData& globalData, ScriptExecutable* owner, StructureStubInfo* stubInfo, int& listIndex)
 {
     PolymorphicAccessStructureList* prototypeStructureList = 0;
     listIndex = 1;
 
     switch (stubInfo->accessType) {
     case access_get_by_id_proto:
-        prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
+        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get());
         stubInfo->stubRoutine = CodeLocationLabel();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
     case access_get_by_id_chain:
-        prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
+        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get());
         stubInfo->stubRoutine = CodeLocationLabel();
         stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
         break;
@@ -1641,12 +1722,12 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
 
     CHECK_FOR_EXCEPTION();
 
-    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
+    if (!baseValue.isCell() || !slot.isCacheable() || baseValue.asCell()->structure()->isDictionary() || baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()) {
         ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
         return JSValue::encode(result);
     }
 
-    Structure* structure = asCell(baseValue)->structure();
+    Structure* structure = baseValue.asCell()->structure();
     CodeBlock* codeBlock = callFrame->codeBlock();
     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
 
@@ -1657,17 +1738,17 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
 
     if (slot.slotBase() == baseValue)
         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
-    else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
-        ASSERT(!asCell(baseValue)->structure()->isDictionary());
+    else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
+        ASSERT(!baseValue.asCell()->structure()->isDictionary());
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (slotBaseObject->structure()->isDictionary()) {
-            slotBaseObject->flattenDictionaryObject();
-            offset = slotBaseObject->structure()->get(propertyName);
+            slotBaseObject->flattenDictionaryObject(callFrame->globalData());
+            offset = slotBaseObject->structure()->get(callFrame->globalData(), propertyName);
         }
 
         int listIndex;
-        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
             JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
 
@@ -1675,9 +1756,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
         }
     } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
-        ASSERT(!asCell(baseValue)->structure()->isDictionary());
+        ASSERT(!baseValue.asCell()->structure()->isDictionary());
         int listIndex;
-        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
+        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
         
         if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
             StructureChain* protoChain = structure->prototypeChain(callFrame);
@@ -1742,6 +1823,23 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_string_fail)
 
 #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
+DEFINE_STUB_FUNCTION(void, op_check_has_instance)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSValue baseVal = stackFrame.args[0].jsValue();
+
+    // ECMA-262 15.3.5.3:
+    // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
+#ifndef NDEBUG
+    TypeInfo typeInfo(UnspecifiedType);
+    ASSERT(!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance());
+#endif
+    stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal);
+    VM_THROW_EXCEPTION_AT_END();
+}
+
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -1761,10 +1859,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
     // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function).
     TypeInfo typeInfo(UnspecifiedType);
     if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) {
-        CallFrame* callFrame = stackFrame.callFrame;
-        CodeBlock* codeBlock = callFrame->codeBlock();
-        unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-        stackFrame.globalData->exception = createInvalidParamError(callFrame, "instanceof", baseVal, vPCIndex, codeBlock);
+        stackFrame.globalData->exception = createInvalidParamError(stackFrame.callFrame, "instanceof", baseVal);
         VM_THROW_EXCEPTION();
     }
     ASSERT(typeInfo.type() != UnspecifiedType);
@@ -1774,7 +1869,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof)
             return JSValue::encode(jsBoolean(false));
 
         if (!proto.isObject()) {
-            throwError(callFrame, TypeError, "instanceof called on an object with an invalid prototype property.");
+            throwError(callFrame, createTypeError(callFrame, "instanceof called on an object with an invalid prototype property."));
             VM_THROW_EXCEPTION();
         }
     }
@@ -1793,7 +1888,11 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
     
     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
 
-    JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier()));
+    bool couldDelete = baseObj->deleteProperty(callFrame, stackFrame.args[1].identifier());
+    JSValue result = jsBoolean(couldDelete);
+    if (!couldDelete && callFrame->codeBlock()->isStrictMode())
+        stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
+
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -1808,10 +1907,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
     double left;
     double right;
     if (src1.getNumber(left) && src2.getNumber(right))
-        return JSValue::encode(jsNumber(stackFrame.globalData, left * right));
+        return JSValue::encode(jsNumber(left * right));
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+    JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -1819,103 +1918,239 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mul)
 DEFINE_STUB_FUNCTION(JSObject*, op_new_func)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
+    
+    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
     return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain());
 }
 
-DEFINE_STUB_FUNCTION(void*, op_call_JSFunction)
+DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
 #if !ASSERT_DISABLED
     CallData callData;
-    ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS);
+    ASSERT(stackFrame.callFrame->callee()->getCallData(callData) == CallTypeJS);
 #endif
 
-    JSFunction* function = asFunction(stackFrame.args[0].jsValue());
+    JSFunction* function = asFunction(stackFrame.callFrame->callee());
     ASSERT(!function->isHostFunction());
     FunctionExecutable* executable = function->jsExecutable();
-    ScopeChainNode* callDataScopeChain = function->scope().node();
-    executable->jitCode(stackFrame.callFrame, callDataScopeChain);
+    ScopeChainNode* callDataScopeChain = function->scope();
+    JSObject* error = executable->compileForCall(stackFrame.callFrame, callDataScopeChain);
+    if (error) {
+        stackFrame.callFrame->globalData().exception = error;
+        return 0;
+    }
+    return function;
+}
+
+DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+#if !ASSERT_DISABLED
+    ConstructData constructData;
+    ASSERT(asFunction(stackFrame.callFrame->callee())->getConstructData(constructData) == ConstructTypeJS);
+#endif
 
+    JSFunction* function = asFunction(stackFrame.callFrame->callee());
+    ASSERT(!function->isHostFunction());
+    FunctionExecutable* executable = function->jsExecutable();
+    ScopeChainNode* callDataScopeChain = function->scope();
+    JSObject* error = executable->compileForConstruct(stackFrame.callFrame, callDataScopeChain);
+    if (error) {
+        stackFrame.callFrame->globalData().exception = error;
+        return 0;
+    }
     return function;
 }
 
-DEFINE_STUB_FUNCTION(VoidPtrPair, op_call_arityCheck)
+DEFINE_STUB_FUNCTION(void*, op_call_arityCheck)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
+    JSFunction* callee = asFunction(callFrame->callee());
     ASSERT(!callee->isHostFunction());
-    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecode();
-    int argCount = stackFrame.args[2].int32();
+    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForCall();
+    int argCount = callFrame->argumentCountIncludingThis();
+    ReturnAddressPtr pc = callFrame->returnPC();
 
     ASSERT(argCount != newCodeBlock->m_numParameters);
 
     CallFrame* oldCallFrame = callFrame->callerFrame();
 
+    Register* r;
     if (argCount > newCodeBlock->m_numParameters) {
         size_t numParameters = newCodeBlock->m_numParameters;
-        Register* r = callFrame->registers() + numParameters;
+        r = callFrame->registers() + numParameters;
         Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
         if (!stackFrame.registerFile->grow(newEnd)) {
             // Rewind to the previous call frame because op_call already optimistically
             // moved the call frame forward.
-            stackFrame.callFrame = oldCallFrame;
-            throwStackOverflowError(oldCallFrame, stackFrame.globalData, stackFrame.args[1].returnAddress(), STUB_RETURN_ADDRESS);
-            RETURN_POINTER_PAIR(0, 0);
+            ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
+            STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+            return handler.callFrame;
         }
 
         Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
         for (size_t i = 0; i < numParameters; ++i)
             argv[i + argCount] = argv[i];
-
-        callFrame = CallFrame::create(r);
-        callFrame->setCallerFrame(oldCallFrame);
     } else {
         size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
-        Register* r = callFrame->registers() + omittedArgCount;
+        r = callFrame->registers() + omittedArgCount;
         Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
         if (!stackFrame.registerFile->grow(newEnd)) {
             // Rewind to the previous call frame because op_call already optimistically
             // moved the call frame forward.
-            stackFrame.callFrame = oldCallFrame;
-            throwStackOverflowError(oldCallFrame, stackFrame.globalData, stackFrame.args[1].returnAddress(), STUB_RETURN_ADDRESS);
-            RETURN_POINTER_PAIR(0, 0);
+            ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
+            STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+            return handler.callFrame;
         }
 
         Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
         for (size_t i = 0; i < omittedArgCount; ++i)
             argv[i] = jsUndefined();
+    }
+
+    callFrame = CallFrame::create(r);
+    callFrame->setCallerFrame(oldCallFrame);
+    callFrame->setArgumentCountIncludingThis(argCount);
+    callFrame->setCallee(callee);
+    callFrame->setScopeChain(callee->scope());
+    callFrame->setReturnPC(pc.value());
+
+    ASSERT((void*)callFrame <= stackFrame.registerFile->end());
+    return callFrame;
+}
+
+DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSFunction* callee = asFunction(callFrame->callee());
+    ASSERT(!callee->isHostFunction());
+    CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeForConstruct();
+    int argCount = callFrame->argumentCountIncludingThis();
+    ReturnAddressPtr pc = callFrame->returnPC();
+
+    ASSERT(argCount != newCodeBlock->m_numParameters);
+
+    CallFrame* oldCallFrame = callFrame->callerFrame();
+
+    Register* r;
+    if (argCount > newCodeBlock->m_numParameters) {
+        size_t numParameters = newCodeBlock->m_numParameters;
+        r = callFrame->registers() + numParameters;
+        Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
+        if (!stackFrame.registerFile->grow(newEnd)) {
+            // Rewind to the previous call frame because op_call already optimistically
+            // moved the call frame forward.
+            ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
+            STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+            return handler.callFrame;
+        }
+
+        Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
+        for (size_t i = 0; i < numParameters; ++i)
+            argv[i + argCount] = argv[i];
+    } else {
+        size_t omittedArgCount = newCodeBlock->m_numParameters - argCount;
+        r = callFrame->registers() + omittedArgCount;
+        Register* newEnd = r + newCodeBlock->m_numCalleeRegisters;
+        if (!stackFrame.registerFile->grow(newEnd)) {
+            // Rewind to the previous call frame because op_call already optimistically
+            // moved the call frame forward.
+            ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc);
+            STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+            return handler.callFrame;
+        }
 
-        callFrame = CallFrame::create(r);
-        callFrame->setCallerFrame(oldCallFrame);
+        Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
+        for (size_t i = 0; i < omittedArgCount; ++i)
+            argv[i] = jsUndefined();
     }
 
     ASSERT((void*)callFrame <= stackFrame.registerFile->end());
-    RETURN_POINTER_PAIR(callee, callFrame);
+    callFrame = CallFrame::create(r);
+    callFrame->setCallerFrame(oldCallFrame);
+    callFrame->setArgumentCountIncludingThis(argCount);
+    callFrame->setCallee(callee);
+    callFrame->setScopeChain(callee->scope());
+    callFrame->setReturnPC(pc.value());
+
+    ASSERT((void*)callFrame <= stackFrame.registerFile->end());
+    return callFrame;
 }
 
 #if ENABLE(JIT_OPTIMIZE_CALL)
 DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSFunction* callee = asFunction(callFrame->callee());
     ExecutableBase* executable = callee->executable();
-    JITCode& jitCode = executable->generatedJITCode();
-    
+
+    MacroAssemblerCodePtr codePtr;
+    CodeBlock* codeBlock = 0;
+    if (executable->isHostFunction())
+        codePtr = executable->generatedJITCodeForCall().addressForCall();
+    else {
+        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+        JSObject* error = functionExecutable->compileForCall(callFrame, callee->scope());
+        if (error) {
+            callFrame->globalData().exception = createStackOverflowError(callFrame);
+            return 0;
+        }
+        codeBlock = &functionExecutable->generatedBytecodeForCall();
+        if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
+            codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
+        else
+            codePtr = functionExecutable->generatedJITCodeForCallWithArityCheck();
+    }
+    CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
+
+    if (!callLinkInfo->seenOnce())
+        callLinkInfo->setSeen();
+    else
+        JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
+
+    return codePtr.executableAddress();
+}
+
+DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+    CallFrame* callFrame = stackFrame.callFrame;
+    JSFunction* callee = asFunction(callFrame->callee());
+    ExecutableBase* executable = callee->executable();
+
+    MacroAssemblerCodePtr codePtr;
     CodeBlock* codeBlock = 0;
-    if (!executable->isHostFunction())
-        codeBlock = &static_cast<FunctionExecutable*>(executable)->bytecode(stackFrame.callFrame, callee->scope().node());
-    CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
+    if (executable->isHostFunction())
+        codePtr = executable->generatedJITCodeForConstruct().addressForCall();
+    else {
+        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
+        JSObject* error = functionExecutable->compileForConstruct(callFrame, callee->scope());
+        if (error) {
+            throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS);
+            return 0;
+        }
+        codeBlock = &functionExecutable->generatedBytecodeForConstruct();
+        if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
+            codePtr = functionExecutable->generatedJITCodeForConstruct().addressForCall();
+        else
+            codePtr = functionExecutable->generatedJITCodeForConstructWithArityCheck();
+    }
+    CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(callFrame->returnPC());
 
     if (!callLinkInfo->seenOnce())
         callLinkInfo->setSeen();
     else
-        JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
+        JIT::linkConstruct(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, codePtr, callLinkInfo, callFrame->argumentCountIncludingThis(), stackFrame.globalData);
 
-    return jitCode.addressForCall().executableAddress();
+    return codePtr.executableAddress();
 }
 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
 
@@ -1924,7 +2159,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_push_activation)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     JSActivation* activation = new (stackFrame.globalData) JSActivation(stackFrame.callFrame, static_cast<FunctionExecutable*>(stackFrame.callFrame->codeBlock()->ownerExecutable()));
-    stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->copy()->push(activation));
+    stackFrame.callFrame->setScopeChain(stackFrame.callFrame->scopeChain()->push(activation));
     return activation;
 }
 
@@ -1935,7 +2170,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
     JSValue funcVal = stackFrame.args[0].jsValue();
 
     CallData callData;
-    CallType callType = funcVal.getCallData(callData);
+    CallType callType = getCallData(funcVal, callData);
 
     ASSERT(callType != CallTypeJS);
 
@@ -1944,55 +2179,43 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
         int argCount = stackFrame.args[2].int32();
         CallFrame* previousCallFrame = stackFrame.callFrame;
         CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
+        if (!stackFrame.registerFile->grow(callFrame->registers())) {
+            throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
+            VM_THROW_EXCEPTION();
+        }
 
-        callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, 0, argCount, 0);
-        stackFrame.callFrame = callFrame;
-
-        Register* argv = stackFrame.callFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
-        ArgList argList(argv + 1, argCount - 1);
+        callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(funcVal));
 
-        JSValue returnValue;
+        EncodedJSValue returnValue;
         {
             SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
-
-            // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
-            JSValue thisValue = argv[0].jsValue();
-            if (thisValue == jsNull())
-                thisValue = callFrame->globalThisValue();
-
-            returnValue = callData.native.function(callFrame, asObject(funcVal), thisValue, argList);
+            returnValue = callData.native.function(callFrame);
         }
-        stackFrame.callFrame = previousCallFrame;
-        CHECK_FOR_EXCEPTION();
 
-        return JSValue::encode(returnValue);
+        CHECK_FOR_EXCEPTION_AT_END();
+        return returnValue;
     }
 
     ASSERT(callType == CallTypeNone);
 
-    CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-    stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal, vPCIndex, codeBlock);
+    stackFrame.globalData->exception = createNotAFunctionError(stackFrame.callFrame, funcVal);
     VM_THROW_EXCEPTION();
 }
 
-DEFINE_STUB_FUNCTION(void, op_create_arguments)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame);
-    stackFrame.callFrame->setCalleeArguments(arguments);
-    stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments);
+    return JSValue::encode(JSValue(arguments));
 }
 
-DEFINE_STUB_FUNCTION(void, op_create_arguments_no_params)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_arguments_no_params)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     Arguments* arguments = new (stackFrame.globalData) Arguments(stackFrame.callFrame, Arguments::NoParameters);
-    stackFrame.callFrame->setCalleeArguments(arguments);
-    stackFrame.callFrame[RegisterFile::ArgumentsRegister] = JSValue(arguments);
+    return JSValue::encode(JSValue(arguments));
 }
 
 DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
@@ -2000,7 +2223,20 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_activation)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
-    asActivation(stackFrame.args[0].jsValue())->copyRegisters(stackFrame.callFrame->optionalCalleeArguments());
+    JSValue activationValue = stackFrame.args[0].jsValue();
+    if (!activationValue) {
+        if (JSValue v = stackFrame.args[1].jsValue()) {
+            if (!stackFrame.callFrame->codeBlock()->isStrictMode())
+                asArguments(v)->copyRegisters(*stackFrame.globalData);
+        }
+        return;
+    }
+    JSActivation* activation = asActivation(stackFrame.args[0].jsValue());
+    activation->copyRegisters(*stackFrame.globalData);
+    if (JSValue v = stackFrame.args[1].jsValue()) {
+        if (!stackFrame.callFrame->codeBlock()->isStrictMode())
+            asArguments(v)->setActivation(*stackFrame.globalData, activation);
+    }
 }
 
 DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
@@ -2008,8 +2244,7 @@ DEFINE_STUB_FUNCTION(void, op_tear_off_arguments)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     ASSERT(stackFrame.callFrame->codeBlock()->usesArguments() && !stackFrame.callFrame->codeBlock()->needsFullScopeChain());
-    if (stackFrame.callFrame->optionalCalleeArguments())
-        stackFrame.callFrame->optionalCalleeArguments()->copyRegisters();
+    asArguments(stackFrame.args[0].jsValue())->copyRegisters(*stackFrame.globalData);
 }
 
 DEFINE_STUB_FUNCTION(void, op_profile_will_call)
@@ -2028,19 +2263,19 @@ DEFINE_STUB_FUNCTION(void, op_profile_did_call)
     (*stackFrame.enabledProfilerReference)->didExecute(stackFrame.callFrame, stackFrame.args[0].jsValue());
 }
 
-DEFINE_STUB_FUNCTION(void, op_ret_scopeChain)
+DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain());
-    stackFrame.callFrame->scopeChain()->deref();
+    ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
+    return constructArray(stackFrame.callFrame, argList);
 }
 
-DEFINE_STUB_FUNCTION(JSObject*, op_new_array)
+DEFINE_STUB_FUNCTION(JSObject*, op_new_array_buffer)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
-    ArgList argList(&stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32());
+    
+    ArgList argList(stackFrame.callFrame->codeBlock()->constantBuffer(stackFrame.args[0].int32()), stackFrame.args[1].int32());
     return constructArray(stackFrame.callFrame, argList);
 }
 
@@ -2057,7 +2292,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
 
     Identifier& ident = stackFrame.args[0].identifier();
     do {
-        JSObject* o = *iter;
+        JSObject* o = iter->get();
         PropertySlot slot(o);
         if (o->getPropertySlot(callFrame, ident, slot)) {
             JSValue result = slot.getValue(callFrame, ident);
@@ -2066,69 +2301,46 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
         }
     } while (++iter != end);
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
     VM_THROW_EXCEPTION();
 }
 
-DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct)
-{
-    STUB_INIT_STACK_FRAME(stackFrame);
-
-    JSFunction* constructor = asFunction(stackFrame.args[0].jsValue());
-    if (constructor->isHostFunction()) {
-        CallFrame* callFrame = stackFrame.callFrame;
-        CodeBlock* codeBlock = callFrame->codeBlock();
-        unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-        stackFrame.globalData->exception = createNotAConstructorError(callFrame, constructor, vPCIndex, codeBlock);
-        VM_THROW_EXCEPTION();
-    }
-
-#if !ASSERT_DISABLED
-    ConstructData constructData;
-    ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);
-#endif
-
-    Structure* structure;
-    if (stackFrame.args[3].jsValue().isObject())
-        structure = asObject(stackFrame.args[3].jsValue())->inheritorID();
-    else
-        structure = constructor->scope().node()->globalObject->emptyObjectStructure();
-    return new (stackFrame.globalData) JSObject(structure);
-}
-
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    CallFrame* callFrame = stackFrame.callFrame;
-
     JSValue constrVal = stackFrame.args[0].jsValue();
-    int argCount = stackFrame.args[2].int32();
-    int thisRegister = stackFrame.args[4].int32();
 
     ConstructData constructData;
-    ConstructType constructType = constrVal.getConstructData(constructData);
+    ConstructType constructType = getConstructData(constrVal, constructData);
+
+    ASSERT(constructType != ConstructTypeJS);
 
     if (constructType == ConstructTypeHost) {
-        ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
+        int registerOffset = stackFrame.args[1].int32();
+        int argCount = stackFrame.args[2].int32();
+        CallFrame* previousCallFrame = stackFrame.callFrame;
+        CallFrame* callFrame = CallFrame::create(previousCallFrame->registers() + registerOffset);
+        if (!stackFrame.registerFile->grow(callFrame->registers())) {
+            throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
+            VM_THROW_EXCEPTION();
+        }
 
-        JSValue returnValue;
+        callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(constrVal));
+
+        EncodedJSValue returnValue;
         {
             SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
-            returnValue = constructData.native.function(callFrame, asObject(constrVal), argList);
+            returnValue = constructData.native.function(callFrame);
         }
-        CHECK_FOR_EXCEPTION();
 
-        return JSValue::encode(returnValue);
+        CHECK_FOR_EXCEPTION_AT_END();
+        return returnValue;
     }
 
     ASSERT(constructType == ConstructTypeNone);
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-    stackFrame.globalData->exception = createNotAConstructorError(callFrame, constrVal, vPCIndex, codeBlock);
+    stackFrame.globalData->exception = createNotAConstructorError(stackFrame.callFrame, constrVal);
     VM_THROW_EXCEPTION();
 }
 
@@ -2144,10 +2356,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val)
 
     if (LIKELY(baseValue.isCell() && subscript.isString())) {
         Identifier propertyName(callFrame, asString(subscript)->value(callFrame));
-        PropertySlot slot(asCell(baseValue));
+        PropertySlot slot(baseValue.asCell());
         // JSString::value may have thrown, but we shouldn't find a property with a null identifier,
         // so we should miss this case and wind up in the CHECK_FOR_EXCEPTION_AT_END, below.
-        if (asCell(baseValue)->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
+        if (baseValue.asCell()->fastGetOwnPropertySlot(callFrame, propertyName, slot)) {
             JSValue result = slot.getValue(callFrame, propertyName);
             CHECK_FOR_EXCEPTION();
             return JSValue::encode(result);
@@ -2249,10 +2461,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub)
     double left;
     double right;
     if (src1.getNumber(left) && src2.getNumber(right))
-        return JSValue::encode(jsNumber(stackFrame.globalData, left - right));
+        return JSValue::encode(jsNumber(left - right));
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+    JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2273,7 +2485,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
         if (isJSArray(globalData, baseValue)) {
             JSArray* jsArray = asArray(baseValue);
             if (jsArray->canSetIndex(i))
-                jsArray->setIndex(i, value);
+                jsArray->setIndex(*globalData, i, value);
             else
                 jsArray->JSArray::put(callFrame, i, value);
         } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
@@ -2297,7 +2509,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val)
     } else {
         Identifier property(callFrame, subscript.toString(callFrame));
         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
-            PutPropertySlot slot;
+            PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
             baseValue.put(callFrame, property, value, slot);
         }
     }
@@ -2340,7 +2552,7 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array)
     } else {
         Identifier property(callFrame, subscript.toString(callFrame));
         if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception.
-            PutPropertySlot slot;
+            PutPropertySlot slot(callFrame->codeBlock()->isStrictMode());
             baseValue.put(callFrame, property, value, slot);
         }
     }
@@ -2377,7 +2589,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
             stackFrame.globalData->exception = createStackOverflowError(callFrame);
             VM_THROW_EXCEPTION();
         }
-        int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
+        int32_t expectedParams = asFunction(callFrame->callee())->jsExecutable()->parameterCount();
         int32_t inplaceArgs = min(providedParams, expectedParams);
         
         Register* inplaceArgsDst = callFrame->registers() + argsOffset;
@@ -2398,12 +2610,10 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
 
     } else if (!arguments.isUndefinedOrNull()) {
         if (!arguments.isObject()) {
-            CodeBlock* codeBlock = callFrame->codeBlock();
-            unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-            stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
+            stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
             VM_THROW_EXCEPTION();
         }
-        if (asObject(arguments)->classInfo() == &Arguments::info) {
+        if (asObject(arguments)->classInfo() == &Arguments::s_info) {
             Arguments* argsObject = asArguments(arguments);
             argCount = argsObject->numProvidedArguments(callFrame);
             argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
@@ -2425,7 +2635,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
                 VM_THROW_EXCEPTION();
             }
             array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
-        } else if (asObject(arguments)->inherits(&JSArray::info)) {
+        } else if (asObject(arguments)->inherits(&JSArray::s_info)) {
             JSObject* argObject = asObject(arguments);
             argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
             argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments));
@@ -2441,9 +2651,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
                 CHECK_FOR_EXCEPTION();
             }
         } else {
-            CodeBlock* codeBlock = callFrame->codeBlock();
-            unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-            stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
+            stackFrame.globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments);
             VM_THROW_EXCEPTION();
         }
     }
@@ -2459,10 +2667,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
 
     double v;
     if (src.getNumber(v))
-        return JSValue::encode(jsNumber(stackFrame.globalData, -v));
+        return JSValue::encode(jsNumber(-v));
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, -src.toNumber(callFrame));
+    JSValue result = jsNumber(-src.toNumber(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2471,9 +2679,35 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain()));
+    return JSValue::encode(JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), false));
+}
+
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_base_strict_put)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+    JSValue base = JSC::resolveBase(stackFrame.callFrame, stackFrame.args[0].identifier(), stackFrame.callFrame->scopeChain(), true);
+    if (!base) {
+        stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[0].identifier().ustring());
+        VM_THROW_EXCEPTION();
+    }
+    return JSValue::encode(base);
 }
 
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_ensure_property_exists)
+{
+    STUB_INIT_STACK_FRAME(stackFrame);
+    JSValue base = stackFrame.callFrame->r(stackFrame.args[0].int32()).jsValue();
+    JSObject* object = asObject(base);
+    PropertySlot slot(object);
+    ASSERT(stackFrame.callFrame->codeBlock()->isStrictMode());
+    if (!object->getPropertySlot(stackFrame.callFrame, stackFrame.args[1].identifier(), slot)) {
+        stackFrame.globalData->exception = createErrorForInvalidGlobalAssignment(stackFrame.callFrame, stackFrame.args[1].identifier().ustring());
+        VM_THROW_EXCEPTION();
+    }
+
+    return JSValue::encode(base);
+}
+    
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
@@ -2486,13 +2720,20 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
     ScopeChainIterator iter = scopeChain->begin();
     ScopeChainIterator end = scopeChain->end();
     ASSERT(iter != end);
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain();
+    ASSERT(skip || !checkTopLevel);
+    if (checkTopLevel && skip--) {
+        if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue())
+            ++iter;
+    }
     while (skip--) {
         ++iter;
         ASSERT(iter != end);
     }
     Identifier& ident = stackFrame.args[0].identifier();
     do {
-        JSObject* o = *iter;
+        JSObject* o = iter->get();
         PropertySlot slot(o);
         if (o->getPropertySlot(callFrame, ident, slot)) {
             JSValue result = slot.getValue(callFrame, ident);
@@ -2501,9 +2742,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_skip)
         }
     } while (++iter != end);
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
     VM_THROW_EXCEPTION();
 }
 
@@ -2512,20 +2751,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSGlobalObject* globalObject = stackFrame.args[0].globalObject();
-    Identifier& ident = stackFrame.args[1].identifier();
-    unsigned globalResolveInfoIndex = stackFrame.args[2].int32();
+    CodeBlock* codeBlock = callFrame->codeBlock();
+    JSGlobalObject* globalObject = codeBlock->globalObject();
+    Identifier& ident = stackFrame.args[0].identifier();
+    unsigned globalResolveInfoIndex = stackFrame.args[1].int32();
     ASSERT(globalObject->isGlobalObject());
 
     PropertySlot slot(globalObject);
     if (globalObject->getPropertySlot(callFrame, ident, slot)) {
         JSValue result = slot.getValue(callFrame, ident);
         if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
-            GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
-            if (globalResolveInfo.structure)
-                globalResolveInfo.structure->deref();
-            globalObject->structure()->ref();
-            globalResolveInfo.structure = globalObject->structure();
+            GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfo(globalResolveInfoIndex);
+            globalResolveInfo.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), globalObject->structure());
             globalResolveInfo.offset = slot.cachedOffset();
             return JSValue::encode(result);
         }
@@ -2534,8 +2771,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
         return JSValue::encode(result);
     }
 
-    unsigned vPCIndex = callFrame->codeBlock()->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, callFrame->codeBlock());
+    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
     VM_THROW_EXCEPTION();
 }
 
@@ -2549,10 +2785,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
     double left;
     double right;
     if (src1.getNumber(left) && src2.getNumber(right))
-        return JSValue::encode(jsNumber(stackFrame.globalData, left / right));
+        return JSValue::encode(jsNumber(left / right));
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, src1.toNumber(callFrame) / src2.toNumber(callFrame));
+    JSValue result = jsNumber(src1.toNumber(callFrame) / src2.toNumber(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2564,7 +2800,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_dec)
     JSValue v = stackFrame.args[0].jsValue();
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, v.toNumber(callFrame) - 1);
+    JSValue result = jsNumber(v.toNumber(callFrame) - 1);
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2632,7 +2868,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc)
     JSValue number = v.toJSNumber(callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
 
-    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() + 1);
+    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() + 1);
     return JSValue::encode(number);
 }
 
@@ -2647,14 +2883,14 @@ DEFINE_STUB_FUNCTION(int, op_eq)
     start:
     if (src2.isUndefined()) {
         return src1.isNull() || 
-               (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) ||
-               src1.isUndefined();
+               (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
+               || src1.isUndefined();
     }
     
     if (src2.isNull()) {
         return src1.isUndefined() || 
-               (src1.isCell() && asCell(src1)->structure()->typeInfo().masqueradesAsUndefined()) ||
-               src1.isNull();
+               (src1.isCell() && src1.asCell()->structure()->typeInfo().masqueradesAsUndefined())
+               || src1.isNull();
     }
 
     if (src1.isInt32()) {
@@ -2690,27 +2926,27 @@ DEFINE_STUB_FUNCTION(int, op_eq)
     }
     
     if (src1.isUndefined())
-        return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
+        return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
     
     if (src1.isNull())
-        return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
+        return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
 
-    JSCell* cell1 = asCell(src1);
+    JSCell* cell1 = src1.asCell();
 
     if (cell1->isString()) {
         if (src2.isInt32())
-            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asInt32();
+            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32();
             
         if (src2.isDouble())
-            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asDouble();
+            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble();
 
         if (src2.isTrue())
-            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 1.0;
+            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0;
 
         if (src2.isFalse())
-            return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 0.0;
+            return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0;
 
-        JSCell* cell2 = asCell(src2);
+        JSCell* cell2 = src2.asCell();
         if (cell2->isString())
             return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame);
 
@@ -2760,7 +2996,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift)
     JSValue shift = stackFrame.args[1].jsValue();
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
+    JSValue result = jsNumber((val.toInt32(callFrame)) << (shift.toUInt32(callFrame) & 0x1f));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2774,7 +3010,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitand)
 
     ASSERT(!src1.isInt32() || !src2.isInt32());
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+    JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2787,7 +3023,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_rshift)
     JSValue shift = stackFrame.args[1].jsValue();
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, (val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+    JSValue result = jsNumber((val.toInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
 
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
@@ -2801,7 +3037,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitnot)
 
     ASSERT(!src.isInt32());
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, ~src.toInt32(callFrame));
+    JSValue result = jsNumber(~src.toInt32(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2823,7 +3059,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
     Identifier& ident = stackFrame.args[0].identifier();
     JSObject* base;
     do {
-        base = *iter;
+        base = iter->get();
         PropertySlot slot(base);
         if (base->getPropertySlot(callFrame, ident, slot)) {
             JSValue result = slot.getValue(callFrame, ident);
@@ -2835,9 +3071,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_with_base)
         ++iter;
     } while (iter != end);
 
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock);
+    stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident);
     VM_THROW_EXCEPTION_AT_END();
     return JSValue::encode(JSValue());
 }
@@ -2849,6 +3083,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
 
     FunctionExecutable* function = stackFrame.args[0].function();
     JSFunction* func = function->make(callFrame, callFrame->scopeChain());
+    ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->uncheckedR(callFrame->codeBlock()->activationRegister()).jsValue());
 
     /* 
         The Identifier in a FunctionExpression can be referenced from inside
@@ -2859,7 +3094,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func_exp)
      */
     if (!function->name().isNull()) {
         JSStaticScopeObject* functionScopeObject = new (callFrame) JSStaticScopeObject(callFrame, function->name(), func, ReadOnly | DontDelete);
-        func->scope().push(functionScopeObject);
+        func->setScope(callFrame->globalData(), func->scope()->push(functionScopeObject));
     }
 
     return func;
@@ -2874,7 +3109,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
 
     CallFrame* callFrame = stackFrame.callFrame;
     double d = dividendValue.toNumber(callFrame);
-    JSValue result = jsNumber(stackFrame.globalData, fmod(d, divisorValue.toNumber(callFrame)));
+    JSValue result = jsNumber(fmod(d, divisorValue.toNumber(callFrame)));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2900,7 +3135,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_dec)
     JSValue number = v.toJSNumber(callFrame);
     CHECK_FOR_EXCEPTION_AT_END();
 
-    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(stackFrame.globalData, number.uncheckedGetNumber() - 1);
+    callFrame->registers()[stackFrame.args[1].int32()] = jsNumber(number.uncheckedGetNumber() - 1);
     return JSValue::encode(number);
 }
 
@@ -2912,7 +3147,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_urshift)
     JSValue shift = stackFrame.args[1].jsValue();
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSValue result = jsNumber(stackFrame.globalData, (val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
+    JSValue result = jsNumber((val.toUInt32(callFrame)) >> (shift.toUInt32(callFrame) & 0x1f));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2926,7 +3161,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+    JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2935,7 +3170,15 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp());
+    CallFrame* callFrame = stackFrame.callFrame;
+
+    RegExp* regExp = stackFrame.args[0].regExp();
+    if (!regExp->isValid()) {
+        stackFrame.globalData->exception = createSyntaxError(callFrame, "Invalid flags supplied to RegExp constructor.");
+        VM_THROW_EXCEPTION();
+    }
+
+    return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject(), stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), regExp);
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
@@ -2947,7 +3190,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
-    JSValue result = jsNumber(stackFrame.globalData, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+    JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2955,6 +3198,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
+    ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->uncheckedR(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue());
 
     CallFrame* callFrame = stackFrame.callFrame;
     RegisterFile* registerFile = stackFrame.registerFile;
@@ -2967,47 +3211,24 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval)
 
     Register* newCallFrame = callFrame->registers() + registerOffset;
     Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
-    JSValue thisValue = argv[0].jsValue();
-    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
-
-    if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
-        JSValue exceptionValue;
-        JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
-        if (UNLIKELY(exceptionValue)) {
-            stackFrame.globalData->exception = exceptionValue;
-            VM_THROW_EXCEPTION_AT_END();
-        }
+    JSValue baseValue = argv[0].jsValue();
+    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject.get();
+
+    if (baseValue == globalObject && funcVal == globalObject->evalFunction()) {
+        JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset);
+        CHECK_FOR_EXCEPTION_AT_END();
         return JSValue::encode(result);
     }
 
     return JSValue::encode(JSValue());
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw)
+DEFINE_STUB_FUNCTION(void*, op_throw)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
-    CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* codeBlock = callFrame->codeBlock();
-
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-
-    JSValue exceptionValue = stackFrame.args[0].jsValue();
-    ASSERT(exceptionValue);
-
-    HandlerInfo* handler = stackFrame.globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
-
-    if (!handler) {
-        *stackFrame.exception = exceptionValue;
-        STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value());
-        return JSValue::encode(jsNull());
-    }
-
-    stackFrame.callFrame = callFrame;
-    void* catchRoutine = handler->nativeCode.executableAddress();
-    ASSERT(catchRoutine);
-    STUB_SET_RETURN_ADDRESS(catchRoutine);
-    return JSValue::encode(exceptionValue);
+    ExceptionHandler handler = jitThrow(stackFrame.globalData, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS);
+    STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+    return handler.callFrame;
 }
 
 DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
@@ -3161,10 +3382,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_in)
     JSValue baseVal = stackFrame.args[1].jsValue();
 
     if (!baseVal.isObject()) {
-        CallFrame* callFrame = stackFrame.callFrame;
-        CodeBlock* codeBlock = callFrame->codeBlock();
-        unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
-        stackFrame.globalData->exception = createInvalidParamError(callFrame, "in", baseVal, vPCIndex, codeBlock);
+        stackFrame.globalData->exception = createInvalidParamError(stackFrame.callFrame, "in", baseVal);
         VM_THROW_EXCEPTION();
     }
 
@@ -3247,7 +3465,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_char)
     void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
-        UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
+        StringImpl* value = asString(scrutinee)->value(callFrame).impl();
         if (value->length() == 1)
             result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->characters()[0]).executableAddress();
     }
@@ -3268,7 +3486,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_string)
     void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
-        UString::Rep* value = asString(scrutinee)->value(callFrame).rep();
+        StringImpl* value = asString(scrutinee)->value(callFrame).impl();
         result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress();
     }
 
@@ -3286,19 +3504,22 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_val)
     JSObject* baseObj = baseValue.toObject(callFrame); // may throw
 
     JSValue subscript = stackFrame.args[1].jsValue();
-    JSValue result;
+    bool result;
     uint32_t i;
     if (subscript.getUInt32(i))
-        result = jsBoolean(baseObj->deleteProperty(callFrame, i));
+        result = baseObj->deleteProperty(callFrame, i);
     else {
         CHECK_FOR_EXCEPTION();
         Identifier property(callFrame, subscript.toString(callFrame));
         CHECK_FOR_EXCEPTION();
-        result = jsBoolean(baseObj->deleteProperty(callFrame, property));
+        result = baseObj->deleteProperty(callFrame, property);
     }
 
+    if (!result && callFrame->codeBlock()->isStrictMode())
+        stackFrame.globalData->exception = createTypeError(stackFrame.callFrame, "Unable to delete property.");
+
     CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
+    return JSValue::encode(jsBoolean(result));
 }
 
 DEFINE_STUB_FUNCTION(void, op_put_getter)
@@ -3325,18 +3546,14 @@ DEFINE_STUB_FUNCTION(void, op_put_setter)
     baseObj->defineSetter(callFrame, stackFrame.args[1].identifier(), asObject(stackFrame.args[2].jsValue()));
 }
 
-DEFINE_STUB_FUNCTION(JSObject*, op_new_error)
+DEFINE_STUB_FUNCTION(void, op_throw_reference_error)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* codeBlock = callFrame->codeBlock();
-    unsigned type = stackFrame.args[0].int32();
-    JSValue message = stackFrame.args[1].jsValue();
-    unsigned bytecodeOffset = stackFrame.args[2].int32();
-
-    unsigned lineNumber = codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
-    return Error::create(callFrame, static_cast<ErrorType>(type), message.toString(callFrame), lineNumber, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
+    UString message = stackFrame.args[0].jsValue().toString(callFrame);
+    stackFrame.globalData->exception = createReferenceError(callFrame, message);
+    VM_THROW_EXCEPTION_AT_END();
 }
 
 DEFINE_STUB_FUNCTION(void, op_debug)
@@ -3352,32 +3569,13 @@ DEFINE_STUB_FUNCTION(void, op_debug)
     stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
 }
 
-DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw)
+DEFINE_STUB_FUNCTION(void*, vm_throw)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
-    CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* codeBlock = callFrame->codeBlock();
     JSGlobalData* globalData = stackFrame.globalData;
-
-    unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, globalData->exceptionLocation);
-
-    JSValue exceptionValue = globalData->exception;
-    ASSERT(exceptionValue);
-    globalData->exception = JSValue();
-
-    HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
-
-    if (!handler) {
-        *stackFrame.exception = exceptionValue;
-        return JSValue::encode(jsNull());
-    }
-
-    stackFrame.callFrame = callFrame;
-    void* catchRoutine = handler->nativeCode.executableAddress();
-    ASSERT(catchRoutine);
-    STUB_SET_RETURN_ADDRESS(catchRoutine);
-    return JSValue::encode(exceptionValue);
+    ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception, globalData->exceptionLocation);
+    STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+    return handler.callFrame;
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
@@ -3388,15 +3586,37 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
     return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame));
 }
 
-NativeExecutable* JITThunks::specializedThunk(JSGlobalData* globalData, ThunkGenerator generator)
+MacroAssemblerCodePtr JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerator generator)
+{
+    std::pair<CTIStubMap::iterator, bool> entry = m_ctiStubMap.add(generator, MacroAssemblerCodePtr());
+    if (entry.second)
+        entry.first->second = generator(globalData, m_executablePool.get());
+    return entry.first->second;
+}
+
+NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function)
 {
-    std::pair<ThunkMap::iterator, bool> entry = m_thunkMap.add(generator, 0);
-    if (!entry.second)
-        return entry.first->second.get();
-    entry.first->second = generator(globalData, m_executablePool.get());
+    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Weak<NativeExecutable>());
+    if (!*entry.first->second)
+        entry.first->second.set(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, m_executablePool, function), function, ctiNativeConstruct(), callHostFunctionAsConstructor));
     return entry.first->second.get();
 }
 
+NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator)
+{
+    std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, Weak<NativeExecutable>());
+    if (!*entry.first->second) {
+        MacroAssemblerCodePtr code = globalData->canUseJIT() ? generator(globalData, m_executablePool.get()) : MacroAssemblerCodePtr();
+        entry.first->second.set(*globalData, NativeExecutable::create(*globalData, code, function, ctiNativeConstruct(), callHostFunctionAsConstructor));
+    }
+    return entry.first->second.get();
+}
+
+void JITThunks::clearHostFunctionStubs()
+{
+    m_hostFunctionStubMap.clear();
+}
+
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index 0ad9a99979a2be4d37a89af523efa2b9aff4cc39..75fbb089ec9388be1c2022208f3a517109a39011 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,6 +30,7 @@
 #ifndef JITStubs_h
 #define JITStubs_h
 
+#include "CallData.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Register.h"
 #include "ThunkGenerators.h"
@@ -57,6 +59,8 @@ namespace JSC {
     class RegisterFile;
     class RegExp;
 
+    template <typename T> class Weak;
+
     union JITStubArg {
         void* asPointer;
         EncodedJSValue asEncodedJSValue;
@@ -78,8 +82,11 @@ namespace JSC {
     struct TrampolineStructure {
         MacroAssemblerCodePtr ctiStringLengthTrampoline;
         MacroAssemblerCodePtr ctiVirtualCallLink;
+        MacroAssemblerCodePtr ctiVirtualConstructLink;
         MacroAssemblerCodePtr ctiVirtualCall;
-        RefPtr<NativeExecutable> ctiNativeCallThunk;
+        MacroAssemblerCodePtr ctiVirtualConstruct;
+        MacroAssemblerCodePtr ctiNativeCall;
+        MacroAssemblerCodePtr ctiNativeConstruct;
         MacroAssemblerCodePtr ctiSoftModulo;
     };
 
@@ -92,7 +99,7 @@ namespace JSC {
         void* code;
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
 
@@ -128,7 +135,7 @@ namespace JSC {
         void* code;
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
         
@@ -140,10 +147,10 @@ namespace JSC {
 #endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC))
 #elif CPU(ARM_THUMB2)
     struct JITStackFrame {
-        void* reserved; // Unused
+        JITStubArg reserved; // Unused
         JITStubArg args[6];
-#if USE(JSVALUE32_64)
-        void* padding[2]; // Maintain 16-byte stack alignment.
+#if USE(JSVALUE64)
+        void* padding; // Maintain 16-byte stack alignment.
 #endif
 
         ReturnAddressPtr thunkReturnAddress;
@@ -156,9 +163,7 @@ namespace JSC {
         // These arguments passed in r1..r3 (r0 contained the entry code pointed, which is not preserved)
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
-
-        void* padding2;
+        void* unused1;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
@@ -167,6 +172,10 @@ namespace JSC {
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
 #elif CPU(ARM_TRADITIONAL)
+#if COMPILER(MSVC)
+#pragma pack(push)
+#pragma pack(4)
+#endif // COMPILER(MSVC)
     struct JITStackFrame {
         JITStubArg padding; // Unused
         JITStubArg args[7];
@@ -182,7 +191,7 @@ namespace JSC {
 
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
@@ -191,11 +200,18 @@ namespace JSC {
         // When JIT code makes a call, it pushes its return address just below the rest of the stack.
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
+#if COMPILER(MSVC)
+#pragma pack(pop)
+#endif // COMPILER(MSVC)
 #elif CPU(MIPS)
     struct JITStackFrame {
-        void* reserved; // Unused
+        JITStubArg reserved; // Unused
         JITStubArg args[6];
 
+#if USE(JSVALUE32_64)
+        void* padding; // Make the overall stack length 8-byte aligned.
+#endif
+
         void* preservedGP; // store GP when using PIC code
         void* preservedS0;
         void* preservedS1;
@@ -207,12 +223,33 @@ namespace JSC {
         // These arguments passed in a1..a3 (a0 contained the entry code pointed, which is not preserved)
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
 
+        ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
+    };
+#elif CPU(SH4)
+    struct JITStackFrame {
+        JITStubArg padding; // Unused
+        JITStubArg args[6];
+
+        ReturnAddressPtr thunkReturnAddress;
+        void* savedR10;
+        void* savedR11;
+        void* savedR13;
+        void* savedRPR;
+        void* savedR14;
+        void* savedTimeoutReg;
+
+        RegisterFile* registerFile;
+        CallFrame* callFrame;
+        JSValue* exception;
+        Profiler** enabledProfilerReference;
+        JSGlobalData* globalData;
+
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
 #else
@@ -221,48 +258,24 @@ namespace JSC {
 
 #define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*))
 
-#if USE(JIT_STUB_ARGUMENT_VA_LIST)
-    #define STUB_ARGS_DECLARATION void* args, ...
-    #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1)
+#define STUB_ARGS_DECLARATION void** args
+#define STUB_ARGS (args)
 
+#if CPU(X86)
     #if COMPILER(MSVC)
-    #define JIT_STUB __cdecl
-    #else
-    #define JIT_STUB
-    #endif
-#else
-    #define STUB_ARGS_DECLARATION void** args
-    #define STUB_ARGS (args)
-
-    #if CPU(X86) && COMPILER(MSVC)
     #define JIT_STUB __fastcall
-    #elif CPU(X86) && COMPILER(GCC)
+    #elif COMPILER(GCC)
     #define JIT_STUB  __attribute__ ((fastcall))
     #else
-    #define JIT_STUB
+    #error "JIT_STUB function calls require fastcall conventions on x86, add appropriate directive/attribute here for your compiler!"
     #endif
-#endif
-
-#if CPU(X86_64)
-    struct VoidPtrPair {
-        void* first;
-        void* second;
-    };
-    #define RETURN_POINTER_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair
 #else
-    // MSVC doesn't support returning a two-value struct in two registers, so
-    // we cast the struct to int64_t instead.
-    typedef uint64_t VoidPtrPair;
-    union VoidPtrPairUnion {
-        struct { void* first; void* second; } s;
-        VoidPtrPair i;
-    };
-    #define RETURN_POINTER_PAIR(a,b) VoidPtrPairUnion pair = {{ a, b }}; return pair.i
+    #define JIT_STUB
 #endif
 
     extern "C" void ctiVMThrowTrampoline();
     extern "C" void ctiOpThrowNotCaught();
-    extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*);
+    extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
 
     class JITThunks {
     public:
@@ -274,14 +287,25 @@ namespace JSC {
 
         MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; }
         MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; }
+        MacroAssemblerCodePtr ctiVirtualConstructLink() { return m_trampolineStructure.ctiVirtualConstructLink; }
         MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
-        NativeExecutable* ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk.get(); }
+        MacroAssemblerCodePtr ctiVirtualConstruct() { return m_trampolineStructure.ctiVirtualConstruct; }
+        MacroAssemblerCodePtr ctiNativeCall() { return m_trampolineStructure.ctiNativeCall; }
+        MacroAssemblerCodePtr ctiNativeConstruct() { return m_trampolineStructure.ctiNativeConstruct; }
         MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; }
 
-        NativeExecutable* specializedThunk(JSGlobalData* globalData, ThunkGenerator generator);
+        MacroAssemblerCodePtr ctiStub(JSGlobalData* globalData, ThunkGenerator generator);
+
+        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction);
+        NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator);
+
+        void clearHostFunctionStubs();
+
     private:
-        typedef HashMap<ThunkGenerator, RefPtr<NativeExecutable> > ThunkMap;
-        ThunkMap m_thunkMap;
+        typedef HashMap<ThunkGenerator, MacroAssemblerCodePtr> CTIStubMap;
+        CTIStubMap m_ctiStubMap;
+        typedef HashMap<NativeFunction, Weak<NativeExecutable> > HostFunctionStubMap;
+        OwnPtr<HostFunctionStubMap> m_hostFunctionStubMap;
         RefPtr<ExecutablePool> m_executablePool;
 
         TrampolineStructure m_trampolineStructure;
@@ -296,16 +320,20 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_convert_this_strict(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_div(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_getter_stub(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION);
@@ -336,6 +364,8 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_resolve_base_strict_put(STUB_ARGS_DECLARATION);
+    EncodedJSValue JIT_STUB cti_op_ensure_property_exists(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_resolve_global_dynamic(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION);
@@ -344,16 +374,13 @@ extern "C" {
     EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
-    EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
     EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION);
-    JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
-    JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
+    JSObject* JIT_STUB cti_op_new_array_buffer(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION);
@@ -363,7 +390,6 @@ extern "C" {
     JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION);
     JSObject* JIT_STUB cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION);
     JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION);
-    VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION);
@@ -373,8 +399,7 @@ extern "C" {
     int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
     int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
+    void JIT_STUB cti_op_check_has_instance(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION);
@@ -392,15 +417,21 @@ extern "C" {
     void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION);
     void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION);
-    void JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
-    void* JIT_STUB cti_op_call_JSFunction(STUB_ARGS_DECLARATION);
+    void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_op_construct_jitCompile(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
     void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION);
+    void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
 } // extern "C"
 
 } // namespace JSC
diff --git a/jit/JITWriteBarrier.h b/jit/JITWriteBarrier.h
new file mode 100644 (file)
index 0000000..10e0710
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 JITWriteBarrier_h
+#define JITWriteBarrier_h
+
+#if ENABLE(JIT)
+
+#include "MacroAssembler.h"
+#include "MarkStack.h"
+#include "WriteBarrier.h"
+
+namespace JSC {
+
+class JSCell;
+class JSGlobalData;
+
+// Needs to be even to appease some of the backends.
+#define JITWriteBarrierFlag ((void*)2)
+class JITWriteBarrierBase {
+public:
+    typedef void* (JITWriteBarrierBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    bool operator!() const { return !get(); }
+
+    void setFlagOnBarrier()
+    {
+        ASSERT(!m_location);
+        m_location = CodeLocationDataLabelPtr(JITWriteBarrierFlag);
+    }
+
+    bool isFlagged() const
+    {
+        return !!m_location;
+    }
+
+    void setLocation(CodeLocationDataLabelPtr location)
+    {
+        ASSERT(!m_location);
+        m_location = location;
+    }
+
+    CodeLocationDataLabelPtr location() const
+    {
+        ASSERT((!!m_location) && m_location.executableAddress() != JITWriteBarrierFlag);
+        return m_location;
+    }
+    
+    void clear() { clear(0); }
+
+protected:
+    JITWriteBarrierBase()
+    {
+    }
+
+    void set(JSGlobalData&, CodeLocationDataLabelPtr location, JSCell* owner, JSCell* value)
+    {
+        Heap::writeBarrier(owner, value);
+        m_location = location;
+        ASSERT(((!!m_location) && m_location.executableAddress() != JITWriteBarrierFlag) || (location.executableAddress() == m_location.executableAddress()));
+        MacroAssembler::repatchPointer(m_location, value);
+        ASSERT(get() == value);
+    }
+
+    JSCell* get() const
+    {
+        if (!m_location || m_location.executableAddress() == JITWriteBarrierFlag)
+            return 0;
+        void* result = static_cast<JSCell*>(MacroAssembler::readPointer(m_location));
+        // We use -1 to indicate a "safe" empty value in the instruction stream
+        if (result == (void*)-1)
+            return 0;
+        return static_cast<JSCell*>(result);
+    }
+
+private:
+    void clear(void* clearedValue)
+    {
+        if (!m_location)
+            return;
+        if (m_location.executableAddress() != JITWriteBarrierFlag)
+            MacroAssembler::repatchPointer(m_location, clearedValue);
+    }
+
+    CodeLocationDataLabelPtr m_location;
+};
+
+#undef JITWriteBarrierFlag
+
+template <typename T> class JITWriteBarrier : public JITWriteBarrierBase {
+public:
+    JITWriteBarrier()
+    {
+    }
+
+    void set(JSGlobalData& globalData, CodeLocationDataLabelPtr location, JSCell* owner, T* value)
+    {
+        validateCell(owner);
+        validateCell(value);
+        JITWriteBarrierBase::set(globalData, location, owner, value);
+    }
+    T* get() const
+    {
+        T* result = static_cast<T*>(JITWriteBarrierBase::get());
+        if (result)
+            validateCell(result);
+        return result;
+    }
+};
+
+template<typename T> inline void MarkStack::append(JITWriteBarrier<T>* slot)
+{
+    internalAppend(slot->get());
+}
+
+}
+
+#endif // ENABLE(JIT)
+
+#endif
index f34800a96ecd257dd3b641d89229efbc64f77899..e1d9353cbb6f2b68db03a7ca6a544aff220c5eb8 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "JITCode.h"
 #include "JITStubs.h"
-#include "JSImmediate.h"
+#include "JSValue.h"
 #include "MacroAssembler.h"
 #include "RegisterFile.h"
 #include <wtf/AlwaysInline.h>
@@ -152,32 +152,71 @@ namespace JSC {
         static const FPRegisterID fpRegT0 = MIPSRegisters::f4;
         static const FPRegisterID fpRegT1 = MIPSRegisters::f6;
         static const FPRegisterID fpRegT2 = MIPSRegisters::f8;
-        static const FPRegisterID fpRegT2 = MIPSRegisters::f10;
+        static const FPRegisterID fpRegT3 = MIPSRegisters::f10;
+#elif CPU(SH4)
+        static const RegisterID timeoutCheckRegister = SH4Registers::r8;
+        static const RegisterID callFrameRegister = SH4Registers::fp;
+
+        static const RegisterID regT0 = SH4Registers::r0;
+        static const RegisterID regT1 = SH4Registers::r1;
+        static const RegisterID regT2 = SH4Registers::r2;
+        static const RegisterID regT3 = SH4Registers::r10;
+        static const RegisterID regT4 = SH4Registers::r4;
+        static const RegisterID regT5 = SH4Registers::r5;
+        static const RegisterID regT6 = SH4Registers::r6;
+        static const RegisterID regT7 = SH4Registers::r7;
+        static const RegisterID firstArgumentRegister =regT4;
+
+        static const RegisterID returnValueRegister = SH4Registers::r0;
+        static const RegisterID cachedResultRegister = SH4Registers::r0;
+
+        static const FPRegisterID fpRegT0  = SH4Registers::fr0;
+        static const FPRegisterID fpRegT1  = SH4Registers::fr2;
+        static const FPRegisterID fpRegT2  = SH4Registers::fr4;
+        static const FPRegisterID fpRegT3  = SH4Registers::fr6;
+        static const FPRegisterID fpRegT4  = SH4Registers::fr8;
+        static const FPRegisterID fpRegT5  = SH4Registers::fr10;
+        static const FPRegisterID fpRegT6  = SH4Registers::fr12;
+        static const FPRegisterID fpRegT7  = SH4Registers::fr14;
 #else
 #error "JIT not supported on this platform."
 #endif
 
+#if USE(JSVALUE32_64)
+        // Can't just propogate JSValue::Int32Tag as visual studio doesn't like it
+        static const unsigned Int32Tag = 0xffffffff;
+        COMPILE_ASSERT(Int32Tag == JSValue::Int32Tag, Int32Tag_out_of_sync);
+#else
+        static const unsigned Int32Tag = TagTypeNumber >> 32;
+#endif
         inline Jump emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID payload);
         inline Jump emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst);
         inline Jump emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch);
 
+        inline void storePtrWithWriteBarrier(TrustedImmPtr ptr, RegisterID /* owner */, Address dest)
+        {
+            storePtr(ptr, dest);
+        }
+
 #if USE(JSVALUE32_64)
         inline Jump emitJumpIfNotJSCell(unsigned virtualRegisterIndex);
-        inline Address tagFor(unsigned index, RegisterID base = callFrameRegister);
+        inline Address tagFor(int index, RegisterID base = callFrameRegister);
 #endif
 
-#if USE(JSVALUE32) || USE(JSVALUE64)
+#if USE(JSVALUE64)
         Jump emitJumpIfImmediateNumber(RegisterID reg);
         Jump emitJumpIfNotImmediateNumber(RegisterID reg);
         void emitFastArithImmToInt(RegisterID reg);
 #endif
 
-        inline Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
-        inline Address addressFor(unsigned index, RegisterID base = callFrameRegister);
+        inline Address payloadFor(int index, RegisterID base = callFrameRegister);
+        inline Address intPayloadFor(int index, RegisterID base = callFrameRegister);
+        inline Address intTagFor(int index, RegisterID base = callFrameRegister);
+        inline Address addressFor(int index, RegisterID base = callFrameRegister);
     };
 
     struct ThunkHelpers {
-        static unsigned stringImplDataOffset() { return WebCore::StringImpl::dataOffset(); }
+        static unsigned stringImplDataOffset() { return StringImpl::dataOffset(); }
         static unsigned jsStringLengthOffset() { return OBJECT_OFFSETOF(JSString, m_length); }
         static unsigned jsStringValueOffset() { return OBJECT_OFFSETOF(JSString, m_value); }
     };
@@ -192,34 +231,44 @@ namespace JSC {
     inline JSInterfaceJIT::Jump JSInterfaceJIT::emitJumpIfNotJSCell(unsigned virtualRegisterIndex)
     {
         ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
-        return branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::CellTag));
+        return branch32(NotEqual, tagFor(virtualRegisterIndex), TrustedImm32(JSValue::CellTag));
     }
     
     inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
     {
         ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
         loadPtr(payloadFor(virtualRegisterIndex), dst);
-        return branch32(NotEqual, tagFor(virtualRegisterIndex), Imm32(JSValue::Int32Tag));
+        return branch32(NotEqual, tagFor(static_cast<int>(virtualRegisterIndex)), TrustedImm32(JSValue::Int32Tag));
     }
     
-    inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(unsigned virtualRegisterIndex, RegisterID base)
+    inline JSInterfaceJIT::Address JSInterfaceJIT::tagFor(int virtualRegisterIndex, RegisterID base)
     {
-        ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
-        return Address(base, (virtualRegisterIndex * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
+        ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
+        return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.tag));
     }
     
-    inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned virtualRegisterIndex, RegisterID base)
+    inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
     {
-        ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
-        return Address(base, (virtualRegisterIndex * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
+        ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
+        return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(JSValue, u.asBits.payload));
+    }
+
+    inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
+    {
+        return payloadFor(virtualRegisterIndex, base);
+    }
+
+    inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
+    {
+        return tagFor(virtualRegisterIndex, base);
     }
 
     inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned virtualRegisterIndex, FPRegisterID dst, RegisterID scratch)
     {
         ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
         loadPtr(tagFor(virtualRegisterIndex), scratch);
-        Jump isDouble = branch32(Below, scratch, Imm32(JSValue::LowestTag));
-        Jump notInt = branch32(NotEqual, scratch, Imm32(JSValue::Int32Tag));
+        Jump isDouble = branch32(Below, scratch, TrustedImm32(JSValue::LowestTag));
+        Jump notInt = branch32(NotEqual, scratch, TrustedImm32(JSValue::Int32Tag));
         loadPtr(payloadFor(virtualRegisterIndex), scratch);
         convertInt32ToDouble(scratch, dst);
         Jump done = jump();
@@ -273,46 +322,29 @@ namespace JSC {
     
 #endif
 
-#if USE(JSVALUE32)
-    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadJSCell(unsigned virtualRegisterIndex, RegisterID dst)
-    {
-        loadPtr(addressFor(virtualRegisterIndex), dst);
-        return branchTest32(NonZero, dst, Imm32(JSImmediate::TagMask));
-    }
-
-    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadInt32(unsigned virtualRegisterIndex, RegisterID dst)
+#if USE(JSVALUE64)
+    inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(int virtualRegisterIndex, RegisterID base)
     {
-        loadPtr(addressFor(virtualRegisterIndex), dst);
-        Jump result = branchTest32(Zero, dst, Imm32(JSImmediate::TagTypeNumber));
-        rshift32(Imm32(JSImmediate::IntegerPayloadShift), dst);
-        return result;
+        ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
+        return addressFor(virtualRegisterIndex, base);
     }
 
-    inline JSInterfaceJIT::Jump JSInterfaceJIT::emitLoadDouble(unsigned, FPRegisterID, RegisterID)
+    inline JSInterfaceJIT::Address JSInterfaceJIT::intPayloadFor(int virtualRegisterIndex, RegisterID base)
     {
-        ASSERT_NOT_REACHED();
-        return jump();
+        ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
+        return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     }
-    
-    ALWAYS_INLINE void JSInterfaceJIT::emitFastArithImmToInt(RegisterID reg)
+    inline JSInterfaceJIT::Address JSInterfaceJIT::intTagFor(int virtualRegisterIndex, RegisterID base)
     {
-        rshift32(Imm32(JSImmediate::IntegerPayloadShift), reg);
-    }
-    
-#endif
-
-#if !USE(JSVALUE32_64)
-    inline JSInterfaceJIT::Address JSInterfaceJIT::payloadFor(unsigned virtualRegisterIndex, RegisterID base)
-    {
-        ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
-        return addressFor(virtualRegisterIndex, base);
+        ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
+        return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
     }
 #endif
 
-    inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(unsigned virtualRegisterIndex, RegisterID base)
+    inline JSInterfaceJIT::Address JSInterfaceJIT::addressFor(int virtualRegisterIndex, RegisterID base)
     {
-        ASSERT(static_cast<int>(virtualRegisterIndex) < FirstConstantRegisterIndex);
-        return Address(base, (virtualRegisterIndex * sizeof(Register)));
+        ASSERT(virtualRegisterIndex < FirstConstantRegisterIndex);
+        return Address(base, (static_cast<unsigned>(virtualRegisterIndex) * sizeof(Register)));
     }
 
 }
index 6f2b120d3e45632ab3b450b71055afc4aecbc0c4..13a5c2eee6e9afe31e8896571b492c01dbb76062 100644 (file)
@@ -43,7 +43,7 @@ namespace JSC {
             , m_pool(pool)
         {
             // Check that we have the expected number of arguments
-            m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), Imm32(expectedArgCount + 1)));
+            m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), TrustedImm32(expectedArgCount + 1)));
         }
         
         void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
@@ -61,7 +61,7 @@ namespace JSC {
         void loadJSStringArgument(int argument, RegisterID dst)
         {
             loadCellArgument(argument, dst);
-            m_failures.append(branchPtr(NotEqual, Address(dst, 0), ImmPtr(m_globalData->jsStringVPtr)));
+            m_failures.append(branchPtr(NotEqual, Address(dst, 0), TrustedImmPtr(m_globalData->jsStringVPtr)));
             m_failures.append(branchTest32(NonZero, Address(dst, OBJECT_OFFSETOF(JSString, m_fiberCount))));
         }
         
@@ -87,7 +87,7 @@ namespace JSC {
         {
             if (src != regT0)
                 move(src, regT0);
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
         
@@ -96,16 +96,12 @@ namespace JSC {
 #if USE(JSVALUE64)
             moveDoubleToPtr(src, regT0);
             subPtr(tagTypeNumberRegister, regT0);
-#elif USE(JSVALUE32_64)
+#else
             storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double)));
             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1);
             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0);
-#else
-            UNUSED_PARAM(src);
-            ASSERT_NOT_REACHED();
-            m_failures.append(jump());
 #endif
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
 
@@ -114,7 +110,7 @@ namespace JSC {
             if (src != regT0)
                 move(src, regT0);
             tagReturnAsInt32();
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
 
@@ -123,15 +119,15 @@ namespace JSC {
             if (src != regT0)
                 move(src, regT0);
             tagReturnAsJSCell();
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
         
-        PassRefPtr<NativeExecutable> finalize()
+        MacroAssemblerCodePtr finalize(JSGlobalData& globalData, MacroAssemblerCodePtr fallback)
         {
-            LinkBuffer patchBuffer(this, m_pool.get(), 0);
-            patchBuffer.link(m_failures, CodeLocationLabel(m_globalData->jitStubs->ctiNativeCallThunk()->generatedJITCode().addressForCall()));
-            return adoptRef(new NativeExecutable(patchBuffer.finalizeCode()));
+            LinkBuffer patchBuffer(globalData, this, m_pool.get());
+            patchBuffer.link(m_failures, CodeLocationLabel(fallback));
+            return patchBuffer.finalizeCode().m_code;
         }
         
     private:
@@ -144,20 +140,15 @@ namespace JSC {
         {
 #if USE(JSVALUE64)
             orPtr(tagTypeNumberRegister, regT0);
-#elif USE(JSVALUE32_64)
-            move(Imm32(JSValue::Int32Tag), regT1);
 #else
-            signExtend32ToPtr(regT0, regT0);
-            // If we can't tag the result, give up and jump to the slow case
-            m_failures.append(branchAddPtr(Overflow, regT0, regT0));
-            addPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
+            move(TrustedImm32(JSValue::Int32Tag), regT1);
 #endif
         }
 
         void tagReturnAsJSCell()
         {
 #if USE(JSVALUE32_64)
-            move(Imm32(JSValue::CellTag), regT1);
+            move(TrustedImm32(JSValue::CellTag), regT1);
 #endif
         }
         
index 72b2d1ab4f9ac7e5a9b5c51f07b5f5056c3075fc..d60fd4d9f6cc5971550dbe346ee5961bcc6acf24 100644 (file)
@@ -57,84 +57,85 @@ static void stringCharLoad(SpecializedThunkJIT& jit)
 
 static void charToString(SpecializedThunkJIT& jit, JSGlobalData* globalData, MacroAssembler::RegisterID src, MacroAssembler::RegisterID dst, MacroAssembler::RegisterID scratch)
 {
-    jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, src, MacroAssembler::Imm32(0x100)));
-    jit.move(MacroAssembler::ImmPtr(globalData->smallStrings.singleCharacterStrings()), scratch);
+    jit.appendFailure(jit.branch32(MacroAssembler::AboveOrEqual, src, MacroAssembler::TrustedImm32(0x100)));
+    jit.move(MacroAssembler::TrustedImmPtr(globalData->smallStrings.singleCharacterStrings()), scratch);
     jit.loadPtr(MacroAssembler::BaseIndex(scratch, src, MacroAssembler::ScalePtr, 0), dst);
     jit.appendFailure(jit.branchTestPtr(MacroAssembler::Zero, dst));
 }
 
-PassRefPtr<NativeExecutable> charCodeAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodePtr charCodeAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
     SpecializedThunkJIT jit(1, globalData, pool);
     stringCharLoad(jit);
     jit.returnInt32(SpecializedThunkJIT::regT0);
-    return jit.finalize();
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
-PassRefPtr<NativeExecutable> charAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
     SpecializedThunkJIT jit(1, globalData, pool);
     stringCharLoad(jit);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     jit.returnJSCell(SpecializedThunkJIT::regT0);
-    return jit.finalize();
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
-PassRefPtr<NativeExecutable> fromCharCodeThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
     SpecializedThunkJIT jit(1, globalData, pool);
     // load char code
     jit.loadInt32Argument(0, SpecializedThunkJIT::regT0);
     charToString(jit, globalData, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT1);
     jit.returnJSCell(SpecializedThunkJIT::regT0);
-    return jit.finalize();
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
-PassRefPtr<NativeExecutable> sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
-#if USE(JSVALUE64) || USE(JSVALUE32_64)
     SpecializedThunkJIT jit(1, globalData, pool);
     if (!jit.supportsFloatingPointSqrt())
-        return globalData->jitStubs->ctiNativeCallThunk();
+        return globalData->jitStubs->ctiNativeCall();
 
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
     jit.returnDouble(SpecializedThunkJIT::fpRegT0);
-    return jit.finalize();
-#else
-    UNUSED_PARAM(pool);
-    return globalData->jitStubs.ctiNativeCallThunk();
-#endif
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
 static const double oneConstant = 1.0;
 static const double negativeHalfConstant = -0.5;
 
-PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+MacroAssemblerCodePtr powThunkGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
-#if USE(JSVALUE64) || USE(JSVALUE32_64)
     SpecializedThunkJIT jit(2, globalData, pool);
     if (!jit.supportsFloatingPoint())
-        return globalData->jitStubs->ctiNativeCallThunk();
+        return globalData->jitStubs->ctiNativeCall();
 
     jit.loadDouble(&oneConstant, SpecializedThunkJIT::fpRegT1);
     jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
     MacroAssembler::Jump nonIntExponent;
     jit.loadInt32Argument(1, SpecializedThunkJIT::regT0, nonIntExponent);
-    jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(0)));
+    jit.appendFailure(jit.branch32(MacroAssembler::LessThan, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(0)));
     
     MacroAssembler::Jump exponentIsZero = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0);
     MacroAssembler::Label startLoop(jit.label());
 
-    MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::Imm32(1));
+    MacroAssembler::Jump exponentIsEven = jit.branchTest32(MacroAssembler::Zero, SpecializedThunkJIT::regT0, MacroAssembler::TrustedImm32(1));
     jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
     exponentIsEven.link(&jit);
     jit.mulDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
-    jit.rshift32(MacroAssembler::Imm32(1), SpecializedThunkJIT::regT0);
+    jit.rshift32(MacroAssembler::TrustedImm32(1), SpecializedThunkJIT::regT0);
     jit.branchTest32(MacroAssembler::NonZero, SpecializedThunkJIT::regT0).linkTo(startLoop, &jit);
 
     exponentIsZero.link(&jit);
-    jit.returnDouble(SpecializedThunkJIT::fpRegT1);
+
+    {
+        SpecializedThunkJIT::JumpList doubleResult;
+        jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT1, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT0);
+        jit.returnInt32(SpecializedThunkJIT::regT0);
+        doubleResult.link(&jit);
+        jit.returnDouble(SpecializedThunkJIT::fpRegT1);
+    }
 
     if (jit.supportsFloatingPointSqrt()) {
         nonIntExponent.link(&jit);
@@ -144,15 +145,16 @@ PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData* globalData, Executa
         jit.appendFailure(jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, SpecializedThunkJIT::fpRegT2, SpecializedThunkJIT::fpRegT3));
         jit.sqrtDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
         jit.divDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT1);
+
+        SpecializedThunkJIT::JumpList doubleResult;
+        jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT1, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT0);
+        jit.returnInt32(SpecializedThunkJIT::regT0);
+        doubleResult.link(&jit);
         jit.returnDouble(SpecializedThunkJIT::fpRegT1);
     } else
         jit.appendFailure(nonIntExponent);
 
-    return jit.finalize();
-#else
-    UNUSED_PARAM(pool);
-    return globalData->jitStubs.ctiNativeCallThunk();
-#endif
+    return jit.finalize(*globalData, globalData->jitStubs->ctiNativeCall());
 }
 
 }
index c3374f2d92d0251e1ccb26da67c2e2335fc7f91e..15261f78be4b637c3f72b89c739ebe5dd954527f 100644 (file)
 #define ThunkGenerators_h
 
 #if ENABLE(JIT)
-#include <wtf/PassRefPtr.h>
-
 namespace JSC {
     class ExecutablePool;
     class JSGlobalData;
     class NativeExecutable;
+    class MacroAssemblerCodePtr;
 
-    typedef PassRefPtr<NativeExecutable> (*ThunkGenerator)(JSGlobalData*, ExecutablePool*);
-    PassRefPtr<NativeExecutable> charCodeAtThunkGenerator(JSGlobalData*, ExecutablePool*);
-    PassRefPtr<NativeExecutable> charAtThunkGenerator(JSGlobalData*, ExecutablePool*);
-    PassRefPtr<NativeExecutable> fromCharCodeThunkGenerator(JSGlobalData*, ExecutablePool*);
-    PassRefPtr<NativeExecutable> sqrtThunkGenerator(JSGlobalData*, ExecutablePool*);
-    PassRefPtr<NativeExecutable> powThunkGenerator(JSGlobalData*, ExecutablePool*);
+    typedef MacroAssemblerCodePtr (*ThunkGenerator)(JSGlobalData*, ExecutablePool*);
+    MacroAssemblerCodePtr charCodeAtThunkGenerator(JSGlobalData*, ExecutablePool*);
+    MacroAssemblerCodePtr charAtThunkGenerator(JSGlobalData*, ExecutablePool*);
+    MacroAssemblerCodePtr fromCharCodeThunkGenerator(JSGlobalData*, ExecutablePool*);
+    MacroAssemblerCodePtr sqrtThunkGenerator(JSGlobalData*, ExecutablePool*);
+    MacroAssemblerCodePtr powThunkGenerator(JSGlobalData*, ExecutablePool*);
 }
 #endif
 
diff --git a/jsc.cpp b/jsc.cpp
index ae47d55994cb061fb696e8a167e812abe4e3084e..85ed56b3f3bd086dce1319a06ff7b9b79f322b6d 100644 (file)
--- a/jsc.cpp
+++ b/jsc.cpp
 #include "BytecodeGenerator.h"
 #include "Completion.h"
 #include "CurrentTime.h"
+#include "ExceptionHelpers.h"
 #include "InitializeThreading.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "JSString.h"
-#include "PrototypeFunction.h"
 #include "SamplingTool.h"
 #include <math.h>
 #include <stdio.h>
@@ -71,19 +71,22 @@ using namespace WTF;
 static void cleanupGlobalData(JSGlobalData*);
 static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer);
 
-static JSValue JSC_HOST_CALL functionPrint(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionDebug(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionGC(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionVersion(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionRun(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionLoad(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionCheckSyntax(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionReadline(ExecState*, JSObject*, JSValue, const ArgList&);
-static NO_RETURN_WITH_VALUE JSValue JSC_HOST_CALL functionQuit(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDebug(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionGC(ExecState*);
+#ifndef NDEBUG
+static EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState*);
+#endif
+static EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionRun(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionLoad(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionReadline(ExecState*);
+static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
 
 #if ENABLE(SAMPLING_FLAGS)
-static JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*);
 #endif
 
 struct Script {
@@ -141,142 +144,155 @@ long StopWatch::getElapsedMS()
 
 class GlobalObject : public JSGlobalObject {
 public:
-    GlobalObject(const Vector<UString>& arguments);
+    GlobalObject(JSGlobalData&, Structure*, const Vector<UString>& arguments);
     virtual UString className() const { return "global"; }
 };
 COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false);
 ASSERT_CLASS_FITS_IN_CELL(GlobalObject);
 
-GlobalObject::GlobalObject(const Vector<UString>& arguments)
-    : JSGlobalObject()
+GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const Vector<UString>& arguments)
+    : JSGlobalObject(globalData, structure)
 {
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "debug"), functionDebug));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "print"), functionPrint));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "quit"), functionQuit));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "gc"), functionGC));
+#ifndef NDEBUG
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "releaseExecutableMemory"), functionReleaseExecutableMemory));
+#endif
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "version"), functionVersion));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "run"), functionRun));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "load"), functionLoad));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "checkSyntax"), functionCheckSyntax));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 0, Identifier(globalExec(), "readline"), functionReadline));
 
 #if ENABLE(SAMPLING_FLAGS)
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
-    putDirectFunction(globalExec(), new (globalExec()) NativeFunctionWrapper(globalExec(), prototypeFunctionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "setSamplingFlags"), functionSetSamplingFlags));
+    putDirectFunction(globalExec(), new (globalExec()) JSFunction(globalExec(), this, functionStructure(), 1, Identifier(globalExec(), "clearSamplingFlags"), functionClearSamplingFlags));
 #endif
 
     JSObject* array = constructEmptyArray(globalExec());
     for (size_t i = 0; i < arguments.size(); ++i)
         array->put(globalExec(), i, jsString(globalExec(), arguments[i]));
-    putDirect(Identifier(globalExec(), "arguments"), array);
+    putDirect(globalExec()->globalData(), Identifier(globalExec(), "arguments"), array);
 }
 
-JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionPrint(ExecState* exec)
 {
-    for (unsigned i = 0; i < args.size(); ++i) {
+    for (unsigned i = 0; i < exec->argumentCount(); ++i) {
         if (i)
             putchar(' ');
 
-        printf("%s", args.at(i).toString(exec).UTF8String().data());
+        printf("%s", exec->argument(i).toString(exec).utf8().data());
     }
 
     putchar('\n');
     fflush(stdout);
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionDebug(ExecState* exec)
 {
-    fprintf(stderr, "--> %s\n", args.at(0).toString(exec).UTF8String().data());
-    return jsUndefined();
+    fprintf(stderr, "--> %s\n", exec->argument(0).toString(exec).utf8().data());
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
 {
     JSLock lock(SilenceAssertionsOnly);
     exec->heap()->collectAllGarbage();
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
+}
+
+#ifndef NDEBUG
+EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
+{
+    JSLock lock(SilenceAssertionsOnly);
+    exec->globalData().releaseExecutableMemory();
+    return JSValue::encode(jsUndefined());
 }
+#endif
 
-JSValue JSC_HOST_CALL functionVersion(ExecState*, JSObject*, JSValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL functionVersion(ExecState*)
 {
     // We need this function for compatibility with the Mozilla JS tests but for now
     // we don't actually do any version-specific handling
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL functionRun(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec)
 {
-    StopWatch stopWatch;
-    UString fileName = args.at(0).toString(exec);
+    UString fileName = exec->argument(0).toString(exec);
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
-        return throwError(exec, GeneralError, "Could not open file.");
+        return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
 
-    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    GlobalObject* globalObject = new (&exec->globalData()) GlobalObject(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<UString>());
 
+    StopWatch stopWatch;
     stopWatch.start();
     evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
     stopWatch.stop();
 
-    return jsNumber(globalObject->globalExec(), stopWatch.getElapsedMS());
+    return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
-JSValue JSC_HOST_CALL functionLoad(ExecState* exec, JSObject* o, JSValue v, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionLoad(ExecState* exec)
 {
-    UNUSED_PARAM(o);
-    UNUSED_PARAM(v);
-    UString fileName = args.at(0).toString(exec);
+    UString fileName = exec->argument(0).toString(exec);
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
-        return throwError(exec, GeneralError, "Could not open file.");
+        return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     Completion result = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script.data(), fileName));
     if (result.complType() == Throw)
-        exec->setException(result.value());
-    return result.value();
+        throwError(exec, result.value());
+    return JSValue::encode(result.value());
 }
 
-JSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec, JSObject* o, JSValue v, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionCheckSyntax(ExecState* exec)
 {
-    UNUSED_PARAM(o);
-    UNUSED_PARAM(v);
-    UString fileName = args.at(0).toString(exec);
+    UString fileName = exec->argument(0).toString(exec);
     Vector<char> script;
     if (!fillBufferWithContentsOfFile(fileName, script))
-        return throwError(exec, GeneralError, "Could not open file.");
+        return JSValue::encode(throwError(exec, createError(exec, "Could not open file.")));
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+
+    StopWatch stopWatch;
+    stopWatch.start();
     Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
+    stopWatch.stop();
+
     if (result.complType() == Throw)
-        exec->setException(result.value());
-    return result.value();
+        throwError(exec, result.value());
+    return JSValue::encode(jsNumber(stopWatch.getElapsedMS()));
 }
 
 #if ENABLE(SAMPLING_FLAGS)
-JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState* exec)
 {
-    for (unsigned i = 0; i < args.size(); ++i) {
-        unsigned flag = static_cast<unsigned>(args.at(i).toNumber(exec));
+    for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+        unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
         if ((flag >= 1) && (flag <= 32))
             SamplingFlags::setFlag(flag);
     }
-    return jsNull();
+    return JSValue::encode(jsNull());
 }
 
-JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState* exec)
 {
-    for (unsigned i = 0; i < args.size(); ++i) {
-        unsigned flag = static_cast<unsigned>(args.at(i).toNumber(exec));
+    for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+        unsigned flag = static_cast<unsigned>(exec->argument(i).toNumber(exec));
         if ((flag >= 1) && (flag <= 32))
             SamplingFlags::clearFlag(flag);
     }
-    return jsNull();
+    return JSValue::encode(jsNull());
 }
 #endif
 
-JSValue JSC_HOST_CALL functionReadline(ExecState* exec, JSObject*, JSValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL functionReadline(ExecState* exec)
 {
     Vector<char, 256> line;
     int c;
@@ -287,10 +303,10 @@ JSValue JSC_HOST_CALL functionReadline(ExecState* exec, JSObject*, JSValue, cons
         line.append(c);
     }
     line.append('\0');
-    return jsString(exec, line.data());
+    return JSValue::encode(jsString(exec, line.data()));
 }
 
-JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec)
 {
     // Technically, destroying the heap in the middle of JS execution is a no-no,
     // but we want to maintain compatibility with the Mozilla test suite, so
@@ -302,7 +318,7 @@ JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const Ar
 
 #if COMPILER(MSVC) && OS(WINCE)
     // Without this, Visual Studio will complain that this method does not return a value.
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
 #endif
 }
 
@@ -311,7 +327,7 @@ JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const Ar
 // be in a separate main function because the jscmain function requires object
 // unwinding.
 
-#if COMPILER(MSVC) && !defined(_DEBUG)
+#if COMPILER(MSVC) && !defined(_DEBUG) && !OS(WINCE)
 #define TRY       __try {
 #define EXCEPT(x) } __except (EXCEPTION_EXECUTE_HANDLER) { x; }
 #else
@@ -323,7 +339,15 @@ int jscmain(int argc, char** argv, JSGlobalData*);
 
 int main(int argc, char** argv)
 {
-#if defined(_DEBUG) && OS(WINDOWS)
+#if OS(WINDOWS)
+#if !OS(WINCE)
+    // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for
+    // testing/debugging, as it causes the post-mortem debugger not to be invoked. We reset the
+    // error mode here to work around Cygwin's behavior. See <http://webkit.org/b/55222>.
+    ::SetErrorMode(0);
+#endif
+
+#if defined(_DEBUG)
     _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
@@ -332,7 +356,6 @@ int main(int argc, char** argv)
     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
 #endif
 
-#if COMPILER(MSVC) && !OS(WINCE)
     timeBeginPeriod(1);
 #endif
 
@@ -346,7 +369,7 @@ int main(int argc, char** argv)
     // We can't use destructors in the following code because it uses Windows
     // Structured Exception Handling
     int res = 0;
-    JSGlobalData* globalData = JSGlobalData::create(ThreadStackTypeLarge).releaseRef();
+    JSGlobalData* globalData = JSGlobalData::create(ThreadStackTypeLarge).leakRef();
     TRY
         res = jscmain(argc, argv, globalData);
     EXCEPT(res = 3)
@@ -358,6 +381,7 @@ int main(int argc, char** argv)
 static void cleanupGlobalData(JSGlobalData* globalData)
 {
     JSLock lock(SilenceAssertionsOnly);
+    globalData->clearBuiltinStructures();
     globalData->heap.destroy();
     globalData->deref();
 }
@@ -371,7 +395,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
     if (dump)
         BytecodeGenerator::setDumpsGeneratedCode(true);
 
-    JSGlobalData* globalData = globalObject->globalData();
+    JSGlobalData& globalData = globalObject->globalData();
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::start();
@@ -389,27 +413,30 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
             fileName = "[Command Line]";
         }
 
-        globalData->startSampling();
+        globalData.startSampling();
 
         Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName));
         success = success && completion.complType() != Throw;
         if (dump) {
             if (completion.complType() == Throw)
-                printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
+                printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
             else
-                printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
+                printf("End: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
         }
 
-        globalData->stopSampling();
+        globalData.stopSampling();
         globalObject->globalExec()->clearException();
     }
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::stop();
 #endif
-    globalData->dumpSampleData(globalObject->globalExec());
+    globalData.dumpSampleData(globalObject->globalExec());
 #if ENABLE(SAMPLING_COUNTERS)
     AbstractSamplingCounter::dump();
+#endif
+#if ENABLE(REGEXP_TRACING)
+    globalData.dumpRegExpTrace();
 #endif
     return success;
 }
@@ -443,9 +470,9 @@ static void runInteractive(GlobalObject* globalObject)
         Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(line.data(), interpreterName));
 #endif
         if (completion.complType() == Throw)
-            printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii());
+            printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
         else
-            printf("%s\n", completion.value().toString(globalObject->globalExec()).UTF8String().data());
+            printf("%s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
 
         globalObject->globalExec()->clearException();
     }
@@ -525,7 +552,7 @@ int jscmain(int argc, char** argv, JSGlobalData* globalData)
     Options options;
     parseArguments(argc, argv, options, globalData);
 
-    GlobalObject* globalObject = new (globalData) GlobalObject(options.arguments);
+    GlobalObject* globalObject = new (globalData) GlobalObject(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments);
     bool success = runWithScripts(globalObject, options.scripts, options.dump);
     if (options.interactive && success)
         runInteractive(globalObject);
@@ -535,9 +562,9 @@ int jscmain(int argc, char** argv, JSGlobalData* globalData)
 
 static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer)
 {
-    FILE* f = fopen(fileName.UTF8String().data(), "r");
+    FILE* f = fopen(fileName.utf8().data(), "r");
     if (!f) {
-        fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().data());
+        fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
         return false;
     }
 
@@ -556,5 +583,8 @@ static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>&
     fclose(f);
     buffer[bufferSize] = '\0';
 
+    if (buffer[0] == '#' && buffer[1] == '!')
+        buffer[0] = buffer[1] = '/';
+
     return true;
 }
diff --git a/jsc.pro b/jsc.pro
index 420a3f119d15d3902c04a1d49ea371339f8958ed..21ffeeacbdcc2f5cfc16e752a46ad5c5b270f9d8 100644 (file)
--- a/jsc.pro
+++ b/jsc.pro
@@ -11,18 +11,13 @@ win32-msvc*: CONFIG += exceptions_off stl_off
 isEmpty(OUTPUT_DIR): OUTPUT_DIR= ..
 include($$PWD/../WebKit.pri)
 
-CONFIG += link_pkgconfig
+unix:!mac:!symbian:CONFIG += link_pkgconfig
 
 QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
 
-CONFIG(debug, debug|release) {
-    OBJECTS_DIR = obj/debug
-} else { # Release
-    OBJECTS_DIR = obj/release
-}
 OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP}
 include($$PWD/JavaScriptCore.pri)
-addJavaScriptCoreLib(.)
+prependJavaScriptCoreLib(.)
 
 symbian {
     TARGET.CAPABILITY = ReadUserData WriteUserData NetworkServices
@@ -30,4 +25,16 @@ symbian {
 
 mac {
     LIBS_PRIVATE += -framework AppKit
-}
\ No newline at end of file
+}
+
+win* {
+    LIBS += -ladvapi32
+}
+
+wince* {
+    LIBS += mmtimer.lib
+}
+
+# Prevent warnings about difference in visibility on Mac OS X
+contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
+unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions
diff --git a/jscore.bkl b/jscore.bkl
deleted file mode 100644 (file)
index e69de29..0000000
index a6b0f6369b19546f88940f6507efabd8548462dd..b9e19e79eb8cf3fce48c49ef81e12a76d7af2e46 100755 (executable)
@@ -4,6 +4,7 @@ export SRCROOT=$PWD
 export WebCore=$PWD
 export CREATE_HASH_TABLE="$SRCROOT/create_hash_table"
 export CREATE_REGEXP_TABLES="$SRCROOT/create_regex_tables"
+export CREATE_KEYWORD_LOOKUP="$SRCROOT/KeywordLookupGenerator.py"
 
 mkdir -p DerivedSources/JavaScriptCore
 cd DerivedSources/JavaScriptCore
diff --git a/os-win32/inttypes.h b/os-win32/inttypes.h
new file mode 100644 (file)
index 0000000..0ed6718
--- /dev/null
@@ -0,0 +1,261 @@
+// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
+//
+//  Copyright (c) 2006 Alexander Chemeris
+//
+// 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.
+//
+//   3. The name of the author may be used to endorse or promote products
+//      derived from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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 INTTYPES_WIN32_H
+#define INTTYPES_WIN32_H
+
+#include <wtf/Platform.h>
+
+#if !COMPILER(MSVC)
+#error "This inttypes.h file should only be compiled with MSVC"
+#endif
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include "stdint.h"
+
+// 7.8.1 Macros for format specifiers
+
+#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif
+
+#endif
+
+#endif
diff --git a/parser/ASTBuilder.h b/parser/ASTBuilder.h
new file mode 100644 (file)
index 0000000..8025c13
--- /dev/null
@@ -0,0 +1,979 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 ASTBuilder_h
+#define ASTBuilder_h
+
+#include "NodeConstructors.h"
+#include "SyntaxChecker.h"
+#include <utility>
+
+namespace JSC {
+
+class ASTBuilder {
+    struct BinaryOpInfo {
+        BinaryOpInfo() {}
+        BinaryOpInfo(int s, int d, int e, bool r)
+            : start(s)
+            , divot(d)
+            , end(e)
+            , hasAssignment(r)
+        {
+        }
+        BinaryOpInfo(const BinaryOpInfo& lhs, const BinaryOpInfo& rhs)
+            : start(lhs.start)
+            , divot(rhs.start)
+            , end(rhs.end)
+            , hasAssignment(lhs.hasAssignment || rhs.hasAssignment)
+        {
+        }
+        int start;
+        int divot;
+        int end;
+        bool hasAssignment;
+    };
+    
+    
+    struct AssignmentInfo {
+        AssignmentInfo() {}
+        AssignmentInfo(ExpressionNode* node, int start, int divot, int initAssignments, Operator op)
+            : m_node(node)
+            , m_start(start)
+            , m_divot(divot)
+            , m_initAssignments(initAssignments)
+            , m_op(op)
+        {
+        }
+        ExpressionNode* m_node;
+        int m_start;
+        int m_divot;
+        int m_initAssignments;
+        Operator m_op;
+    };
+public:
+    ASTBuilder(JSGlobalData* globalData, Lexer* lexer)
+        : m_globalData(globalData)
+        , m_lexer(lexer)
+        , m_scope(globalData)
+        , m_evalCount(0)
+    {
+    }
+    
+    struct BinaryExprContext {
+        BinaryExprContext(ASTBuilder&) {}
+    };
+    struct UnaryExprContext {
+        UnaryExprContext(ASTBuilder&) {}
+    };
+
+    typedef SyntaxChecker FunctionBodyBuilder;
+
+    typedef ExpressionNode* Expression;
+    typedef JSC::SourceElements* SourceElements;
+    typedef ArgumentsNode* Arguments;
+    typedef CommaNode* Comma;
+    typedef PropertyNode* Property;
+    typedef PropertyListNode* PropertyList;
+    typedef ElementNode* ElementList;
+    typedef ArgumentListNode* ArgumentsList;
+    typedef ParameterNode* FormalParameterList;
+    typedef FunctionBodyNode* FunctionBody;
+    typedef StatementNode* Statement;
+    typedef ClauseListNode* ClauseList;
+    typedef CaseClauseNode* Clause;
+    typedef ConstDeclNode* ConstDeclList;
+    typedef std::pair<ExpressionNode*, BinaryOpInfo> BinaryOperand;
+    
+    static const bool CreatesAST = true;
+    static const bool NeedsFreeVariableInfo = true;
+    static const bool CanUseFunctionCache = true;
+    static const int  DontBuildKeywords = 0;
+    static const int  DontBuildStrings = 0;
+
+    ExpressionNode* makeBinaryNode(int token, std::pair<ExpressionNode*, BinaryOpInfo>, std::pair<ExpressionNode*, BinaryOpInfo>);
+    ExpressionNode* makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end);
+
+    JSC::SourceElements* createSourceElements() { return new (m_globalData) JSC::SourceElements(m_globalData); }
+
+    ParserArenaData<DeclarationStacks::VarStack>* varDeclarations() { return m_scope.m_varDeclarations; }
+    ParserArenaData<DeclarationStacks::FunctionStack>* funcDeclarations() { return m_scope.m_funcDeclarations; }
+    int features() const { return m_scope.m_features; }
+    int numConstants() const { return m_scope.m_numConstants; }
+
+    void appendToComma(CommaNode* commaNode, ExpressionNode* expr) { commaNode->append(expr); }
+
+    CommaNode* createCommaExpr(ExpressionNode* lhs, ExpressionNode* rhs) { return new (m_globalData) CommaNode(m_globalData, lhs, rhs); }
+
+    ExpressionNode* makeAssignNode(ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end);
+    ExpressionNode* makePrefixNode(ExpressionNode*, Operator, int start, int divot, int end);
+    ExpressionNode* makePostfixNode(ExpressionNode*, Operator, int start, int divot, int end);
+    ExpressionNode* makeTypeOfNode(ExpressionNode*);
+    ExpressionNode* makeDeleteNode(ExpressionNode*, int start, int divot, int end);
+    ExpressionNode* makeNegateNode(ExpressionNode*);
+    ExpressionNode* makeBitwiseNotNode(ExpressionNode*);
+    ExpressionNode* makeMultNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeDivNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeModNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeAddNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeSubNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeBitXOrNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeBitAndNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeBitOrNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeLeftShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeRightShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+    ExpressionNode* makeURightShiftNode(ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
+
+    ExpressionNode* createLogicalNot(ExpressionNode* expr) { return new (m_globalData) LogicalNotNode(m_globalData, expr); }
+    ExpressionNode* createUnaryPlus(ExpressionNode* expr) { return new (m_globalData) UnaryPlusNode(m_globalData, expr); }
+    ExpressionNode* createVoid(ExpressionNode* expr)
+    {
+        incConstants();
+        return new (m_globalData) VoidNode(m_globalData, expr);
+    }
+    ExpressionNode* thisExpr()
+    {
+        usesThis();
+        return new (m_globalData) ThisNode(m_globalData);
+    }
+    ExpressionNode* createResolve(const Identifier* ident, int start)
+    {
+        if (m_globalData->propertyNames->arguments == *ident)
+            usesArguments();
+        return new (m_globalData) ResolveNode(m_globalData, *ident, start);
+    }
+    ExpressionNode* createObjectLiteral() { return new (m_globalData) ObjectLiteralNode(m_globalData); }
+    ExpressionNode* createObjectLiteral(PropertyListNode* properties) { return new (m_globalData) ObjectLiteralNode(m_globalData, properties); }
+
+    ExpressionNode* createArray(int elisions)
+    {
+        if (elisions)
+            incConstants();
+        return new (m_globalData) ArrayNode(m_globalData, elisions);
+    }
+
+    ExpressionNode* createArray(ElementNode* elems) { return new (m_globalData) ArrayNode(m_globalData, elems); }
+    ExpressionNode* createArray(int elisions, ElementNode* elems)
+    {
+        if (elisions)
+            incConstants();
+        return new (m_globalData) ArrayNode(m_globalData, elisions, elems);
+    }
+    ExpressionNode* createNumberExpr(double d)
+    {
+        incConstants();
+        return new (m_globalData) NumberNode(m_globalData, d);
+    }
+
+    ExpressionNode* createString(const Identifier* string)
+    {
+        incConstants();
+        return new (m_globalData) StringNode(m_globalData, *string);
+    }
+
+    ExpressionNode* createBoolean(bool b)
+    {
+        incConstants();
+        return new (m_globalData) BooleanNode(m_globalData, b);
+    }
+
+    ExpressionNode* createNull()
+    {
+        incConstants();
+        return new (m_globalData) NullNode(m_globalData);
+    }
+
+    ExpressionNode* createBracketAccess(ExpressionNode* base, ExpressionNode* property, bool propertyHasAssignments, int start, int divot, int end)
+    {
+        BracketAccessorNode* node = new (m_globalData) BracketAccessorNode(m_globalData, base, property, propertyHasAssignments);
+        setExceptionLocation(node, start, divot, end);
+        return node;
+    }
+
+    ExpressionNode* createDotAccess(ExpressionNode* base, const Identifier* property, int start, int divot, int end)
+    {
+        DotAccessorNode* node = new (m_globalData) DotAccessorNode(m_globalData, base, *property);
+        setExceptionLocation(node, start, divot, end);
+        return node;
+    }
+
+    ExpressionNode* createRegExp(const Identifier& pattern, const Identifier& flags, int start)
+    {
+        if (Yarr::checkSyntax(pattern.ustring()))
+            return 0;
+        RegExpNode* node = new (m_globalData) RegExpNode(m_globalData, pattern, flags);
+        int size = pattern.length() + 2; // + 2 for the two /'s
+        setExceptionLocation(node, start, start + size, start + size);
+        return node;
+    }
+
+    ExpressionNode* createNewExpr(ExpressionNode* expr, ArgumentsNode* arguments, int start, int divot, int end)
+    {
+        NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr, arguments);
+        setExceptionLocation(node, start, divot, end);
+        return node;
+    }
+
+    ExpressionNode* createNewExpr(ExpressionNode* expr, int start, int end)
+    {
+        NewExprNode* node = new (m_globalData) NewExprNode(m_globalData, expr);
+        setExceptionLocation(node, start, end, end);
+        return node;
+    }
+
+    ExpressionNode* createConditionalExpr(ExpressionNode* condition, ExpressionNode* lhs, ExpressionNode* rhs)
+    {
+        return new (m_globalData) ConditionalNode(m_globalData, condition, lhs, rhs);
+    }
+
+    ExpressionNode* createAssignResolve(const Identifier& ident, ExpressionNode* rhs, bool rhsHasAssignment, int start, int divot, int end)
+    {
+        AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, ident, rhs, rhsHasAssignment);
+        setExceptionLocation(node, start, divot, end);
+        return node;
+    }
+
+    ExpressionNode* createFunctionExpr(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    {
+        FuncExprNode* result = new (m_globalData) FuncExprNode(m_globalData, *name, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), parameters);
+        body->setLoc(bodyStartLine, bodyEndLine);
+        return result;
+    }
+
+    FunctionBodyNode* createFunctionBody(bool inStrictContext)
+    {
+        usesClosures();
+        return FunctionBodyNode::create(m_globalData, inStrictContext);
+    }
+    
+    template <bool> PropertyNode* createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, ParameterNode* params, FunctionBodyNode* body, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    {
+        ASSERT(name);
+        body->setLoc(bodyStartLine, bodyEndLine);
+        return new (m_globalData) PropertyNode(m_globalData, *name, new (m_globalData) FuncExprNode(m_globalData, m_globalData->propertyNames->nullIdentifier, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), params), type);
+    }
+    
+
+    ArgumentsNode* createArguments() { return new (m_globalData) ArgumentsNode(m_globalData); }
+    ArgumentsNode* createArguments(ArgumentListNode* args) { return new (m_globalData) ArgumentsNode(m_globalData, args); }
+    ArgumentListNode* createArgumentsList(ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, arg); }
+    ArgumentListNode* createArgumentsList(ArgumentListNode* args, ExpressionNode* arg) { return new (m_globalData) ArgumentListNode(m_globalData, args, arg); }
+
+    template <bool> PropertyNode* createProperty(const Identifier* propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, *propertyName, node, type); }
+    template <bool> PropertyNode* createProperty(JSGlobalData*, double propertyName, ExpressionNode* node, PropertyNode::Type type) { return new (m_globalData) PropertyNode(m_globalData, propertyName, node, type); }
+    PropertyListNode* createPropertyList(PropertyNode* property) { return new (m_globalData) PropertyListNode(m_globalData, property); }
+    PropertyListNode* createPropertyList(PropertyNode* property, PropertyListNode* tail) { return new (m_globalData) PropertyListNode(m_globalData, property, tail); }
+
+    ElementNode* createElementList(int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(m_globalData, elisions, expr); }
+    ElementNode* createElementList(ElementNode* elems, int elisions, ExpressionNode* expr) { return new (m_globalData) ElementNode(m_globalData, elems, elisions, expr); }
+
+    ParameterNode* createFormalParameterList(const Identifier& ident) { return new (m_globalData) ParameterNode(m_globalData, ident); }
+    ParameterNode* createFormalParameterList(ParameterNode* list, const Identifier& ident) { return new (m_globalData) ParameterNode(m_globalData, list, ident); }
+
+    CaseClauseNode* createClause(ExpressionNode* expr, JSC::SourceElements* statements) { return new (m_globalData) CaseClauseNode(m_globalData, expr, statements); }
+    ClauseListNode* createClauseList(CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(m_globalData, clause); }
+    ClauseListNode* createClauseList(ClauseListNode* tail, CaseClauseNode* clause) { return new (m_globalData) ClauseListNode(m_globalData, tail, clause); }
+
+    void setUsesArguments(FunctionBodyNode* node) { node->setUsesArguments(); }
+
+    StatementNode* createFuncDeclStatement(const Identifier* name, FunctionBodyNode* body, ParameterNode* parameters, int openBracePos, int closeBracePos, int bodyStartLine, int bodyEndLine)
+    {
+        FuncDeclNode* decl = new (m_globalData) FuncDeclNode(m_globalData, *name, body, m_lexer->sourceCode(openBracePos, closeBracePos, bodyStartLine), parameters);
+        if (*name == m_globalData->propertyNames->arguments)
+            usesArguments();
+        m_scope.m_funcDeclarations->data.append(decl->body());
+        body->setLoc(bodyStartLine, bodyEndLine);
+        return decl;
+    }
+
+    StatementNode* createBlockStatement(JSC::SourceElements* elements, int startLine, int endLine)
+    {
+        BlockNode* block = new (m_globalData) BlockNode(m_globalData, elements);
+        block->setLoc(startLine, endLine);
+        return block;
+    }
+
+    StatementNode* createExprStatement(ExpressionNode* expr, int start, int end)
+    {
+        ExprStatementNode* result = new (m_globalData) ExprStatementNode(m_globalData, expr);
+        result->setLoc(start, end);
+        return result;
+    }
+
+    StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, int start, int end)
+    {
+        IfNode* result = new (m_globalData) IfNode(m_globalData, condition, trueBlock);
+        result->setLoc(start, end);
+        return result;
+    }
+
+    StatementNode* createIfStatement(ExpressionNode* condition, StatementNode* trueBlock, StatementNode* falseBlock, int start, int end)
+    {
+        IfNode* result = new (m_globalData) IfElseNode(m_globalData, condition, trueBlock, falseBlock);
+        result->setLoc(start, end);
+        return result;
+    }
+
+    StatementNode* createForLoop(ExpressionNode* initializer, ExpressionNode* condition, ExpressionNode* iter, StatementNode* statements, bool b, int start, int end)
+    {
+        ForNode* result = new (m_globalData) ForNode(m_globalData, initializer, condition, iter, statements, b);
+        result->setLoc(start, end);
+        return result;
+    }
+
+    StatementNode* createForInLoop(const Identifier* ident, ExpressionNode* initializer, ExpressionNode* iter, StatementNode* statements, int start, int divot, int end, int initStart, int initEnd, int startLine, int endLine)
+    {
+        ForInNode* result = new (m_globalData) ForInNode(m_globalData, *ident, initializer, iter, statements, initStart, initStart - start, initEnd - initStart);
+        result->setLoc(startLine, endLine);
+        setExceptionLocation(result, start, divot + 1, end);
+        return result;
+    }
+
+    StatementNode* createForInLoop(ExpressionNode* lhs, ExpressionNode* iter, StatementNode* statements, int eStart, int eDivot, int eEnd, int start, int end)
+    {
+        ForInNode* result = new (m_globalData) ForInNode(m_globalData, lhs, iter, statements);
+        result->setLoc(start, end);
+        setExceptionLocation(result, eStart, eDivot, eEnd);
+        return result;
+    }
+
+    StatementNode* createEmptyStatement() { return new (m_globalData) EmptyStatementNode(m_globalData); }
+
+    StatementNode* createVarStatement(ExpressionNode* expr, int start, int end)
+    {
+        StatementNode* result;
+        if (!expr)
+            result = new (m_globalData) EmptyStatementNode(m_globalData);
+        else
+            result = new (m_globalData) VarStatementNode(m_globalData, expr);
+        result->setLoc(start, end);
+        return result;
+    }
+
+    StatementNode* createReturnStatement(ExpressionNode* expression, int eStart, int eEnd, int startLine, int endLine)
+    {
+        ReturnNode* result = new (m_globalData) ReturnNode(m_globalData, expression);
+        setExceptionLocation(result, eStart, eEnd, eEnd);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createBreakStatement(int eStart, int eEnd, int startLine, int endLine)
+    {
+        BreakNode* result = new (m_globalData) BreakNode(m_globalData);
+        setExceptionLocation(result, eStart, eEnd, eEnd);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createBreakStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
+    {
+        BreakNode* result = new (m_globalData) BreakNode(m_globalData, *ident);
+        setExceptionLocation(result, eStart, eEnd, eEnd);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createContinueStatement(int eStart, int eEnd, int startLine, int endLine)
+    {
+        ContinueNode* result = new (m_globalData) ContinueNode(m_globalData);
+        setExceptionLocation(result, eStart, eEnd, eEnd);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createContinueStatement(const Identifier* ident, int eStart, int eEnd, int startLine, int endLine)
+    {
+        ContinueNode* result = new (m_globalData) ContinueNode(m_globalData, *ident);
+        setExceptionLocation(result, eStart, eEnd, eEnd);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createTryStatement(StatementNode* tryBlock, const Identifier* ident, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock, int startLine, int endLine)
+    {
+        TryNode* result = new (m_globalData) TryNode(m_globalData, tryBlock, *ident, catchHasEval, catchBlock, finallyBlock);
+        if (catchBlock)
+            usesCatch();
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createSwitchStatement(ExpressionNode* expr, ClauseListNode* firstClauses, CaseClauseNode* defaultClause, ClauseListNode* secondClauses, int startLine, int endLine)
+    {
+        CaseBlockNode* cases = new (m_globalData) CaseBlockNode(m_globalData, firstClauses, defaultClause, secondClauses);
+        SwitchNode* result = new (m_globalData) SwitchNode(m_globalData, expr, cases);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createWhileStatement(ExpressionNode* expr, StatementNode* statement, int startLine, int endLine)
+    {
+        WhileNode* result = new (m_globalData) WhileNode(m_globalData, expr, statement);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createDoWhileStatement(StatementNode* statement, ExpressionNode* expr, int startLine, int endLine)
+    {
+        DoWhileNode* result = new (m_globalData) DoWhileNode(m_globalData, statement, expr);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    StatementNode* createLabelStatement(const Identifier* ident, StatementNode* statement, int start, int end)
+    {
+        LabelNode* result = new (m_globalData) LabelNode(m_globalData, *ident, statement);
+        setExceptionLocation(result, start, end, end);
+        return result;
+    }
+
+    StatementNode* createWithStatement(ExpressionNode* expr, StatementNode* statement, int start, int end, int startLine, int endLine)
+    {
+        usesWith();
+        WithNode* result = new (m_globalData) WithNode(m_globalData, expr, statement, end, end - start);
+        result->setLoc(startLine, endLine);
+        return result;
+    }    
+    
+    StatementNode* createThrowStatement(ExpressionNode* expr, int start, int end, int startLine, int endLine)
+    {
+        ThrowNode* result = new (m_globalData) ThrowNode(m_globalData, expr);
+        result->setLoc(startLine, endLine);
+        setExceptionLocation(result, start, end, end);
+        return result;
+    }
+    
+    StatementNode* createDebugger(int startLine, int endLine)
+    {
+        DebuggerStatementNode* result = new (m_globalData) DebuggerStatementNode(m_globalData);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+    
+    StatementNode* createConstStatement(ConstDeclNode* decls, int startLine, int endLine)
+    {
+        ConstStatementNode* result = new (m_globalData) ConstStatementNode(m_globalData, decls);
+        result->setLoc(startLine, endLine);
+        return result;
+    }
+
+    ConstDeclNode* appendConstDecl(ConstDeclNode* tail, const Identifier* name, ExpressionNode* initializer)
+    {
+        ConstDeclNode* result = new (m_globalData) ConstDeclNode(m_globalData, *name, initializer);
+        if (tail)
+            tail->m_next = result;
+        return result;
+    }
+
+    void appendStatement(JSC::SourceElements* elements, JSC::StatementNode* statement)
+    {
+        elements->append(statement);
+    }
+
+    void addVar(const Identifier* ident, int attrs)
+    {
+        if (m_globalData->propertyNames->arguments == *ident)
+            usesArguments();
+        m_scope.m_varDeclarations->data.append(std::make_pair(ident, attrs));
+    }
+
+    ExpressionNode* combineCommaNodes(ExpressionNode* list, ExpressionNode* init)
+    {
+        if (!list)
+            return init;
+        if (list->isCommaNode()) {
+            static_cast<CommaNode*>(list)->append(init);
+            return list;
+        }
+        return new (m_globalData) CommaNode(m_globalData, list, init);
+    }
+
+    int evalCount() const { return m_evalCount; }
+
+    void appendBinaryExpressionInfo(int& operandStackDepth, ExpressionNode* current, int exprStart, int lhs, int rhs, bool hasAssignments)
+    {
+        operandStackDepth++;
+        m_binaryOperandStack.append(std::make_pair(current, BinaryOpInfo(exprStart, lhs, rhs, hasAssignments)));
+    }
+
+    // Logic to handle datastructures used during parsing of binary expressions
+    void operatorStackPop(int& operatorStackDepth)
+    {
+        operatorStackDepth--;
+        m_binaryOperatorStack.removeLast();
+    }
+    bool operatorStackHasHigherPrecedence(int&, int precedence)
+    {
+        return precedence <= m_binaryOperatorStack.last().second;
+    }
+    const BinaryOperand& getFromOperandStack(int i) { return m_binaryOperandStack[m_binaryOperandStack.size() + i]; }
+    void shrinkOperandStackBy(int& operandStackDepth, int amount)
+    {
+        operandStackDepth -= amount;
+        ASSERT(operandStackDepth >= 0);
+        m_binaryOperandStack.resize(m_binaryOperandStack.size() - amount);
+    }
+    void appendBinaryOperation(int& operandStackDepth, int&, const BinaryOperand& lhs, const BinaryOperand& rhs)
+    {
+        operandStackDepth++;
+        m_binaryOperandStack.append(std::make_pair(makeBinaryNode(m_binaryOperatorStack.last().first, lhs, rhs), BinaryOpInfo(lhs.second, rhs.second)));
+    }
+    void operatorStackAppend(int& operatorStackDepth, int op, int precedence)
+    {
+        operatorStackDepth++;
+        m_binaryOperatorStack.append(std::make_pair(op, precedence));
+    }
+    ExpressionNode* popOperandStack(int&)
+    {
+        ExpressionNode* result = m_binaryOperandStack.last().first;
+        m_binaryOperandStack.removeLast();
+        return result;
+    }
+    
+    void appendUnaryToken(int& tokenStackDepth, int type, int start)
+    {
+        tokenStackDepth++;
+        m_unaryTokenStack.append(std::make_pair(type, start));
+    }
+
+    int unaryTokenStackLastType(int&)
+    {
+        return m_unaryTokenStack.last().first;
+    }
+    
+    int unaryTokenStackLastStart(int&)
+    {
+        return m_unaryTokenStack.last().second;
+    }
+    
+    void unaryTokenStackRemoveLast(int& tokenStackDepth)
+    {
+        tokenStackDepth--;
+        m_unaryTokenStack.removeLast();
+    }
+    
+    void assignmentStackAppend(int& assignmentStackDepth, ExpressionNode* node, int start, int divot, int assignmentCount, Operator op)
+    {
+        assignmentStackDepth++;
+        m_assignmentInfoStack.append(AssignmentInfo(node, start, divot, assignmentCount, op));
+    }
+
+    ExpressionNode* createAssignment(int& assignmentStackDepth, ExpressionNode* rhs, int initialAssignmentCount, int currentAssignmentCount, int lastTokenEnd)
+    {
+        ExpressionNode* result = makeAssignNode(m_assignmentInfoStack.last().m_node, m_assignmentInfoStack.last().m_op, rhs, m_assignmentInfoStack.last().m_initAssignments != initialAssignmentCount, m_assignmentInfoStack.last().m_initAssignments != currentAssignmentCount, m_assignmentInfoStack.last().m_start, m_assignmentInfoStack.last().m_divot + 1, lastTokenEnd);
+        m_assignmentInfoStack.removeLast();
+        assignmentStackDepth--;
+        return result;
+    }
+    
+    const Identifier& getName(Property property) const { return property->name(); }
+    PropertyNode::Type getType(Property property) const { return property->type(); }
+
+    bool isResolve(ExpressionNode* expr) const { return expr->isResolveNode(); }
+
+private:
+    struct Scope {
+        Scope(JSGlobalData* globalData)
+            : m_varDeclarations(new (globalData) ParserArenaData<DeclarationStacks::VarStack>)
+            , m_funcDeclarations(new (globalData) ParserArenaData<DeclarationStacks::FunctionStack>)
+            , m_features(0)
+            , m_numConstants(0)
+        {
+        }
+        ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
+        ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+        int m_features;
+        int m_numConstants;
+    };
+
+    static void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end)
+    {
+        node->setExceptionSourceCode(divot, divot - start, end - divot);
+    }
+
+    void incConstants() { m_scope.m_numConstants++; }
+    void usesThis() { m_scope.m_features |= ThisFeature; }
+    void usesCatch() { m_scope.m_features |= CatchFeature; }
+    void usesClosures() { m_scope.m_features |= ClosureFeature; }
+    void usesArguments() { m_scope.m_features |= ArgumentsFeature; }
+    void usesAssignment() { m_scope.m_features |= AssignFeature; }
+    void usesWith() { m_scope.m_features |= WithFeature; }
+    void usesEval() 
+    {
+        m_evalCount++;
+        m_scope.m_features |= EvalFeature;
+    }
+    ExpressionNode* createNumber(double d)
+    {
+        return new (m_globalData) NumberNode(m_globalData, d);
+    }
+    
+    JSGlobalData* m_globalData;
+    Lexer* m_lexer;
+    Scope m_scope;
+    Vector<BinaryOperand, 10> m_binaryOperandStack;
+    Vector<AssignmentInfo, 10> m_assignmentInfoStack;
+    Vector<pair<int, int>, 10> m_binaryOperatorStack;
+    Vector<pair<int, int>, 10> m_unaryTokenStack;
+    int m_evalCount;
+};
+
+ExpressionNode* ASTBuilder::makeTypeOfNode(ExpressionNode* expr)
+{
+    if (expr->isResolveNode()) {
+        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+        return new (m_globalData) TypeOfResolveNode(m_globalData, resolve->identifier());
+    }
+    return new (m_globalData) TypeOfValueNode(m_globalData, expr);
+}
+
+ExpressionNode* ASTBuilder::makeDeleteNode(ExpressionNode* expr, int start, int divot, int end)
+{
+    if (!expr->isLocation())
+        return new (m_globalData) DeleteValueNode(m_globalData, expr);
+    if (expr->isResolveNode()) {
+        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+        return new (m_globalData) DeleteResolveNode(m_globalData, resolve->identifier(), divot, divot - start, end - divot);
+    }
+    if (expr->isBracketAccessorNode()) {
+        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+        return new (m_globalData) DeleteBracketNode(m_globalData, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
+    }
+    ASSERT(expr->isDotAccessorNode());
+    DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+    return new (m_globalData) DeleteDotNode(m_globalData, dot->base(), dot->identifier(), divot, divot - start, end - divot);
+}
+
+ExpressionNode* ASTBuilder::makeNegateNode(ExpressionNode* n)
+{
+    if (n->isNumber()) {
+        NumberNode* numberNode = static_cast<NumberNode*>(n);
+        numberNode->setValue(-numberNode->value());
+        return numberNode;
+    }
+
+    return new (m_globalData) NegateNode(m_globalData, n);
+}
+
+ExpressionNode* ASTBuilder::makeBitwiseNotNode(ExpressionNode* expr)
+{
+    if (expr->isNumber())
+        return createNumber(~toInt32(static_cast<NumberNode*>(expr)->value()));
+    return new (m_globalData) BitwiseNotNode(m_globalData, expr);
+}
+
+ExpressionNode* ASTBuilder::makeMultNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    expr1 = expr1->stripUnaryPlus();
+    expr2 = expr2->stripUnaryPlus();
+
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
+
+    if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
+        return new (m_globalData) UnaryPlusNode(m_globalData, expr2);
+
+    if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
+        return new (m_globalData) UnaryPlusNode(m_globalData, expr1);
+
+    return new (m_globalData) MultNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeDivNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    expr1 = expr1->stripUnaryPlus();
+    expr2 = expr2->stripUnaryPlus();
+
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
+    return new (m_globalData) DivNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeModNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    expr1 = expr1->stripUnaryPlus();
+    expr2 = expr2->stripUnaryPlus();
+    
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(fmod(static_cast<NumberNode*>(expr1)->value(), static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) ModNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeAddNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
+    return new (m_globalData) AddNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeSubNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    expr1 = expr1->stripUnaryPlus();
+    expr2 = expr2->stripUnaryPlus();
+
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
+    return new (m_globalData) SubNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeLeftShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (m_globalData) LeftShiftNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeRightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (m_globalData) RightShiftNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeURightShiftNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(toUInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
+    return new (m_globalData) UnsignedRightShiftNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeBitOrNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) | toInt32(static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) BitOrNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeBitAndNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) & toInt32(static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) BitAndNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeBitXOrNode(ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
+{
+    if (expr1->isNumber() && expr2->isNumber())
+        return createNumber(toInt32(static_cast<NumberNode*>(expr1)->value()) ^ toInt32(static_cast<NumberNode*>(expr2)->value()));
+    return new (m_globalData) BitXOrNode(m_globalData, expr1, expr2, rightHasAssignments);
+}
+
+ExpressionNode* ASTBuilder::makeFunctionCallNode(ExpressionNode* func, ArgumentsNode* args, int start, int divot, int end)
+{
+    if (!func->isLocation())
+        return new (m_globalData) FunctionCallValueNode(m_globalData, func, args, divot, divot - start, end - divot);
+    if (func->isResolveNode()) {
+        ResolveNode* resolve = static_cast<ResolveNode*>(func);
+        const Identifier& identifier = resolve->identifier();
+        if (identifier == m_globalData->propertyNames->eval) {
+            usesEval();
+            return new (m_globalData) EvalFunctionCallNode(m_globalData, args, divot, divot - start, end - divot);
+        }
+        return new (m_globalData) FunctionCallResolveNode(m_globalData, identifier, args, divot, divot - start, end - divot);
+    }
+    if (func->isBracketAccessorNode()) {
+        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func);
+        FunctionCallBracketNode* node = new (m_globalData) FunctionCallBracketNode(m_globalData, bracket->base(), bracket->subscript(), args, divot, divot - start, end - divot);
+        node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+        return node;
+    }
+    ASSERT(func->isDotAccessorNode());
+    DotAccessorNode* dot = static_cast<DotAccessorNode*>(func);
+    FunctionCallDotNode* node;
+    if (dot->identifier() == m_globalData->propertyNames->call)
+        node = new (m_globalData) CallFunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+    else if (dot->identifier() == m_globalData->propertyNames->apply)
+        node = new (m_globalData) ApplyFunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+    else
+        node = new (m_globalData) FunctionCallDotNode(m_globalData, dot->base(), dot->identifier(), args, divot, divot - start, end - divot);
+    node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+    return node;
+}
+
+ExpressionNode* ASTBuilder::makeBinaryNode(int token, pair<ExpressionNode*, BinaryOpInfo> lhs, pair<ExpressionNode*, BinaryOpInfo> rhs)
+{
+    switch (token) {
+    case OR:
+        return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalOr);
+
+    case AND:
+        return new (m_globalData) LogicalOpNode(m_globalData, lhs.first, rhs.first, OpLogicalAnd);
+
+    case BITOR:
+        return makeBitOrNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case BITXOR:
+        return makeBitXOrNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case BITAND:
+        return makeBitAndNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case EQEQ:
+        return new (m_globalData) EqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case NE:
+        return new (m_globalData) NotEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case STREQ:
+        return new (m_globalData) StrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case STRNEQ:
+        return new (m_globalData) NotStrictEqualNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case LT:
+        return new (m_globalData) LessNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case GT:
+        return new (m_globalData) GreaterNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case LE:
+        return new (m_globalData) LessEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case GE:
+        return new (m_globalData) GreaterEqNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case INSTANCEOF: {
+        InstanceOfNode* node = new (m_globalData) InstanceOfNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
+        return node;
+    }
+
+    case INTOKEN: {
+        InNode* node = new (m_globalData) InNode(m_globalData, lhs.first, rhs.first, rhs.second.hasAssignment);
+        setExceptionLocation(node, lhs.second.start, rhs.second.start, rhs.second.end);
+        return node;
+    }
+
+    case LSHIFT:
+        return makeLeftShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case RSHIFT:
+        return makeRightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case URSHIFT:
+        return makeURightShiftNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case PLUS:
+        return makeAddNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case MINUS:
+        return makeSubNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case TIMES:
+        return makeMultNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case DIVIDE:
+        return makeDivNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+
+    case MOD:
+        return makeModNode(lhs.first, rhs.first, rhs.second.hasAssignment);
+    }
+    CRASH();
+    return 0;
+}
+
+ExpressionNode* ASTBuilder::makeAssignNode(ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
+{
+    usesAssignment();
+    if (!loc->isLocation())
+        return new (m_globalData) AssignErrorNode(m_globalData, loc, op, expr, divot, divot - start, end - divot);
+
+    if (loc->isResolveNode()) {
+        ResolveNode* resolve = static_cast<ResolveNode*>(loc);
+        if (op == OpEqual) {
+            AssignResolveNode* node = new (m_globalData) AssignResolveNode(m_globalData, resolve->identifier(), expr, exprHasAssignments);
+            setExceptionLocation(node, start, divot, end);
+            return node;
+        }
+        return new (m_globalData) ReadModifyResolveNode(m_globalData, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+    }
+    if (loc->isBracketAccessorNode()) {
+        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
+        if (op == OpEqual)
+            return new (m_globalData) AssignBracketNode(m_globalData, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
+        ReadModifyBracketNode* node = new (m_globalData) ReadModifyBracketNode(m_globalData, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
+        node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+        return node;
+    }
+    ASSERT(loc->isDotAccessorNode());
+    DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
+    if (op == OpEqual)
+        return new (m_globalData) AssignDotNode(m_globalData, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
+
+    ReadModifyDotNode* node = new (m_globalData) ReadModifyDotNode(m_globalData, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
+    node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+    return node;
+}
+
+ExpressionNode* ASTBuilder::makePrefixNode(ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+    usesAssignment();
+    if (!expr->isLocation())
+        return new (m_globalData) PrefixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot);
+
+    if (expr->isResolveNode()) {
+        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+        return new (m_globalData) PrefixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot);
+    }
+    if (expr->isBracketAccessorNode()) {
+        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+        PrefixBracketNode* node = new (m_globalData) PrefixBracketNode(m_globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+        node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
+        return node;
+    }
+    ASSERT(expr->isDotAccessorNode());
+    DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+    PrefixDotNode* node = new (m_globalData) PrefixDotNode(m_globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+    node->setSubexpressionInfo(dot->divot(), dot->startOffset());
+    return node;
+}
+
+ExpressionNode* ASTBuilder::makePostfixNode(ExpressionNode* expr, Operator op, int start, int divot, int end)
+{
+    usesAssignment();
+    if (!expr->isLocation())
+        return new (m_globalData) PostfixErrorNode(m_globalData, expr, op, divot, divot - start, end - divot);
+
+    if (expr->isResolveNode()) {
+        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
+        return new (m_globalData) PostfixResolveNode(m_globalData, resolve->identifier(), op, divot, divot - start, end - divot);
+    }
+    if (expr->isBracketAccessorNode()) {
+        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
+        PostfixBracketNode* node = new (m_globalData) PostfixBracketNode(m_globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
+        node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
+        return node;
+
+    }
+    ASSERT(expr->isDotAccessorNode());
+    DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
+    PostfixDotNode* node = new (m_globalData) PostfixDotNode(m_globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
+    node->setSubexpressionInfo(dot->divot(), dot->endOffset());
+    return node;
+}
+
+}
+
+#endif
diff --git a/parser/Grammar.y b/parser/Grammar.y
deleted file mode 100644 (file)
index 4d6e7d1..0000000
+++ /dev/null
@@ -1,2099 +0,0 @@
-%pure_parser
-
-%{
-
-/*
- *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include "config.h"
-
-#include "JSObject.h"
-#include "JSString.h"
-#include "Lexer.h"
-#include "NodeConstructors.h"
-#include "NodeInfo.h"
-#include <stdlib.h>
-#include <string.h>
-#include <wtf/MathExtras.h>
-
-#define YYMALLOC fastMalloc
-#define YYFREE fastFree
-
-#define YYMAXDEPTH 10000
-#define YYENABLE_NLS 0
-
-// Default values for bison.
-#define YYDEBUG 0 // Set to 1 to debug a parse error.
-#define jscyydebug 0 // Set to 1 to debug a parse error.
-#if !OS(DARWIN)
-// Avoid triggering warnings in older bison by not setting this on the Darwin platform.
-// FIXME: Is this still needed?
-#define YYERROR_VERBOSE
-#endif
-
-int jscyyerror(const char*);
-
-static inline bool allowAutomaticSemicolon(JSC::Lexer&, int);
-
-#define GLOBAL_DATA static_cast<JSGlobalData*>(globalPtr)
-#define AUTO_SEMICOLON do { if (!allowAutomaticSemicolon(*GLOBAL_DATA->lexer, yychar)) YYABORT; } while (0)
-
-using namespace JSC;
-using namespace std;
-
-static ExpressionNode* makeAssignNode(JSGlobalData*, ExpressionNode* left, Operator, ExpressionNode* right, bool leftHasAssignments, bool rightHasAssignments, int start, int divot, int end);
-static ExpressionNode* makePrefixNode(JSGlobalData*, ExpressionNode*, Operator, int start, int divot, int end);
-static ExpressionNode* makePostfixNode(JSGlobalData*, ExpressionNode*, Operator, int start, int divot, int end);
-static PropertyNode* makeGetterOrSetterPropertyNode(JSGlobalData*, const Identifier& getOrSet, const Identifier& name, ParameterNode*, FunctionBodyNode*, const SourceCode&);
-static ExpressionNodeInfo makeFunctionCallNode(JSGlobalData*, ExpressionNodeInfo function, ArgumentsNodeInfo, int start, int divot, int end);
-static ExpressionNode* makeTypeOfNode(JSGlobalData*, ExpressionNode*);
-static ExpressionNode* makeDeleteNode(JSGlobalData*, ExpressionNode*, int start, int divot, int end);
-static ExpressionNode* makeNegateNode(JSGlobalData*, ExpressionNode*);
-static NumberNode* makeNumberNode(JSGlobalData*, double);
-static ExpressionNode* makeBitwiseNotNode(JSGlobalData*, ExpressionNode*);
-static ExpressionNode* makeMultNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
-static ExpressionNode* makeDivNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
-static ExpressionNode* makeAddNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
-static ExpressionNode* makeSubNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
-static ExpressionNode* makeLeftShiftNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
-static ExpressionNode* makeRightShiftNode(JSGlobalData*, ExpressionNode* left, ExpressionNode* right, bool rightHasAssignments);
-static StatementNode* makeVarStatementNode(JSGlobalData*, ExpressionNode*);
-static ExpressionNode* combineCommaNodes(JSGlobalData*, ExpressionNode* list, ExpressionNode* init);
-
-#if COMPILER(MSVC)
-
-#pragma warning(disable: 4065)
-#pragma warning(disable: 4244)
-#pragma warning(disable: 4702)
-
-#endif
-
-#define YYPARSE_PARAM globalPtr
-#define YYLEX_PARAM globalPtr
-
-template <typename T> inline NodeDeclarationInfo<T> createNodeDeclarationInfo(T node,
-    ParserArenaData<DeclarationStacks::VarStack>* varDecls,
-    ParserArenaData<DeclarationStacks::FunctionStack>* funcDecls,
-    CodeFeatures info, int numConstants) 
-{
-    ASSERT((info & ~AllFeatures) == 0);
-    NodeDeclarationInfo<T> result = { node, varDecls, funcDecls, info, numConstants };
-    return result;
-}
-
-template <typename T> inline NodeInfo<T> createNodeInfo(T node, CodeFeatures info, int numConstants)
-{
-    ASSERT((info & ~AllFeatures) == 0);
-    NodeInfo<T> result = { node, info, numConstants };
-    return result;
-}
-
-template <typename T> inline T mergeDeclarationLists(T decls1, T decls2) 
-{
-    // decls1 or both are null
-    if (!decls1)
-        return decls2;
-    // only decls1 is non-null
-    if (!decls2)
-        return decls1;
-
-    // Both are non-null
-    decls1->data.append(decls2->data);
-    
-    // Manually release as much as possible from the now-defunct declaration lists
-    // to avoid accumulating so many unused heap allocated vectors.
-    decls2->data.clear();
-
-    return decls1;
-}
-
-static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, const Identifier& ident, unsigned attrs)
-{
-    if (!varDecls)
-        varDecls = new (globalData) ParserArenaData<DeclarationStacks::VarStack>;
-
-    varDecls->data.append(make_pair(&ident, attrs));
-}
-
-static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserArenaData<DeclarationStacks::VarStack>*& varDecls, ConstDeclNode* decl)
-{
-    unsigned attrs = DeclarationStacks::IsConstant;
-    if (decl->hasInitializer())
-        attrs |= DeclarationStacks::HasInitializer;        
-    appendToVarDeclarationList(globalData, varDecls, decl->ident(), attrs);
-}
-
-%}
-
-%union {
-    int                 intValue;
-    double              doubleValue;
-    const Identifier*   ident;
-
-    // expression subtrees
-    ExpressionNodeInfo  expressionNode;
-    FuncDeclNodeInfo    funcDeclNode;
-    PropertyNodeInfo    propertyNode;
-    ArgumentsNodeInfo   argumentsNode;
-    ConstDeclNodeInfo   constDeclNode;
-    CaseBlockNodeInfo   caseBlockNode;
-    CaseClauseNodeInfo  caseClauseNode;
-    FuncExprNodeInfo    funcExprNode;
-
-    // statement nodes
-    StatementNodeInfo   statementNode;
-    FunctionBodyNode*   functionBodyNode;
-    ProgramNode*        programNode;
-
-    SourceElementsInfo  sourceElements;
-    PropertyListInfo    propertyList;
-    ArgumentListInfo    argumentList;
-    VarDeclListInfo     varDeclList;
-    ConstDeclListInfo   constDeclList;
-    ClauseListInfo      clauseList;
-    ElementListInfo     elementList;
-    ParameterListInfo   parameterList;
-
-    Operator            op;
-}
-
-%{
-
-template <typename T> inline void setStatementLocation(StatementNode* statement, const T& start, const T& end)
-{
-    statement->setLoc(start.first_line, end.last_line);
-}
-
-static inline void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end)
-{
-    node->setExceptionSourceCode(divot, divot - start, end - divot);
-}
-
-%}
-
-%start Program
-
-/* literals */
-%token NULLTOKEN TRUETOKEN FALSETOKEN
-
-/* keywords */
-%token BREAK CASE DEFAULT FOR NEW VAR CONSTTOKEN CONTINUE
-%token FUNCTION RETURN VOIDTOKEN DELETETOKEN
-%token IF THISTOKEN DO WHILE INTOKEN INSTANCEOF TYPEOF
-%token SWITCH WITH RESERVED
-%token THROW TRY CATCH FINALLY
-%token DEBUGGER
-
-/* give an if without an else higher precedence than an else to resolve the ambiguity */
-%nonassoc IF_WITHOUT_ELSE
-%nonassoc ELSE
-
-/* punctuators */
-%token EQEQ NE                     /* == and != */
-%token STREQ STRNEQ                /* === and !== */
-%token LE GE                       /* < and > */
-%token OR AND                      /* || and && */
-%token PLUSPLUS MINUSMINUS         /* ++ and --  */
-%token LSHIFT                      /* << */
-%token RSHIFT URSHIFT              /* >> and >>> */
-%token PLUSEQUAL MINUSEQUAL        /* += and -= */
-%token MULTEQUAL DIVEQUAL          /* *= and /= */
-%token LSHIFTEQUAL                 /* <<= */
-%token RSHIFTEQUAL URSHIFTEQUAL    /* >>= and >>>= */
-%token ANDEQUAL MODEQUAL           /* &= and %= */
-%token XOREQUAL OREQUAL            /* ^= and |= */
-%token <intValue> OPENBRACE        /* { (with char offset) */
-%token <intValue> CLOSEBRACE       /* } (with char offset) */
-
-/* terminal types */
-%token <doubleValue> NUMBER
-%token <ident> IDENT STRING
-
-/* automatically inserted semicolon */
-%token AUTOPLUSPLUS AUTOMINUSMINUS
-
-/* non-terminal types */
-%type <expressionNode>  Literal ArrayLiteral
-
-%type <expressionNode>  PrimaryExpr PrimaryExprNoBrace
-%type <expressionNode>  MemberExpr MemberExprNoBF /* BF => brace or function */
-%type <expressionNode>  NewExpr NewExprNoBF
-%type <expressionNode>  CallExpr CallExprNoBF
-%type <expressionNode>  LeftHandSideExpr LeftHandSideExprNoBF
-%type <expressionNode>  PostfixExpr PostfixExprNoBF
-%type <expressionNode>  UnaryExpr UnaryExprNoBF UnaryExprCommon
-%type <expressionNode>  MultiplicativeExpr MultiplicativeExprNoBF
-%type <expressionNode>  AdditiveExpr AdditiveExprNoBF
-%type <expressionNode>  ShiftExpr ShiftExprNoBF
-%type <expressionNode>  RelationalExpr RelationalExprNoIn RelationalExprNoBF
-%type <expressionNode>  EqualityExpr EqualityExprNoIn EqualityExprNoBF
-%type <expressionNode>  BitwiseANDExpr BitwiseANDExprNoIn BitwiseANDExprNoBF
-%type <expressionNode>  BitwiseXORExpr BitwiseXORExprNoIn BitwiseXORExprNoBF
-%type <expressionNode>  BitwiseORExpr BitwiseORExprNoIn BitwiseORExprNoBF
-%type <expressionNode>  LogicalANDExpr LogicalANDExprNoIn LogicalANDExprNoBF
-%type <expressionNode>  LogicalORExpr LogicalORExprNoIn LogicalORExprNoBF
-%type <expressionNode>  ConditionalExpr ConditionalExprNoIn ConditionalExprNoBF
-%type <expressionNode>  AssignmentExpr AssignmentExprNoIn AssignmentExprNoBF
-%type <expressionNode>  Expr ExprNoIn ExprNoBF
-
-%type <expressionNode>  ExprOpt ExprNoInOpt
-
-%type <statementNode>   Statement Block
-%type <statementNode>   VariableStatement ConstStatement EmptyStatement ExprStatement
-%type <statementNode>   IfStatement IterationStatement ContinueStatement
-%type <statementNode>   BreakStatement ReturnStatement WithStatement
-%type <statementNode>   SwitchStatement LabelledStatement
-%type <statementNode>   ThrowStatement TryStatement
-%type <statementNode>   DebuggerStatement
-
-%type <expressionNode>  Initializer InitializerNoIn
-%type <statementNode>   FunctionDeclaration
-%type <funcExprNode>    FunctionExpr
-%type <functionBodyNode> FunctionBody
-%type <sourceElements>  SourceElements
-%type <parameterList>   FormalParameterList
-%type <op>              AssignmentOperator
-%type <argumentsNode>   Arguments
-%type <argumentList>    ArgumentList
-%type <varDeclList>     VariableDeclarationList VariableDeclarationListNoIn
-%type <constDeclList>   ConstDeclarationList
-%type <constDeclNode>   ConstDeclaration
-%type <caseBlockNode>   CaseBlock
-%type <caseClauseNode>  CaseClause DefaultClause
-%type <clauseList>      CaseClauses CaseClausesOpt
-%type <intValue>        Elision ElisionOpt
-%type <elementList>     ElementList
-%type <propertyNode>    Property
-%type <propertyList>    PropertyList
-%%
-
-// FIXME: There are currently two versions of the grammar in this file, the normal one, and the NoNodes version used for
-// lazy recompilation of FunctionBodyNodes.  We should move to generating the two versions from a script to avoid bugs.
-// In the mean time, make sure to make any changes to the grammar in both versions.
-
-Literal:
-    NULLTOKEN                           { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NullNode(GLOBAL_DATA), 0, 1); }
-  | TRUETOKEN                           { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, true), 0, 1); }
-  | FALSETOKEN                          { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, false), 0, 1); }
-  | NUMBER                              { $$ = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, $1), 0, 1); }
-  | STRING                              { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *$1), 0, 1); }
-  | '/' /* regexp */                    {
-                                            Lexer& l = *GLOBAL_DATA->lexer;
-                                            const Identifier* pattern;
-                                            const Identifier* flags;
-                                            if (!l.scanRegExp(pattern, flags))
-                                                YYABORT;
-                                            RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, *pattern, *flags);
-                                            int size = pattern->size() + 2; // + 2 for the two /'s
-                                            setExceptionLocation(node, @1.first_column, @1.first_column + size, @1.first_column + size);
-                                            $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
-                                        }
-  | DIVEQUAL /* regexp with /= */       {
-                                            Lexer& l = *GLOBAL_DATA->lexer;
-                                            const Identifier* pattern;
-                                            const Identifier* flags;
-                                            if (!l.scanRegExp(pattern, flags, '='))
-                                                YYABORT;
-                                            RegExpNode* node = new (GLOBAL_DATA) RegExpNode(GLOBAL_DATA, *pattern, *flags);
-                                            int size = pattern->size() + 2; // + 2 for the two /'s
-                                            setExceptionLocation(node, @1.first_column, @1.first_column + size, @1.first_column + size);
-                                            $$ = createNodeInfo<ExpressionNode*>(node, 0, 0);
-                                        }
-;
-
-Property:
-    IDENT ':' AssignmentExpr            { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
-  | STRING ':' AssignmentExpr           { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *$1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
-  | NUMBER ':' AssignmentExpr           { $$ = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, $1, $3.m_node, PropertyNode::Constant), $3.m_features, $3.m_numConstants); }
-  | IDENT IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE    { $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(GLOBAL_DATA, *$1, *$2, 0, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); setStatementLocation($6, @5, @7); if (!$$.m_node) YYABORT; }
-  | IDENT IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
-                                                             {
-                                                                 $$ = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(GLOBAL_DATA, *$1, *$2, $4.m_node.head, $7, GLOBAL_DATA->lexer->sourceCode($6, $8, @6.first_line)), $4.m_features | ClosureFeature, 0); 
-                                                                 if ($4.m_features & ArgumentsFeature)
-                                                                     $7->setUsesArguments(); 
-                                                                 setStatementLocation($7, @6, @8); 
-                                                                 if (!$$.m_node) 
-                                                                     YYABORT; 
-                                                             }
-;
-
-PropertyList:
-    Property                            { $$.m_node.head = new (GLOBAL_DATA) PropertyListNode(GLOBAL_DATA, $1.m_node); 
-                                          $$.m_node.tail = $$.m_node.head;
-                                          $$.m_features = $1.m_features;
-                                          $$.m_numConstants = $1.m_numConstants; }
-  | PropertyList ',' Property           { $$.m_node.head = $1.m_node.head;
-                                          $$.m_node.tail = new (GLOBAL_DATA) PropertyListNode(GLOBAL_DATA, $3.m_node, $1.m_node.tail);
-                                          $$.m_features = $1.m_features | $3.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
-;
-
-PrimaryExpr:
-    PrimaryExprNoBrace
-  | OPENBRACE CLOSEBRACE                             { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA), 0, 0); }
-  | OPENBRACE PropertyList CLOSEBRACE                { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
-  /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
-  | OPENBRACE PropertyList ',' CLOSEBRACE            { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
-;
-
-PrimaryExprNoBrace:
-    THISTOKEN                           { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ThisNode(GLOBAL_DATA), ThisFeature, 0); }
-  | Literal
-  | ArrayLiteral
-  | IDENT                               { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ResolveNode(GLOBAL_DATA, *$1, @1.first_column), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
-  | '(' Expr ')'                        { $$ = $2; }
-;
-
-ArrayLiteral:
-    '[' ElisionOpt ']'                  { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $2), 0, $2 ? 1 : 0); }
-  | '[' ElementList ']'                 { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
-  | '[' ElementList ',' ElisionOpt ']'  { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, $4, $2.m_node.head), $2.m_features, $4 ? $2.m_numConstants + 1 : $2.m_numConstants); }
-;
-
-ElementList:
-    ElisionOpt AssignmentExpr           { $$.m_node.head = new (GLOBAL_DATA) ElementNode(GLOBAL_DATA, $1, $2.m_node);
-                                          $$.m_node.tail = $$.m_node.head;
-                                          $$.m_features = $2.m_features;
-                                          $$.m_numConstants = $2.m_numConstants; }
-  | ElementList ',' ElisionOpt AssignmentExpr
-                                        { $$.m_node.head = $1.m_node.head;
-                                          $$.m_node.tail = new (GLOBAL_DATA) ElementNode(GLOBAL_DATA, $1.m_node.tail, $3, $4.m_node);
-                                          $$.m_features = $1.m_features | $4.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $4.m_numConstants; }
-;
-
-ElisionOpt:
-    /* nothing */                       { $$ = 0; }
-  | Elision
-;
-
-Elision:
-    ','                                 { $$ = 1; }
-  | Elision ','                         { $$ = $1 + 1; }
-;
-
-MemberExpr:
-    PrimaryExpr
-  | FunctionExpr                        { $$ = createNodeInfo<ExpressionNode*>($1.m_node, $1.m_features, $1.m_numConstants); }
-  | MemberExpr '[' Expr ']'             { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
-                                        }
-  | MemberExpr '.' IDENT                { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
-                                        }
-  | NEW MemberExpr Arguments            { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @3.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
-                                        }
-;
-
-MemberExprNoBF:
-    PrimaryExprNoBrace
-  | MemberExprNoBF '[' Expr ']'         { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
-                                        }
-  | MemberExprNoBF '.' IDENT            { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants);
-                                        }
-  | NEW MemberExpr Arguments            { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node, $3.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @3.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features | $3.m_features, $2.m_numConstants + $3.m_numConstants);
-                                        }
-;
-
-NewExpr:
-    MemberExpr
-  | NEW NewExpr                         { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants); 
-                                        }
-;
-
-NewExprNoBF:
-    MemberExprNoBF
-  | NEW NewExpr                         { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, $2.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $2.m_features, $2.m_numConstants);
-                                        }
-;
-
-CallExpr:
-    MemberExpr Arguments                { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
-  | CallExpr Arguments                  { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
-  | CallExpr '[' Expr ']'               { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
-                                        }
-  | CallExpr '.' IDENT                  { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); }
-;
-
-CallExprNoBF:
-    MemberExprNoBF Arguments            { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
-  | CallExprNoBF Arguments              { $$ = makeFunctionCallNode(GLOBAL_DATA, $1, $2, @1.first_column, @1.last_column, @2.last_column); }
-  | CallExprNoBF '[' Expr ']'           { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @4.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); 
-                                        }
-  | CallExprNoBF '.' IDENT              { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, $1.m_node, *$3);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @3.last_column);
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features, $1.m_numConstants); 
-                                        }
-;
-
-Arguments:
-    '(' ')'                             { $$ = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA), 0, 0); }
-  | '(' ArgumentList ')'                { $$ = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA, $2.m_node.head), $2.m_features, $2.m_numConstants); }
-;
-
-ArgumentList:
-    AssignmentExpr                      { $$.m_node.head = new (GLOBAL_DATA) ArgumentListNode(GLOBAL_DATA, $1.m_node);
-                                          $$.m_node.tail = $$.m_node.head;
-                                          $$.m_features = $1.m_features;
-                                          $$.m_numConstants = $1.m_numConstants; }
-  | ArgumentList ',' AssignmentExpr     { $$.m_node.head = $1.m_node.head;
-                                          $$.m_node.tail = new (GLOBAL_DATA) ArgumentListNode(GLOBAL_DATA, $1.m_node.tail, $3.m_node);
-                                          $$.m_features = $1.m_features | $3.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
-;
-
-LeftHandSideExpr:
-    NewExpr
-  | CallExpr
-;
-
-LeftHandSideExprNoBF:
-    NewExprNoBF
-  | CallExprNoBF
-;
-
-PostfixExpr:
-    LeftHandSideExpr
-  | LeftHandSideExpr PLUSPLUS           { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
-  | LeftHandSideExpr MINUSMINUS         { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
-;
-
-PostfixExprNoBF:
-    LeftHandSideExprNoBF
-  | LeftHandSideExprNoBF PLUSPLUS       { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpPlusPlus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
-  | LeftHandSideExprNoBF MINUSMINUS     { $$ = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, $1.m_node, OpMinusMinus, @1.first_column, @1.last_column, @2.last_column), $1.m_features | AssignFeature, $1.m_numConstants); }
-;
-
-UnaryExprCommon:
-    DELETETOKEN UnaryExpr               { $$ = createNodeInfo<ExpressionNode*>(makeDeleteNode(GLOBAL_DATA, $2.m_node, @1.first_column, @2.last_column, @2.last_column), $2.m_features, $2.m_numConstants); }
-  | VOIDTOKEN UnaryExpr                 { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) VoidNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants + 1); }
-  | TYPEOF UnaryExpr                    { $$ = createNodeInfo<ExpressionNode*>(makeTypeOfNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
-  | PLUSPLUS UnaryExpr                  { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
-  | AUTOPLUSPLUS UnaryExpr              { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpPlusPlus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
-  | MINUSMINUS UnaryExpr                { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
-  | AUTOMINUSMINUS UnaryExpr            { $$ = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, $2.m_node, OpMinusMinus, @1.first_column, @2.first_column + 1, @2.last_column), $2.m_features | AssignFeature, $2.m_numConstants); }
-  | '+' UnaryExpr                       { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
-  | '-' UnaryExpr                       { $$ = createNodeInfo<ExpressionNode*>(makeNegateNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
-  | '~' UnaryExpr                       { $$ = createNodeInfo<ExpressionNode*>(makeBitwiseNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
-  | '!' UnaryExpr                       { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalNotNode(GLOBAL_DATA, $2.m_node), $2.m_features, $2.m_numConstants); }
-
-UnaryExpr:
-    PostfixExpr
-  | UnaryExprCommon
-;
-
-UnaryExprNoBF:
-    PostfixExprNoBF
-  | UnaryExprCommon
-;
-
-MultiplicativeExpr:
-    UnaryExpr
-  | MultiplicativeExpr '*' UnaryExpr    { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | MultiplicativeExpr '/' UnaryExpr    { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | MultiplicativeExpr '%' UnaryExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-MultiplicativeExprNoBF:
-    UnaryExprNoBF
-  | MultiplicativeExprNoBF '*' UnaryExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | MultiplicativeExprNoBF '/' UnaryExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | MultiplicativeExprNoBF '%' UnaryExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ModNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-AdditiveExpr:
-    MultiplicativeExpr
-  | AdditiveExpr '+' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | AdditiveExpr '-' MultiplicativeExpr { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-AdditiveExprNoBF:
-    MultiplicativeExprNoBF
-  | AdditiveExprNoBF '+' MultiplicativeExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | AdditiveExprNoBF '-' MultiplicativeExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ShiftExpr:
-    AdditiveExpr
-  | ShiftExpr LSHIFT AdditiveExpr       { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | ShiftExpr RSHIFT AdditiveExpr       { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | ShiftExpr URSHIFT AdditiveExpr      { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ShiftExprNoBF:
-    AdditiveExprNoBF
-  | ShiftExprNoBF LSHIFT AdditiveExpr   { $$ = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | ShiftExprNoBF RSHIFT AdditiveExpr   { $$ = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | ShiftExprNoBF URSHIFT AdditiveExpr  { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnsignedRightShiftNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-RelationalExpr:
-    ShiftExpr
-  | RelationalExpr '<' ShiftExpr        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExpr '>' ShiftExpr        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExpr LE ShiftExpr         { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExpr GE ShiftExpr         { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExpr INSTANCEOF ShiftExpr { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExpr INTOKEN ShiftExpr    { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-RelationalExprNoIn:
-    ShiftExpr
-  | RelationalExprNoIn '<' ShiftExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoIn '>' ShiftExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoIn LE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoIn GE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoIn INSTANCEOF ShiftExpr
-                                        { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-RelationalExprNoBF:
-    ShiftExprNoBF
-  | RelationalExprNoBF '<' ShiftExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoBF '>' ShiftExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoBF LE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoBF GE ShiftExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoBF INSTANCEOF ShiftExpr
-                                        { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | RelationalExprNoBF INTOKEN ShiftExpr 
-                                        { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @3.first_column, @3.last_column);  
-                                          $$ = createNodeInfo<ExpressionNode*>(node, $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-EqualityExpr:
-    RelationalExpr
-  | EqualityExpr EQEQ RelationalExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExpr NE RelationalExpr      { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExpr STREQ RelationalExpr   { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExpr STRNEQ RelationalExpr  { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-EqualityExprNoIn:
-    RelationalExprNoIn
-  | EqualityExprNoIn EQEQ RelationalExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExprNoIn NE RelationalExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExprNoIn STREQ RelationalExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExprNoIn STRNEQ RelationalExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-EqualityExprNoBF:
-    RelationalExprNoBF
-  | EqualityExprNoBF EQEQ RelationalExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExprNoBF NE RelationalExpr  { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExprNoBF STREQ RelationalExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-  | EqualityExprNoBF STRNEQ RelationalExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseANDExpr:
-    EqualityExpr
-  | BitwiseANDExpr '&' EqualityExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseANDExprNoIn:
-    EqualityExprNoIn
-  | BitwiseANDExprNoIn '&' EqualityExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseANDExprNoBF:
-    EqualityExprNoBF
-  | BitwiseANDExprNoBF '&' EqualityExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseXORExpr:
-    BitwiseANDExpr
-  | BitwiseXORExpr '^' BitwiseANDExpr   { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseXORExprNoIn:
-    BitwiseANDExprNoIn
-  | BitwiseXORExprNoIn '^' BitwiseANDExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseXORExprNoBF:
-    BitwiseANDExprNoBF
-  | BitwiseXORExprNoBF '^' BitwiseANDExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseORExpr:
-    BitwiseXORExpr
-  | BitwiseORExpr '|' BitwiseXORExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseORExprNoIn:
-    BitwiseXORExprNoIn
-  | BitwiseORExprNoIn '|' BitwiseXORExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-BitwiseORExprNoBF:
-    BitwiseXORExprNoBF
-  | BitwiseORExprNoBF '|' BitwiseXORExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, $1.m_node, $3.m_node, $3.m_features & AssignFeature), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalANDExpr:
-    BitwiseORExpr
-  | LogicalANDExpr AND BitwiseORExpr    { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalANDExprNoIn:
-    BitwiseORExprNoIn
-  | LogicalANDExprNoIn AND BitwiseORExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalANDExprNoBF:
-    BitwiseORExprNoBF
-  | LogicalANDExprNoBF AND BitwiseORExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalAnd), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalORExpr:
-    LogicalANDExpr
-  | LogicalORExpr OR LogicalANDExpr     { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalORExprNoIn:
-    LogicalANDExprNoIn
-  | LogicalORExprNoIn OR LogicalANDExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-LogicalORExprNoBF:
-    LogicalANDExprNoBF
-  | LogicalORExprNoBF OR LogicalANDExpr { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, $1.m_node, $3.m_node, OpLogicalOr), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ConditionalExpr:
-    LogicalORExpr
-  | LogicalORExpr '?' AssignmentExpr ':' AssignmentExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
-;
-
-ConditionalExprNoIn:
-    LogicalORExprNoIn
-  | LogicalORExprNoIn '?' AssignmentExprNoIn ':' AssignmentExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
-;
-
-ConditionalExprNoBF:
-    LogicalORExprNoBF
-  | LogicalORExprNoBF '?' AssignmentExpr ':' AssignmentExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, $1.m_node, $3.m_node, $5.m_node), $1.m_features | $3.m_features | $5.m_features, $1.m_numConstants + $3.m_numConstants + $5.m_numConstants); }
-;
-
-AssignmentExpr:
-    ConditionalExpr
-  | LeftHandSideExpr AssignmentOperator AssignmentExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature, 
-                                                                                                     @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants); 
-                                        }
-;
-
-AssignmentExprNoIn:
-    ConditionalExprNoIn
-  | LeftHandSideExpr AssignmentOperator AssignmentExprNoIn
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature, 
-                                                                                                     @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants);
-                                        }
-;
-
-AssignmentExprNoBF:
-    ConditionalExprNoBF
-  | LeftHandSideExprNoBF AssignmentOperator AssignmentExpr
-                                        { $$ = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, $1.m_node, $2, $3.m_node, $1.m_features & AssignFeature, $3.m_features & AssignFeature,
-                                                                                                     @1.first_column, @2.first_column + 1, @3.last_column), $1.m_features | $3.m_features | AssignFeature, $1.m_numConstants + $3.m_numConstants); 
-                                        }
-;
-
-AssignmentOperator:
-    '='                                 { $$ = OpEqual; }
-  | PLUSEQUAL                           { $$ = OpPlusEq; }
-  | MINUSEQUAL                          { $$ = OpMinusEq; }
-  | MULTEQUAL                           { $$ = OpMultEq; }
-  | DIVEQUAL                            { $$ = OpDivEq; }
-  | LSHIFTEQUAL                         { $$ = OpLShift; }
-  | RSHIFTEQUAL                         { $$ = OpRShift; }
-  | URSHIFTEQUAL                        { $$ = OpURShift; }
-  | ANDEQUAL                            { $$ = OpAndEq; }
-  | XOREQUAL                            { $$ = OpXOrEq; }
-  | OREQUAL                             { $$ = OpOrEq; }
-  | MODEQUAL                            { $$ = OpModEq; }
-;
-
-Expr:
-    AssignmentExpr
-  | Expr ',' AssignmentExpr             { $$ = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ExprNoIn:
-    AssignmentExprNoIn
-  | ExprNoIn ',' AssignmentExprNoIn     { $$ = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-ExprNoBF:
-    AssignmentExprNoBF
-  | ExprNoBF ',' AssignmentExpr         { $$ = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, $1.m_node, $3.m_node), $1.m_features | $3.m_features, $1.m_numConstants + $3.m_numConstants); }
-;
-
-Statement:
-    Block
-  | VariableStatement
-  | ConstStatement
-  | FunctionDeclaration
-  | EmptyStatement
-  | ExprStatement
-  | IfStatement
-  | IterationStatement
-  | ContinueStatement
-  | BreakStatement
-  | ReturnStatement
-  | WithStatement
-  | SwitchStatement
-  | LabelledStatement
-  | ThrowStatement
-  | TryStatement
-  | DebuggerStatement
-;
-
-Block:
-    OPENBRACE CLOSEBRACE                { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @2); }
-  | OPENBRACE SourceElements CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @3); }
-;
-
-VariableStatement:
-    VAR VariableDeclarationList ';'     { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @3); }
-  | VAR VariableDeclarationList error   { $$ = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, $2.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @2);
-                                          AUTO_SEMICOLON; }
-;
-
-VariableDeclarationList:
-    IDENT                               { $$.m_node = 0;
-                                          $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
-                                          $$.m_numConstants = 0;
-                                        }
-  | IDENT Initializer                   { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @2.first_column + 1, @2.last_column);
-                                          $$.m_node = node;
-                                          $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
-                                          $$.m_numConstants = $2.m_numConstants;
-                                        }
-  | VariableDeclarationList ',' IDENT
-                                        { $$.m_node = $1.m_node;
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
-                                          $$.m_numConstants = $1.m_numConstants;
-                                        }
-  | VariableDeclarationList ',' IDENT Initializer
-                                        { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
-                                          setExceptionLocation(node, @3.first_column, @4.first_column + 1, @4.last_column);
-                                          $$.m_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
-                                        }
-;
-
-VariableDeclarationListNoIn:
-    IDENT                               { $$.m_node = 0;
-                                          $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, 0);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
-                                          $$.m_numConstants = 0;
-                                        }
-  | IDENT InitializerNoIn               { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$1, $2.m_node, $2.m_features & AssignFeature);
-                                          setExceptionLocation(node, @1.first_column, @2.first_column + 1, @2.last_column);
-                                          $$.m_node = node;
-                                          $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$1, DeclarationStacks::HasInitializer);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features;
-                                          $$.m_numConstants = $2.m_numConstants;
-                                        }
-  | VariableDeclarationListNoIn ',' IDENT
-                                        { $$.m_node = $1.m_node;
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, 0);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
-                                          $$.m_numConstants = $1.m_numConstants;
-                                        }
-  | VariableDeclarationListNoIn ',' IDENT InitializerNoIn
-                                        { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *$3, $4.m_node, $4.m_features & AssignFeature);
-                                          setExceptionLocation(node, @3.first_column, @4.first_column + 1, @4.last_column);
-                                          $$.m_node = combineCommaNodes(GLOBAL_DATA, $1.m_node, node);
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, *$3, DeclarationStacks::HasInitializer);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $4.m_numConstants;
-                                        }
-;
-
-ConstStatement:
-    CONSTTOKEN ConstDeclarationList ';' { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @3); }
-  | CONSTTOKEN ConstDeclarationList error
-                                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, $2.m_node.head), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-ConstDeclarationList:
-    ConstDeclaration                    { $$.m_node.head = $1.m_node;
-                                          $$.m_node.tail = $$.m_node.head;
-                                          $$.m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $1.m_node);
-                                          $$.m_funcDeclarations = 0; 
-                                          $$.m_features = $1.m_features;
-                                          $$.m_numConstants = $1.m_numConstants;
-    }
-  | ConstDeclarationList ',' ConstDeclaration
-                                        { $$.m_node.head = $1.m_node.head;
-                                          $1.m_node.tail->m_next = $3.m_node;
-                                          $$.m_node.tail = $3.m_node;
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          appendToVarDeclarationList(GLOBAL_DATA, $$.m_varDeclarations, $3.m_node);
-                                          $$.m_funcDeclarations = 0;
-                                          $$.m_features = $1.m_features | $3.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $3.m_numConstants; }
-;
-
-ConstDeclaration:
-    IDENT                               { $$ = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *$1, 0), (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); }
-  | IDENT Initializer                   { $$ = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *$1, $2.m_node), ((*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $2.m_features, $2.m_numConstants); }
-;
-
-Initializer:
-    '=' AssignmentExpr                  { $$ = $2; }
-;
-
-InitializerNoIn:
-    '=' AssignmentExprNoIn              { $$ = $2; }
-;
-
-EmptyStatement:
-    ';'                                 { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); }
-;
-
-ExprStatement:
-    ExprNoBF ';'                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @2); }
-  | ExprNoBF error                      { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, $1.m_node), 0, 0, $1.m_features, $1.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
-;
-
-IfStatement:
-    IF '(' Expr ')' Statement %prec IF_WITHOUT_ELSE
-                                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @4); }
-  | IF '(' Expr ')' Statement ELSE Statement
-                                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfElseNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node), 
-                                                                                         mergeDeclarationLists($5.m_varDeclarations, $7.m_varDeclarations),
-                                                                                         mergeDeclarationLists($5.m_funcDeclarations, $7.m_funcDeclarations),
-                                                                                         $3.m_features | $5.m_features | $7.m_features,
-                                                                                         $3.m_numConstants + $5.m_numConstants + $7.m_numConstants); 
-                                          setStatementLocation($$.m_node, @1, @4); }
-;
-
-IterationStatement:
-    DO Statement WHILE '(' Expr ')' ';'    { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
-                                             setStatementLocation($$.m_node, @1, @3); }
-  | DO Statement WHILE '(' Expr ')' error  { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, $2.m_node, $5.m_node), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features | $5.m_features, $2.m_numConstants + $5.m_numConstants);
-                                             setStatementLocation($$.m_node, @1, @3); } // Always performs automatic semicolon insertion.
-  | WHILE '(' Expr ')' Statement        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WhileNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @4); }
-  | FOR '(' ExprNoInOpt ';' ExprOpt ';' ExprOpt ')' Statement
-                                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node, $9.m_node, false), $9.m_varDeclarations, $9.m_funcDeclarations, 
-                                                                                         $3.m_features | $5.m_features | $7.m_features | $9.m_features,
-                                                                                         $3.m_numConstants + $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @8); 
-                                        }
-  | FOR '(' VAR VariableDeclarationListNoIn ';' ExprOpt ';' ExprOpt ')' Statement
-                                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, $4.m_node, $6.m_node, $8.m_node, $10.m_node, true),
-                                                                                         mergeDeclarationLists($4.m_varDeclarations, $10.m_varDeclarations),
-                                                                                         mergeDeclarationLists($4.m_funcDeclarations, $10.m_funcDeclarations),
-                                                                                         $4.m_features | $6.m_features | $8.m_features | $10.m_features,
-                                                                                         $4.m_numConstants + $6.m_numConstants + $8.m_numConstants + $10.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @9); }
-  | FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
-                                        {
-                                            ForInNode* node = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, $3.m_node, $5.m_node, $7.m_node);
-                                            setExceptionLocation(node, @3.first_column, @3.last_column, @5.last_column);
-                                            $$ = createNodeDeclarationInfo<StatementNode*>(node, $7.m_varDeclarations, $7.m_funcDeclarations,
-                                                                                           $3.m_features | $5.m_features | $7.m_features,
-                                                                                           $3.m_numConstants + $5.m_numConstants + $7.m_numConstants);
-                                            setStatementLocation($$.m_node, @1, @6);
-                                        }
-  | FOR '(' VAR IDENT INTOKEN Expr ')' Statement
-                                        { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, 0, $6.m_node, $8.m_node, @5.first_column, @5.first_column - @4.first_column, @6.last_column - @5.first_column);
-                                          setExceptionLocation(forIn, @4.first_column, @5.first_column + 1, @6.last_column);
-                                          appendToVarDeclarationList(GLOBAL_DATA, $8.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $8.m_varDeclarations, $8.m_funcDeclarations, ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $6.m_features | $8.m_features, $6.m_numConstants + $8.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @7); }
-  | FOR '(' VAR IDENT InitializerNoIn INTOKEN Expr ')' Statement
-                                        { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *$4, $5.m_node, $7.m_node, $9.m_node, @5.first_column, @5.first_column - @4.first_column, @5.last_column - @5.first_column);
-                                          setExceptionLocation(forIn, @4.first_column, @6.first_column + 1, @7.last_column);
-                                          appendToVarDeclarationList(GLOBAL_DATA, $9.m_varDeclarations, *$4, DeclarationStacks::HasInitializer);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(forIn, $9.m_varDeclarations, $9.m_funcDeclarations,
-                                                                                         ((*$4 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $5.m_features | $7.m_features | $9.m_features,
-                                                                                         $5.m_numConstants + $7.m_numConstants + $9.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @8); }
-;
-
-ExprOpt:
-    /* nothing */                       { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
-  | Expr
-;
-
-ExprNoInOpt:
-    /* nothing */                       { $$ = createNodeInfo<ExpressionNode*>(0, 0, 0); }
-  | ExprNoIn
-;
-
-ContinueStatement:
-    CONTINUE ';'                        { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @2); }
-  | CONTINUE error                      { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
-  | CONTINUE IDENT ';'                  { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @3); }
-  | CONTINUE IDENT error                { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *$2);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-BreakStatement:
-    BREAK ';'                           { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @2); }
-  | BREAK error                         { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA);
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA), 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
-  | BREAK IDENT ';'                     { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @3); }
-  | BREAK IDENT error                   { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *$2), 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-ReturnStatement:
-    RETURN ';'                          { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); 
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @2); }
-  | RETURN error                        { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); 
-                                          setExceptionLocation(node, @1.first_column, @1.last_column, @1.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
-  | RETURN Expr ';'                     { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); 
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @3); }
-  | RETURN Expr error                   { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, $2.m_node); 
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column); 
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; }
-;
-
-WithStatement:
-    WITH '(' Expr ')' Statement         { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WithNode(GLOBAL_DATA, $3.m_node, $5.m_node, @3.last_column, @3.last_column - @3.first_column),
-                                                                                         $5.m_varDeclarations, $5.m_funcDeclarations, $3.m_features | $5.m_features | WithFeature, $3.m_numConstants + $5.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @4); }
-;
-
-SwitchStatement:
-    SWITCH '(' Expr ')' CaseBlock       { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) SwitchNode(GLOBAL_DATA, $3.m_node, $5.m_node), $5.m_varDeclarations, $5.m_funcDeclarations,
-                                                                                         $3.m_features | $5.m_features, $3.m_numConstants + $5.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @4); }
-;
-
-CaseBlock:
-    OPENBRACE CaseClausesOpt CLOSEBRACE              { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) CaseBlockNode(GLOBAL_DATA, $2.m_node.head, 0, 0), $2.m_varDeclarations, $2.m_funcDeclarations, $2.m_features, $2.m_numConstants); }
-  | OPENBRACE CaseClausesOpt DefaultClause CaseClausesOpt CLOSEBRACE
-                                        { $$ = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) CaseBlockNode(GLOBAL_DATA, $2.m_node.head, $3.m_node, $4.m_node.head),
-                                                                                         mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $3.m_varDeclarations), $4.m_varDeclarations),
-                                                                                         mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $3.m_funcDeclarations), $4.m_funcDeclarations),
-                                                                                         $2.m_features | $3.m_features | $4.m_features,
-                                                                                         $2.m_numConstants + $3.m_numConstants + $4.m_numConstants); }
-;
-
-CaseClausesOpt:
-  /* nothing */                         { $$.m_node.head = 0; $$.m_node.tail = 0; $$.m_varDeclarations = 0; $$.m_funcDeclarations = 0; $$.m_features = 0; $$.m_numConstants = 0; }
-  | CaseClauses
-;
-
-CaseClauses:
-    CaseClause                          { $$.m_node.head = new (GLOBAL_DATA) ClauseListNode(GLOBAL_DATA, $1.m_node);
-                                          $$.m_node.tail = $$.m_node.head;
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          $$.m_funcDeclarations = $1.m_funcDeclarations; 
-                                          $$.m_features = $1.m_features;
-                                          $$.m_numConstants = $1.m_numConstants; }
-  | CaseClauses CaseClause              { $$.m_node.head = $1.m_node.head;
-                                          $$.m_node.tail = new (GLOBAL_DATA) ClauseListNode(GLOBAL_DATA, $1.m_node.tail, $2.m_node);
-                                          $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
-                                          $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
-                                          $$.m_features = $1.m_features | $2.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
-                                        }
-;
-
-CaseClause:
-    CASE Expr ':'                       { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, $2.m_node), 0, 0, $2.m_features, $2.m_numConstants); }
-  | CASE Expr ':' SourceElements        { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, $2.m_node, $4.m_node), $4.m_varDeclarations, $4.m_funcDeclarations, $2.m_features | $4.m_features, $2.m_numConstants + $4.m_numConstants); }
-;
-
-DefaultClause:
-    DEFAULT ':'                         { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); }
-  | DEFAULT ':' SourceElements          { $$ = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0, $3.m_node), $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
-;
-
-LabelledStatement:
-    IDENT ':' Statement                 { LabelNode* node = new (GLOBAL_DATA) LabelNode(GLOBAL_DATA, *$1, $3.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, $3.m_varDeclarations, $3.m_funcDeclarations, $3.m_features, $3.m_numConstants); }
-;
-
-ThrowStatement:
-    THROW Expr ';'                      { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @2);
-                                        }
-  | THROW Expr error                    { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, $2.m_node);
-                                          setExceptionLocation(node, @1.first_column, @2.last_column, @2.last_column);
-                                          $$ = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, $2.m_features, $2.m_numConstants); setStatementLocation($$.m_node, @1, @2); AUTO_SEMICOLON; 
-                                        }
-;
-
-TryStatement:
-    TRY Block FINALLY Block             { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node),
-                                                                                         mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations),
-                                                                                         mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations),
-                                                                                         $2.m_features | $4.m_features,
-                                                                                         $2.m_numConstants + $4.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @2); }
-  | TRY Block CATCH '(' IDENT ')' Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, 0),
-                                                                                         mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations),
-                                                                                         mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations),
-                                                                                         $2.m_features | $7.m_features | CatchFeature,
-                                                                                         $2.m_numConstants + $7.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @2); }
-  | TRY Block CATCH '(' IDENT ')' Block FINALLY Block
-                                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, *$5, ($7.m_features & EvalFeature) != 0, $7.m_node, $9.m_node),
-                                                                                         mergeDeclarationLists(mergeDeclarationLists($2.m_varDeclarations, $7.m_varDeclarations), $9.m_varDeclarations),
-                                                                                         mergeDeclarationLists(mergeDeclarationLists($2.m_funcDeclarations, $7.m_funcDeclarations), $9.m_funcDeclarations),
-                                                                                         $2.m_features | $7.m_features | $9.m_features | CatchFeature,
-                                                                                         $2.m_numConstants + $7.m_numConstants + $9.m_numConstants);
-                                          setStatementLocation($$.m_node, @1, @2); }
-;
-
-DebuggerStatement:
-    DEBUGGER ';'                        { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @2); }
-  | DEBUGGER error                      { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0);
-                                          setStatementLocation($$.m_node, @1, @1); AUTO_SEMICOLON; }
-;
-
-FunctionDeclaration:
-    FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) FuncDeclNode(GLOBAL_DATA, *$2, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line)), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); setStatementLocation($6, @5, @7); $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)->body()); }
-  | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
-      {
-          $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) FuncDeclNode(GLOBAL_DATA, *$2, $7, GLOBAL_DATA->lexer->sourceCode($6, $8, @6.first_line), $4.m_node.head), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*$2 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | $4.m_features | ClosureFeature, 0);
-          if ($4.m_features & ArgumentsFeature)
-              $7->setUsesArguments();
-          setStatementLocation($7, @6, @8);
-          $$.m_funcDeclarations->data.append(static_cast<FuncDeclNode*>($$.m_node)->body());
-      }
-;
-
-FunctionExpr:
-    FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, GLOBAL_DATA->lexer->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); setStatementLocation($5, @4, @6); }
-    | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
-      {
-          $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0);
-          if ($3.m_features & ArgumentsFeature)
-              $6->setUsesArguments();
-          setStatementLocation($6, @5, @7);
-      }
-  | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, *$2, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line)), ClosureFeature, 0); setStatementLocation($6, @5, @7); }
-  | FUNCTION IDENT '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE
-      {
-          $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, *$2, $7, GLOBAL_DATA->lexer->sourceCode($6, $8, @6.first_line), $4.m_node.head), $4.m_features | ClosureFeature, 0); 
-          if ($4.m_features & ArgumentsFeature)
-              $7->setUsesArguments();
-          setStatementLocation($7, @6, @8);
-      }
-;
-
-FormalParameterList:
-    IDENT                               { $$.m_node.head = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, *$1);
-                                          $$.m_features = (*$1 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0;
-                                          $$.m_node.tail = $$.m_node.head; }
-  | FormalParameterList ',' IDENT       { $$.m_node.head = $1.m_node.head;
-                                          $$.m_features = $1.m_features | ((*$3 == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0);
-                                          $$.m_node.tail = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, $1.m_node.tail, *$3);  }
-;
-
-FunctionBody:
-    /* not in spec */                   { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
-  | SourceElements_NoNode               { $$ = FunctionBodyNode::create(GLOBAL_DATA); }
-;
-
-Program:
-    /* not in spec */                   { GLOBAL_DATA->parser->didFinishParsing(new (GLOBAL_DATA) SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, @0.last_line, 0); }
-    | SourceElements                    { GLOBAL_DATA->parser->didFinishParsing($1.m_node, $1.m_varDeclarations, $1.m_funcDeclarations, $1.m_features, 
-                                                                                @1.last_line, $1.m_numConstants); }
-;
-
-SourceElements:
-    Statement                           { $$.m_node = new (GLOBAL_DATA) SourceElements(GLOBAL_DATA);
-                                          $$.m_node->append($1.m_node);
-                                          $$.m_varDeclarations = $1.m_varDeclarations;
-                                          $$.m_funcDeclarations = $1.m_funcDeclarations;
-                                          $$.m_features = $1.m_features;
-                                          $$.m_numConstants = $1.m_numConstants;
-                                        }
-  | SourceElements Statement            { $$.m_node->append($2.m_node);
-                                          $$.m_varDeclarations = mergeDeclarationLists($1.m_varDeclarations, $2.m_varDeclarations);
-                                          $$.m_funcDeclarations = mergeDeclarationLists($1.m_funcDeclarations, $2.m_funcDeclarations);
-                                          $$.m_features = $1.m_features | $2.m_features;
-                                          $$.m_numConstants = $1.m_numConstants + $2.m_numConstants;
-                                        }
-;
-// Start NoNodes
-
-Literal_NoNode:
-    NULLTOKEN
-  | TRUETOKEN
-  | FALSETOKEN
-  | NUMBER { }
-  | STRING { }
-  | '/' /* regexp */ { if (!GLOBAL_DATA->lexer->skipRegExp()) YYABORT; }
-  | DIVEQUAL /* regexp with /= */ { if (!GLOBAL_DATA->lexer->skipRegExp()) YYABORT; }
-;
-
-Property_NoNode:
-    IDENT ':' AssignmentExpr_NoNode { }
-  | STRING ':' AssignmentExpr_NoNode { }
-  | NUMBER ':' AssignmentExpr_NoNode { }
-  | IDENT IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
-  | IDENT IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE { if (*$1 != "get" && *$1 != "set") YYABORT; }
-;
-
-PropertyList_NoNode:
-    Property_NoNode
-  | PropertyList_NoNode ',' Property_NoNode
-;
-
-PrimaryExpr_NoNode:
-    PrimaryExprNoBrace_NoNode
-  | OPENBRACE CLOSEBRACE { }
-  | OPENBRACE PropertyList_NoNode CLOSEBRACE { }
-  /* allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939 */
-  | OPENBRACE PropertyList_NoNode ',' CLOSEBRACE { }
-;
-
-PrimaryExprNoBrace_NoNode:
-    THISTOKEN
-  | Literal_NoNode
-  | ArrayLiteral_NoNode
-  | IDENT { }
-  | '(' Expr_NoNode ')'
-;
-
-ArrayLiteral_NoNode:
-    '[' ElisionOpt_NoNode ']'
-  | '[' ElementList_NoNode ']'
-  | '[' ElementList_NoNode ',' ElisionOpt_NoNode ']'
-;
-
-ElementList_NoNode:
-    ElisionOpt_NoNode AssignmentExpr_NoNode
-  | ElementList_NoNode ',' ElisionOpt_NoNode AssignmentExpr_NoNode
-;
-
-ElisionOpt_NoNode:
-    /* nothing */
-  | Elision_NoNode
-;
-
-Elision_NoNode:
-    ','
-  | Elision_NoNode ','
-;
-
-MemberExpr_NoNode:
-    PrimaryExpr_NoNode
-  | FunctionExpr_NoNode
-  | MemberExpr_NoNode '[' Expr_NoNode ']'
-  | MemberExpr_NoNode '.' IDENT
-  | NEW MemberExpr_NoNode Arguments_NoNode
-;
-
-MemberExprNoBF_NoNode:
-    PrimaryExprNoBrace_NoNode
-  | MemberExprNoBF_NoNode '[' Expr_NoNode ']'
-  | MemberExprNoBF_NoNode '.' IDENT
-  | NEW MemberExpr_NoNode Arguments_NoNode
-;
-
-NewExpr_NoNode:
-    MemberExpr_NoNode
-  | NEW NewExpr_NoNode
-;
-
-NewExprNoBF_NoNode:
-    MemberExprNoBF_NoNode
-  | NEW NewExpr_NoNode
-;
-
-CallExpr_NoNode:
-    MemberExpr_NoNode Arguments_NoNode
-  | CallExpr_NoNode Arguments_NoNode
-  | CallExpr_NoNode '[' Expr_NoNode ']'
-  | CallExpr_NoNode '.' IDENT
-;
-
-CallExprNoBF_NoNode:
-    MemberExprNoBF_NoNode Arguments_NoNode
-  | CallExprNoBF_NoNode Arguments_NoNode
-  | CallExprNoBF_NoNode '[' Expr_NoNode ']'
-  | CallExprNoBF_NoNode '.' IDENT
-;
-
-Arguments_NoNode:
-    '(' ')'
-  | '(' ArgumentList_NoNode ')'
-;
-
-ArgumentList_NoNode:
-    AssignmentExpr_NoNode
-  | ArgumentList_NoNode ',' AssignmentExpr_NoNode
-;
-
-LeftHandSideExpr_NoNode:
-    NewExpr_NoNode
-  | CallExpr_NoNode
-;
-
-LeftHandSideExprNoBF_NoNode:
-    NewExprNoBF_NoNode
-  | CallExprNoBF_NoNode
-;
-
-PostfixExpr_NoNode:
-    LeftHandSideExpr_NoNode
-  | LeftHandSideExpr_NoNode PLUSPLUS
-  | LeftHandSideExpr_NoNode MINUSMINUS
-;
-
-PostfixExprNoBF_NoNode:
-    LeftHandSideExprNoBF_NoNode
-  | LeftHandSideExprNoBF_NoNode PLUSPLUS
-  | LeftHandSideExprNoBF_NoNode MINUSMINUS
-;
-
-UnaryExprCommon_NoNode:
-    DELETETOKEN UnaryExpr_NoNode
-  | VOIDTOKEN UnaryExpr_NoNode
-  | TYPEOF UnaryExpr_NoNode
-  | PLUSPLUS UnaryExpr_NoNode
-  | AUTOPLUSPLUS UnaryExpr_NoNode
-  | MINUSMINUS UnaryExpr_NoNode
-  | AUTOMINUSMINUS UnaryExpr_NoNode
-  | '+' UnaryExpr_NoNode
-  | '-' UnaryExpr_NoNode
-  | '~' UnaryExpr_NoNode
-  | '!' UnaryExpr_NoNode
-
-UnaryExpr_NoNode:
-    PostfixExpr_NoNode
-  | UnaryExprCommon_NoNode
-;
-
-UnaryExprNoBF_NoNode:
-    PostfixExprNoBF_NoNode
-  | UnaryExprCommon_NoNode
-;
-
-MultiplicativeExpr_NoNode:
-    UnaryExpr_NoNode
-  | MultiplicativeExpr_NoNode '*' UnaryExpr_NoNode
-  | MultiplicativeExpr_NoNode '/' UnaryExpr_NoNode
-  | MultiplicativeExpr_NoNode '%' UnaryExpr_NoNode
-;
-
-MultiplicativeExprNoBF_NoNode:
-    UnaryExprNoBF_NoNode
-  | MultiplicativeExprNoBF_NoNode '*' UnaryExpr_NoNode
-  | MultiplicativeExprNoBF_NoNode '/' UnaryExpr_NoNode
-  | MultiplicativeExprNoBF_NoNode '%' UnaryExpr_NoNode
-;
-
-AdditiveExpr_NoNode:
-    MultiplicativeExpr_NoNode
-  | AdditiveExpr_NoNode '+' MultiplicativeExpr_NoNode
-  | AdditiveExpr_NoNode '-' MultiplicativeExpr_NoNode
-;
-
-AdditiveExprNoBF_NoNode:
-    MultiplicativeExprNoBF_NoNode
-  | AdditiveExprNoBF_NoNode '+' MultiplicativeExpr_NoNode
-  | AdditiveExprNoBF_NoNode '-' MultiplicativeExpr_NoNode
-;
-
-ShiftExpr_NoNode:
-    AdditiveExpr_NoNode
-  | ShiftExpr_NoNode LSHIFT AdditiveExpr_NoNode
-  | ShiftExpr_NoNode RSHIFT AdditiveExpr_NoNode
-  | ShiftExpr_NoNode URSHIFT AdditiveExpr_NoNode
-;
-
-ShiftExprNoBF_NoNode:
-    AdditiveExprNoBF_NoNode
-  | ShiftExprNoBF_NoNode LSHIFT AdditiveExpr_NoNode
-  | ShiftExprNoBF_NoNode RSHIFT AdditiveExpr_NoNode
-  | ShiftExprNoBF_NoNode URSHIFT AdditiveExpr_NoNode
-;
-
-RelationalExpr_NoNode:
-    ShiftExpr_NoNode
-  | RelationalExpr_NoNode '<' ShiftExpr_NoNode
-  | RelationalExpr_NoNode '>' ShiftExpr_NoNode
-  | RelationalExpr_NoNode LE ShiftExpr_NoNode
-  | RelationalExpr_NoNode GE ShiftExpr_NoNode
-  | RelationalExpr_NoNode INSTANCEOF ShiftExpr_NoNode
-  | RelationalExpr_NoNode INTOKEN ShiftExpr_NoNode
-;
-
-RelationalExprNoIn_NoNode:
-    ShiftExpr_NoNode
-  | RelationalExprNoIn_NoNode '<' ShiftExpr_NoNode
-  | RelationalExprNoIn_NoNode '>' ShiftExpr_NoNode
-  | RelationalExprNoIn_NoNode LE ShiftExpr_NoNode
-  | RelationalExprNoIn_NoNode GE ShiftExpr_NoNode
-  | RelationalExprNoIn_NoNode INSTANCEOF ShiftExpr_NoNode
-;
-
-RelationalExprNoBF_NoNode:
-    ShiftExprNoBF_NoNode
-  | RelationalExprNoBF_NoNode '<' ShiftExpr_NoNode
-  | RelationalExprNoBF_NoNode '>' ShiftExpr_NoNode
-  | RelationalExprNoBF_NoNode LE ShiftExpr_NoNode
-  | RelationalExprNoBF_NoNode GE ShiftExpr_NoNode
-  | RelationalExprNoBF_NoNode INSTANCEOF ShiftExpr_NoNode
-  | RelationalExprNoBF_NoNode INTOKEN ShiftExpr_NoNode
-;
-
-EqualityExpr_NoNode:
-    RelationalExpr_NoNode
-  | EqualityExpr_NoNode EQEQ RelationalExpr_NoNode
-  | EqualityExpr_NoNode NE RelationalExpr_NoNode
-  | EqualityExpr_NoNode STREQ RelationalExpr_NoNode
-  | EqualityExpr_NoNode STRNEQ RelationalExpr_NoNode
-;
-
-EqualityExprNoIn_NoNode:
-    RelationalExprNoIn_NoNode
-  | EqualityExprNoIn_NoNode EQEQ RelationalExprNoIn_NoNode
-  | EqualityExprNoIn_NoNode NE RelationalExprNoIn_NoNode
-  | EqualityExprNoIn_NoNode STREQ RelationalExprNoIn_NoNode
-  | EqualityExprNoIn_NoNode STRNEQ RelationalExprNoIn_NoNode
-;
-
-EqualityExprNoBF_NoNode:
-    RelationalExprNoBF_NoNode
-  | EqualityExprNoBF_NoNode EQEQ RelationalExpr_NoNode
-  | EqualityExprNoBF_NoNode NE RelationalExpr_NoNode
-  | EqualityExprNoBF_NoNode STREQ RelationalExpr_NoNode
-  | EqualityExprNoBF_NoNode STRNEQ RelationalExpr_NoNode
-;
-
-BitwiseANDExpr_NoNode:
-    EqualityExpr_NoNode
-  | BitwiseANDExpr_NoNode '&' EqualityExpr_NoNode
-;
-
-BitwiseANDExprNoIn_NoNode:
-    EqualityExprNoIn_NoNode
-  | BitwiseANDExprNoIn_NoNode '&' EqualityExprNoIn_NoNode
-;
-
-BitwiseANDExprNoBF_NoNode:
-    EqualityExprNoBF_NoNode
-  | BitwiseANDExprNoBF_NoNode '&' EqualityExpr_NoNode
-;
-
-BitwiseXORExpr_NoNode:
-    BitwiseANDExpr_NoNode
-  | BitwiseXORExpr_NoNode '^' BitwiseANDExpr_NoNode
-;
-
-BitwiseXORExprNoIn_NoNode:
-    BitwiseANDExprNoIn_NoNode
-  | BitwiseXORExprNoIn_NoNode '^' BitwiseANDExprNoIn_NoNode
-;
-
-BitwiseXORExprNoBF_NoNode:
-    BitwiseANDExprNoBF_NoNode
-  | BitwiseXORExprNoBF_NoNode '^' BitwiseANDExpr_NoNode
-;
-
-BitwiseORExpr_NoNode:
-    BitwiseXORExpr_NoNode
-  | BitwiseORExpr_NoNode '|' BitwiseXORExpr_NoNode
-;
-
-BitwiseORExprNoIn_NoNode:
-    BitwiseXORExprNoIn_NoNode
-  | BitwiseORExprNoIn_NoNode '|' BitwiseXORExprNoIn_NoNode
-;
-
-BitwiseORExprNoBF_NoNode:
-    BitwiseXORExprNoBF_NoNode
-  | BitwiseORExprNoBF_NoNode '|' BitwiseXORExpr_NoNode
-;
-
-LogicalANDExpr_NoNode:
-    BitwiseORExpr_NoNode
-  | LogicalANDExpr_NoNode AND BitwiseORExpr_NoNode
-;
-
-LogicalANDExprNoIn_NoNode:
-    BitwiseORExprNoIn_NoNode
-  | LogicalANDExprNoIn_NoNode AND BitwiseORExprNoIn_NoNode
-;
-
-LogicalANDExprNoBF_NoNode:
-    BitwiseORExprNoBF_NoNode
-  | LogicalANDExprNoBF_NoNode AND BitwiseORExpr_NoNode
-;
-
-LogicalORExpr_NoNode:
-    LogicalANDExpr_NoNode
-  | LogicalORExpr_NoNode OR LogicalANDExpr_NoNode
-;
-
-LogicalORExprNoIn_NoNode:
-    LogicalANDExprNoIn_NoNode
-  | LogicalORExprNoIn_NoNode OR LogicalANDExprNoIn_NoNode
-;
-
-LogicalORExprNoBF_NoNode:
-    LogicalANDExprNoBF_NoNode
-  | LogicalORExprNoBF_NoNode OR LogicalANDExpr_NoNode
-;
-
-ConditionalExpr_NoNode:
-    LogicalORExpr_NoNode
-  | LogicalORExpr_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
-;
-
-ConditionalExprNoIn_NoNode:
-    LogicalORExprNoIn_NoNode
-  | LogicalORExprNoIn_NoNode '?' AssignmentExprNoIn_NoNode ':' AssignmentExprNoIn_NoNode
-;
-
-ConditionalExprNoBF_NoNode:
-    LogicalORExprNoBF_NoNode
-  | LogicalORExprNoBF_NoNode '?' AssignmentExpr_NoNode ':' AssignmentExpr_NoNode
-;
-
-AssignmentExpr_NoNode:
-    ConditionalExpr_NoNode
-  | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
-;
-
-AssignmentExprNoIn_NoNode:
-    ConditionalExprNoIn_NoNode
-  | LeftHandSideExpr_NoNode AssignmentOperator_NoNode AssignmentExprNoIn_NoNode
-;
-
-AssignmentExprNoBF_NoNode:
-    ConditionalExprNoBF_NoNode
-  | LeftHandSideExprNoBF_NoNode AssignmentOperator_NoNode AssignmentExpr_NoNode
-;
-
-AssignmentOperator_NoNode:
-    '='
-  | PLUSEQUAL
-  | MINUSEQUAL
-  | MULTEQUAL
-  | DIVEQUAL
-  | LSHIFTEQUAL
-  | RSHIFTEQUAL
-  | URSHIFTEQUAL
-  | ANDEQUAL
-  | XOREQUAL
-  | OREQUAL
-  | MODEQUAL
-;
-
-Expr_NoNode:
-    AssignmentExpr_NoNode
-  | Expr_NoNode ',' AssignmentExpr_NoNode
-;
-
-ExprNoIn_NoNode:
-    AssignmentExprNoIn_NoNode
-  | ExprNoIn_NoNode ',' AssignmentExprNoIn_NoNode
-;
-
-ExprNoBF_NoNode:
-    AssignmentExprNoBF_NoNode
-  | ExprNoBF_NoNode ',' AssignmentExpr_NoNode
-;
-
-Statement_NoNode:
-    Block_NoNode
-  | VariableStatement_NoNode
-  | ConstStatement_NoNode
-  | FunctionDeclaration_NoNode
-  | EmptyStatement_NoNode
-  | ExprStatement_NoNode
-  | IfStatement_NoNode
-  | IterationStatement_NoNode
-  | ContinueStatement_NoNode
-  | BreakStatement_NoNode
-  | ReturnStatement_NoNode
-  | WithStatement_NoNode
-  | SwitchStatement_NoNode
-  | LabelledStatement_NoNode
-  | ThrowStatement_NoNode
-  | TryStatement_NoNode
-  | DebuggerStatement_NoNode
-;
-
-Block_NoNode:
-    OPENBRACE CLOSEBRACE { }
-  | OPENBRACE SourceElements_NoNode CLOSEBRACE { }
-;
-
-VariableStatement_NoNode:
-    VAR VariableDeclarationList_NoNode ';'
-  | VAR VariableDeclarationList_NoNode error { AUTO_SEMICOLON; }
-;
-
-VariableDeclarationList_NoNode:
-    IDENT { }
-  | IDENT Initializer_NoNode { }
-  | VariableDeclarationList_NoNode ',' IDENT
-  | VariableDeclarationList_NoNode ',' IDENT Initializer_NoNode
-;
-
-VariableDeclarationListNoIn_NoNode:
-    IDENT { }
-  | IDENT InitializerNoIn_NoNode { }
-  | VariableDeclarationListNoIn_NoNode ',' IDENT
-  | VariableDeclarationListNoIn_NoNode ',' IDENT InitializerNoIn_NoNode
-;
-
-ConstStatement_NoNode:
-    CONSTTOKEN ConstDeclarationList_NoNode ';'
-  | CONSTTOKEN ConstDeclarationList_NoNode error { AUTO_SEMICOLON; }
-;
-
-ConstDeclarationList_NoNode:
-    ConstDeclaration_NoNode
-  | ConstDeclarationList_NoNode ',' ConstDeclaration_NoNode
-;
-
-ConstDeclaration_NoNode:
-    IDENT { }
-  | IDENT Initializer_NoNode { }
-;
-
-Initializer_NoNode:
-    '=' AssignmentExpr_NoNode
-;
-
-InitializerNoIn_NoNode:
-    '=' AssignmentExprNoIn_NoNode
-;
-
-EmptyStatement_NoNode:
-    ';'
-;
-
-ExprStatement_NoNode:
-    ExprNoBF_NoNode ';'
-  | ExprNoBF_NoNode error { AUTO_SEMICOLON; }
-;
-
-IfStatement_NoNode:
-    IF '(' Expr_NoNode ')' Statement_NoNode %prec IF_WITHOUT_ELSE
-  | IF '(' Expr_NoNode ')' Statement_NoNode ELSE Statement_NoNode
-;
-
-IterationStatement_NoNode:
-    DO Statement_NoNode WHILE '(' Expr_NoNode ')' ';'
-  | DO Statement_NoNode WHILE '(' Expr_NoNode ')' error // Always performs automatic semicolon insertion
-  | WHILE '(' Expr_NoNode ')' Statement_NoNode
-  | FOR '(' ExprNoInOpt_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
-  | FOR '(' VAR VariableDeclarationListNoIn_NoNode ';' ExprOpt_NoNode ';' ExprOpt_NoNode ')' Statement_NoNode
-  | FOR '(' LeftHandSideExpr_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
-  | FOR '(' VAR IDENT INTOKEN Expr_NoNode ')' Statement_NoNode
-  | FOR '(' VAR IDENT InitializerNoIn_NoNode INTOKEN Expr_NoNode ')' Statement_NoNode
-;
-
-ExprOpt_NoNode:
-    /* nothing */
-  | Expr_NoNode
-;
-
-ExprNoInOpt_NoNode:
-    /* nothing */
-  | ExprNoIn_NoNode
-;
-
-ContinueStatement_NoNode:
-    CONTINUE ';'
-  | CONTINUE error { AUTO_SEMICOLON; }
-  | CONTINUE IDENT ';'
-  | CONTINUE IDENT error { AUTO_SEMICOLON; }
-;
-
-BreakStatement_NoNode:
-    BREAK ';'
-  | BREAK error { AUTO_SEMICOLON; }
-  | BREAK IDENT ';'
-  | BREAK IDENT error { AUTO_SEMICOLON; }
-;
-
-ReturnStatement_NoNode:
-    RETURN ';'
-  | RETURN error { AUTO_SEMICOLON; }
-  | RETURN Expr_NoNode ';'
-  | RETURN Expr_NoNode error { AUTO_SEMICOLON; }
-;
-
-WithStatement_NoNode:
-    WITH '(' Expr_NoNode ')' Statement_NoNode
-;
-
-SwitchStatement_NoNode:
-    SWITCH '(' Expr_NoNode ')' CaseBlock_NoNode
-;
-
-CaseBlock_NoNode:
-    OPENBRACE CaseClausesOpt_NoNode CLOSEBRACE { }
-  | OPENBRACE CaseClausesOpt_NoNode DefaultClause_NoNode CaseClausesOpt_NoNode CLOSEBRACE { }
-;
-
-CaseClausesOpt_NoNode:
-    /* nothing */
-  | CaseClauses_NoNode
-;
-
-CaseClauses_NoNode:
-    CaseClause_NoNode
-  | CaseClauses_NoNode CaseClause_NoNode
-;
-
-CaseClause_NoNode:
-    CASE Expr_NoNode ':'
-  | CASE Expr_NoNode ':' SourceElements_NoNode
-;
-
-DefaultClause_NoNode:
-    DEFAULT ':'
-  | DEFAULT ':' SourceElements_NoNode
-;
-
-LabelledStatement_NoNode:
-    IDENT ':' Statement_NoNode { }
-;
-
-ThrowStatement_NoNode:
-    THROW Expr_NoNode ';'
-  | THROW Expr_NoNode error { AUTO_SEMICOLON; }
-;
-
-TryStatement_NoNode:
-    TRY Block_NoNode FINALLY Block_NoNode
-  | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode
-  | TRY Block_NoNode CATCH '(' IDENT ')' Block_NoNode FINALLY Block_NoNode
-;
-
-DebuggerStatement_NoNode:
-    DEBUGGER ';'
-  | DEBUGGER error { AUTO_SEMICOLON; }
-;
-
-FunctionDeclaration_NoNode:
-    FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-  | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-;
-
-FunctionExpr_NoNode:
-    FUNCTION '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-  | FUNCTION '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-  | FUNCTION IDENT '(' ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-  | FUNCTION IDENT '(' FormalParameterList_NoNode ')' OPENBRACE FunctionBody_NoNode CLOSEBRACE
-;
-
-FormalParameterList_NoNode:
-    IDENT { }
-  | FormalParameterList_NoNode ',' IDENT
-;
-
-FunctionBody_NoNode:
-    /* not in spec */
-  | SourceElements_NoNode
-;
-
-SourceElements_NoNode:
-    Statement_NoNode
-  | SourceElements_NoNode Statement_NoNode
-;
-
-// End NoNodes
-
-%%
-
-#undef GLOBAL_DATA
-
-static ExpressionNode* makeAssignNode(JSGlobalData* globalData, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, int start, int divot, int end)
-{
-    if (!loc->isLocation())
-        return new (globalData) AssignErrorNode(globalData, loc, op, expr, divot, divot - start, end - divot);
-
-    if (loc->isResolveNode()) {
-        ResolveNode* resolve = static_cast<ResolveNode*>(loc);
-        if (op == OpEqual) {
-            AssignResolveNode* node = new (globalData) AssignResolveNode(globalData, resolve->identifier(), expr, exprHasAssignments);
-            setExceptionLocation(node, start, divot, end);
-            return node;
-        } else
-            return new (globalData) ReadModifyResolveNode(globalData, resolve->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
-    }
-    if (loc->isBracketAccessorNode()) {
-        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(loc);
-        if (op == OpEqual)
-            return new (globalData) AssignBracketNode(globalData, bracket->base(), bracket->subscript(), expr, locHasAssignments, exprHasAssignments, bracket->divot(), bracket->divot() - start, end - bracket->divot());
-        else {
-            ReadModifyBracketNode* node = new (globalData) ReadModifyBracketNode(globalData, bracket->base(), bracket->subscript(), op, expr, locHasAssignments, exprHasAssignments, divot, divot - start, end - divot);
-            node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
-            return node;
-        }
-    }
-    ASSERT(loc->isDotAccessorNode());
-    DotAccessorNode* dot = static_cast<DotAccessorNode*>(loc);
-    if (op == OpEqual)
-        return new (globalData) AssignDotNode(globalData, dot->base(), dot->identifier(), expr, exprHasAssignments, dot->divot(), dot->divot() - start, end - dot->divot());
-
-    ReadModifyDotNode* node = new (globalData) ReadModifyDotNode(globalData, dot->base(), dot->identifier(), op, expr, exprHasAssignments, divot, divot - start, end - divot);
-    node->setSubexpressionInfo(dot->divot(), dot->endOffset());
-    return node;
-}
-
-static ExpressionNode* makePrefixNode(JSGlobalData* globalData, ExpressionNode* expr, Operator op, int start, int divot, int end)
-{
-    if (!expr->isLocation())
-        return new (globalData) PrefixErrorNode(globalData, expr, op, divot, divot - start, end - divot);
-    
-    if (expr->isResolveNode()) {
-        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (globalData) PrefixResolveNode(globalData, resolve->identifier(), op, divot, divot - start, end - divot);
-    }
-    if (expr->isBracketAccessorNode()) {
-        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
-        PrefixBracketNode* node = new (globalData) PrefixBracketNode(globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
-        node->setSubexpressionInfo(bracket->divot(), bracket->startOffset());
-        return node;
-    }
-    ASSERT(expr->isDotAccessorNode());
-    DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-    PrefixDotNode* node = new (globalData) PrefixDotNode(globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
-    node->setSubexpressionInfo(dot->divot(), dot->startOffset());
-    return node;
-}
-
-static ExpressionNode* makePostfixNode(JSGlobalData* globalData, ExpressionNode* expr, Operator op, int start, int divot, int end)
-{ 
-    if (!expr->isLocation())
-        return new (globalData) PostfixErrorNode(globalData, expr, op, divot, divot - start, end - divot);
-    
-    if (expr->isResolveNode()) {
-        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (globalData) PostfixResolveNode(globalData, resolve->identifier(), op, divot, divot - start, end - divot);
-    }
-    if (expr->isBracketAccessorNode()) {
-        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
-        PostfixBracketNode* node = new (globalData) PostfixBracketNode(globalData, bracket->base(), bracket->subscript(), op, divot, divot - start, end - divot);
-        node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
-        return node;
-        
-    }
-    ASSERT(expr->isDotAccessorNode());
-    DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-    PostfixDotNode* node = new (globalData) PostfixDotNode(globalData, dot->base(), dot->identifier(), op, divot, divot - start, end - divot);
-    node->setSubexpressionInfo(dot->divot(), dot->endOffset());
-    return node;
-}
-
-static ExpressionNodeInfo makeFunctionCallNode(JSGlobalData* globalData, ExpressionNodeInfo func, ArgumentsNodeInfo args, int start, int divot, int end)
-{
-    CodeFeatures features = func.m_features | args.m_features;
-    int numConstants = func.m_numConstants + args.m_numConstants;
-    if (!func.m_node->isLocation())
-        return createNodeInfo<ExpressionNode*>(new (globalData) FunctionCallValueNode(globalData, func.m_node, args.m_node, divot, divot - start, end - divot), features, numConstants);
-    if (func.m_node->isResolveNode()) {
-        ResolveNode* resolve = static_cast<ResolveNode*>(func.m_node);
-        const Identifier& identifier = resolve->identifier();
-        if (identifier == globalData->propertyNames->eval)
-            return createNodeInfo<ExpressionNode*>(new (globalData) EvalFunctionCallNode(globalData, args.m_node, divot, divot - start, end - divot), EvalFeature | features, numConstants);
-        return createNodeInfo<ExpressionNode*>(new (globalData) FunctionCallResolveNode(globalData, identifier, args.m_node, divot, divot - start, end - divot), features, numConstants);
-    }
-    if (func.m_node->isBracketAccessorNode()) {
-        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(func.m_node);
-        FunctionCallBracketNode* node = new (globalData) FunctionCallBracketNode(globalData, bracket->base(), bracket->subscript(), args.m_node, divot, divot - start, end - divot);
-        node->setSubexpressionInfo(bracket->divot(), bracket->endOffset());
-        return createNodeInfo<ExpressionNode*>(node, features, numConstants);
-    }
-    ASSERT(func.m_node->isDotAccessorNode());
-    DotAccessorNode* dot = static_cast<DotAccessorNode*>(func.m_node);
-    FunctionCallDotNode* node;
-    if (dot->identifier() == globalData->propertyNames->call)
-        node = new (globalData) CallFunctionCallDotNode(globalData, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
-    else if (dot->identifier() == globalData->propertyNames->apply)
-        node = new (globalData) ApplyFunctionCallDotNode(globalData, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
-    else
-        node = new (globalData) FunctionCallDotNode(globalData, dot->base(), dot->identifier(), args.m_node, divot, divot - start, end - divot);
-    node->setSubexpressionInfo(dot->divot(), dot->endOffset());
-    return createNodeInfo<ExpressionNode*>(node, features, numConstants);
-}
-
-static ExpressionNode* makeTypeOfNode(JSGlobalData* globalData, ExpressionNode* expr)
-{
-    if (expr->isResolveNode()) {
-        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (globalData) TypeOfResolveNode(globalData, resolve->identifier());
-    }
-    return new (globalData) TypeOfValueNode(globalData, expr);
-}
-
-static ExpressionNode* makeDeleteNode(JSGlobalData* globalData, ExpressionNode* expr, int start, int divot, int end)
-{
-    if (!expr->isLocation())
-        return new (globalData) DeleteValueNode(globalData, expr);
-    if (expr->isResolveNode()) {
-        ResolveNode* resolve = static_cast<ResolveNode*>(expr);
-        return new (globalData) DeleteResolveNode(globalData, resolve->identifier(), divot, divot - start, end - divot);
-    }
-    if (expr->isBracketAccessorNode()) {
-        BracketAccessorNode* bracket = static_cast<BracketAccessorNode*>(expr);
-        return new (globalData) DeleteBracketNode(globalData, bracket->base(), bracket->subscript(), divot, divot - start, end - divot);
-    }
-    ASSERT(expr->isDotAccessorNode());
-    DotAccessorNode* dot = static_cast<DotAccessorNode*>(expr);
-    return new (globalData) DeleteDotNode(globalData, dot->base(), dot->identifier(), divot, divot - start, end - divot);
-}
-
-static PropertyNode* makeGetterOrSetterPropertyNode(JSGlobalData* globalData, const Identifier& getOrSet, const Identifier& name, ParameterNode* params, FunctionBodyNode* body, const SourceCode& source)
-{
-    PropertyNode::Type type;
-    if (getOrSet == "get")
-        type = PropertyNode::Getter;
-    else if (getOrSet == "set")
-        type = PropertyNode::Setter;
-    else
-        return 0;
-    return new (globalData) PropertyNode(globalData, name, new (globalData) FuncExprNode(globalData, globalData->propertyNames->nullIdentifier, body, source, params), type);
-}
-
-static ExpressionNode* makeNegateNode(JSGlobalData* globalData, ExpressionNode* n)
-{
-    if (n->isNumber()) {
-        NumberNode* numberNode = static_cast<NumberNode*>(n);
-        numberNode->setValue(-numberNode->value());
-        return numberNode;
-    }
-
-    return new (globalData) NegateNode(globalData, n);
-}
-
-static NumberNode* makeNumberNode(JSGlobalData* globalData, double d)
-{
-    return new (globalData) NumberNode(globalData, d);
-}
-
-static ExpressionNode* makeBitwiseNotNode(JSGlobalData* globalData, ExpressionNode* expr)
-{
-    if (expr->isNumber())
-        return makeNumberNode(globalData, ~toInt32(static_cast<NumberNode*>(expr)->value()));
-    return new (globalData) BitwiseNotNode(globalData, expr);
-}
-
-static ExpressionNode* makeMultNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
-    expr1 = expr1->stripUnaryPlus();
-    expr2 = expr2->stripUnaryPlus();
-
-    if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() * static_cast<NumberNode*>(expr2)->value());
-
-    if (expr1->isNumber() && static_cast<NumberNode*>(expr1)->value() == 1)
-        return new (globalData) UnaryPlusNode(globalData, expr2);
-
-    if (expr2->isNumber() && static_cast<NumberNode*>(expr2)->value() == 1)
-        return new (globalData) UnaryPlusNode(globalData, expr1);
-
-    return new (globalData) MultNode(globalData, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeDivNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
-    expr1 = expr1->stripUnaryPlus();
-    expr2 = expr2->stripUnaryPlus();
-
-    if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() / static_cast<NumberNode*>(expr2)->value());
-    return new (globalData) DivNode(globalData, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeAddNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
-    if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() + static_cast<NumberNode*>(expr2)->value());
-    return new (globalData) AddNode(globalData, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeSubNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
-    expr1 = expr1->stripUnaryPlus();
-    expr2 = expr2->stripUnaryPlus();
-
-    if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalData, static_cast<NumberNode*>(expr1)->value() - static_cast<NumberNode*>(expr2)->value());
-    return new (globalData) SubNode(globalData, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeLeftShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
-    if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalData, toInt32(static_cast<NumberNode*>(expr1)->value()) << (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
-    return new (globalData) LeftShiftNode(globalData, expr1, expr2, rightHasAssignments);
-}
-
-static ExpressionNode* makeRightShiftNode(JSGlobalData* globalData, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
-{
-    if (expr1->isNumber() && expr2->isNumber())
-        return makeNumberNode(globalData, toInt32(static_cast<NumberNode*>(expr1)->value()) >> (toUInt32(static_cast<NumberNode*>(expr2)->value()) & 0x1f));
-    return new (globalData) RightShiftNode(globalData, expr1, expr2, rightHasAssignments);
-}
-
-// Called by yyparse on error.
-int yyerror(const char*)
-{
-    return 1;
-}
-
-// May we automatically insert a semicolon?
-static bool allowAutomaticSemicolon(Lexer& lexer, int yychar)
-{
-    return yychar == CLOSEBRACE || yychar == 0 || lexer.prevTerminator();
-}
-
-static ExpressionNode* combineCommaNodes(JSGlobalData* globalData, ExpressionNode* list, ExpressionNode* init)
-{
-    if (!list)
-        return init;
-    if (list->isCommaNode()) {
-        static_cast<CommaNode*>(list)->append(init);
-        return list;
-    }
-    return new (globalData) CommaNode(globalData, list, init);
-}
-
-// We turn variable declarations into either assignments or empty
-// statements (which later get stripped out), because the actual
-// declaration work is hoisted up to the start of the function body
-static StatementNode* makeVarStatementNode(JSGlobalData* globalData, ExpressionNode* expr)
-{
-    if (!expr)
-        return new (globalData) EmptyStatementNode(globalData);
-    return new (globalData) VarStatementNode(globalData, expr);
-}
diff --git a/parser/JSParser.cpp b/parser/JSParser.cpp
new file mode 100644 (file)
index 0000000..d56155b
--- /dev/null
@@ -0,0 +1,2186 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+
+#include "JSParser.h"
+
+using namespace JSC;
+
+#include "CodeBlock.h"
+#include "JSGlobalData.h"
+#include "NodeInfo.h"
+#include "ASTBuilder.h"
+#include "SourceProvider.h"
+#include "SourceProviderCacheItem.h"
+#include <wtf/HashFunctions.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/WTFThreadData.h>
+#include <utility>
+
+using namespace std;
+
+namespace JSC {
+#define fail() do { m_error = true; return 0; } while (0)
+#define failIfFalse(cond) do { if (!(cond)) fail(); } while (0)
+#define failIfTrue(cond) do { if ((cond)) fail(); } while (0)
+#define failIfTrueIfStrict(cond) do { if ((cond) && strictMode()) fail(); } while (0)
+#define failIfFalseIfStrict(cond) do { if ((!(cond)) && strictMode()) fail(); } while (0)
+#define consumeOrFail(tokenType) do { if (!consume(tokenType)) fail(); } while (0)
+#define consumeOrFailWithFlags(tokenType, flags) do { if (!consume(tokenType, flags)) fail(); } while (0)
+#define matchOrFail(tokenType) do { if (!match(tokenType)) fail(); } while (0)
+#define failIfStackOverflow() do { failIfFalse(canRecurse()); } while (0)
+
+// Macros to make the more common TreeBuilder types a little less verbose
+#define TreeStatement typename TreeBuilder::Statement
+#define TreeExpression typename TreeBuilder::Expression
+#define TreeFormalParameterList typename TreeBuilder::FormalParameterList
+#define TreeSourceElements typename TreeBuilder::SourceElements
+#define TreeClause typename TreeBuilder::Clause
+#define TreeClauseList typename TreeBuilder::ClauseList
+#define TreeConstDeclList typename TreeBuilder::ConstDeclList
+#define TreeArguments typename TreeBuilder::Arguments
+#define TreeArgumentsList typename TreeBuilder::ArgumentsList
+#define TreeFunctionBody typename TreeBuilder::FunctionBody
+#define TreeProperty typename TreeBuilder::Property
+#define TreePropertyList typename TreeBuilder::PropertyList
+
+COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
+
+class JSParser {
+public:
+    JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*);
+    const char* parseProgram();
+private:
+    struct AllowInOverride {
+        AllowInOverride(JSParser* parser)
+            : m_parser(parser)
+            , m_oldAllowsIn(parser->m_allowsIn)
+        {
+            parser->m_allowsIn = true;
+        }
+        ~AllowInOverride()
+        {
+            m_parser->m_allowsIn = m_oldAllowsIn;
+        }
+        JSParser* m_parser;
+        bool m_oldAllowsIn;
+    };
+    
+    struct ScopeLabelInfo {
+        ScopeLabelInfo(StringImpl* ident, bool isLoop)
+        : m_ident(ident)
+        , m_isLoop(isLoop)
+        {
+        }
+        StringImpl* m_ident;
+        bool m_isLoop;
+    };
+    
+    ALWAYS_INLINE void next(unsigned lexType = 0)
+    {
+        m_lastLine = m_token.m_info.line;
+        m_lastTokenEnd = m_token.m_info.endOffset;
+        m_lexer->setLastLineNumber(m_lastLine);
+        m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_info, lexType, strictMode());
+    }
+    
+    ALWAYS_INLINE void nextExpectIdentifier(unsigned lexType = 0)
+    {
+        m_lastLine = m_token.m_info.line;
+        m_lastTokenEnd = m_token.m_info.endOffset;
+        m_lexer->setLastLineNumber(m_lastLine);
+        m_token.m_type = m_lexer->lexExpectIdentifier(&m_token.m_data, &m_token.m_info, lexType, strictMode());
+    }
+    
+    ALWAYS_INLINE bool nextTokenIsColon()
+    {
+        return m_lexer->nextTokenIsColon();
+    }
+
+    ALWAYS_INLINE bool consume(JSTokenType expected, unsigned flags = 0)
+    {
+        bool result = m_token.m_type == expected;
+        failIfFalse(result);
+        next(flags);
+        return result;
+    }
+
+    ALWAYS_INLINE bool match(JSTokenType expected)
+    {
+        return m_token.m_type == expected;
+    }
+
+    ALWAYS_INLINE int tokenStart()
+    {
+        return m_token.m_info.startOffset;
+    }
+
+    ALWAYS_INLINE int tokenLine()
+    {
+        return m_token.m_info.line;
+    }
+
+    ALWAYS_INLINE int tokenEnd()
+    {
+        return m_token.m_info.endOffset;
+    }
+    
+    void startLoop() { currentScope()->startLoop(); }
+    void endLoop() { currentScope()->endLoop(); }
+    void startSwitch() { currentScope()->startSwitch(); }
+    void endSwitch() { currentScope()->endSwitch(); }
+    void setStrictMode() { currentScope()->setStrictMode(); }
+    bool strictMode() { return currentScope()->strictMode(); }
+    bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
+    bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
+    bool breakIsValid()
+    {
+        ScopeRef current = currentScope();
+        while (!current->breakIsValid()) {
+            if (!current.hasContainingScope())
+                return false;
+            current = current.containingScope();
+        }
+        return true;
+    }
+    bool continueIsValid()
+    {
+        ScopeRef current = currentScope();
+        while (!current->continueIsValid()) {
+            if (!current.hasContainingScope())
+                return false;
+            current = current.containingScope();
+        }
+        return true;
+    }
+    void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); }
+    void popLabel() { currentScope()->popLabel(); }
+    ScopeLabelInfo* getLabel(const Identifier* label)
+    {
+        ScopeRef current = currentScope();
+        ScopeLabelInfo* result = 0;
+        while (!(result = current->getLabel(label))) {
+            if (!current.hasContainingScope())
+                return 0;
+            current = current.containingScope();
+        }
+        return result;
+    }
+
+    enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode };
+    template <SourceElementsMode mode, class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive);
+    template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
+    template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeStatement parseBlockStatement(TreeBuilder&);
+    template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
+    template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
+    template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&);
+    template <bool strict, class TreeBuilder> ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
+    template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd);
+    template <class TreeBuilder> ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context);
+    enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName };
+    template <FunctionRequirements, bool nameIsInContainingScope, class TreeBuilder> bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, int& openBrace, int& closeBrace, int& bodyStartLine);
+    ALWAYS_INLINE int isBinaryOperator(JSTokenType token);
+    bool allowAutomaticSemicolon();
+
+    bool autoSemiColon()
+    {
+        if (m_token.m_type == SEMICOLON) {
+            next();
+            return true;
+        }
+        return allowAutomaticSemicolon();
+    }
+
+    bool canRecurse()
+    {
+        return m_stack.recursionCheck();
+    }
+    
+    int lastTokenEnd() const
+    {
+        return m_lastTokenEnd;
+    }
+
+    ParserArena m_arena;
+    Lexer* m_lexer;
+    StackBounds m_stack;
+    bool m_error;
+    const char* m_errorMessage;
+    JSGlobalData* m_globalData;
+    JSToken m_token;
+    bool m_allowsIn;
+    int m_lastLine;
+    int m_lastTokenEnd;
+    int m_assignmentCount;
+    int m_nonLHSCount;
+    bool m_syntaxAlreadyValidated;
+    int m_statementDepth;
+    int m_nonTrivialExpressionCount;
+    const Identifier* m_lastIdentifier;
+
+    struct DepthManager {
+        DepthManager(int* depth)
+            : m_originalDepth(*depth)
+            , m_depth(depth)
+        {
+        }
+        
+        ~DepthManager()
+        {
+            *m_depth = m_originalDepth;
+        }
+        
+    private:
+        int m_originalDepth;
+        int* m_depth;
+    };
+    
+    struct Scope {
+        Scope(JSGlobalData* globalData, bool isFunction, bool strictMode)
+            : m_globalData(globalData)
+            , m_shadowsArguments(false)
+            , m_usesEval(false)
+            , m_needsFullActivation(false)
+            , m_allowsNewDecls(true)
+            , m_strictMode(strictMode)
+            , m_isFunction(isFunction)
+            , m_isFunctionBoundary(false)
+            , m_isValidStrictMode(true)
+            , m_loopDepth(0)
+            , m_switchDepth(0)
+        {
+        }
+
+        Scope(const Scope& rhs)
+            : m_globalData(rhs.m_globalData)
+            , m_shadowsArguments(rhs.m_shadowsArguments)
+            , m_usesEval(rhs.m_usesEval)
+            , m_needsFullActivation(rhs.m_needsFullActivation)
+            , m_allowsNewDecls(rhs.m_allowsNewDecls)
+            , m_strictMode(rhs.m_strictMode)
+            , m_isFunction(rhs.m_isFunction)
+            , m_isFunctionBoundary(rhs.m_isFunctionBoundary)
+            , m_isValidStrictMode(rhs.m_isValidStrictMode)
+            , m_loopDepth(rhs.m_loopDepth)
+            , m_switchDepth(rhs.m_switchDepth)
+        {
+            if (rhs.m_labels) {
+                m_labels = adoptPtr(new LabelStack);
+                
+                typedef LabelStack::const_iterator iterator;
+                iterator end = rhs.m_labels->end();
+                for (iterator it = rhs.m_labels->begin(); it != end; ++it)
+                    m_labels->append(ScopeLabelInfo(it->m_ident, it->m_isLoop));
+            }
+        }
+
+        void startSwitch() { m_switchDepth++; }
+        void endSwitch() { m_switchDepth--; }
+        void startLoop() { m_loopDepth++; }
+        void endLoop() { ASSERT(m_loopDepth); m_loopDepth--; }
+        bool inLoop() { return !!m_loopDepth; }
+        bool breakIsValid() { return m_loopDepth || m_switchDepth; }
+        bool continueIsValid() { return m_loopDepth; }
+
+        void pushLabel(const Identifier* label, bool isLoop)
+        {
+            if (!m_labels)
+                m_labels = adoptPtr(new LabelStack);
+            m_labels->append(ScopeLabelInfo(label->impl(), isLoop));
+        }
+
+        void popLabel()
+        {
+            ASSERT(m_labels);
+            ASSERT(m_labels->size());
+            m_labels->removeLast();
+        }
+
+        ScopeLabelInfo* getLabel(const Identifier* label)
+        {
+            if (!m_labels)
+                return 0;
+            for (int i = m_labels->size(); i > 0; i--) {
+                if (m_labels->at(i - 1).m_ident == label->impl())
+                    return &m_labels->at(i - 1);
+            }
+            return 0;
+        }
+
+        void setIsFunction()
+        {
+            m_isFunction = true;
+            m_isFunctionBoundary = true;
+        }
+        bool isFunction() { return m_isFunction; }
+        bool isFunctionBoundary() { return m_isFunctionBoundary; }
+        
+        bool declareVariable(const Identifier* ident)
+        {
+            bool isValidStrictMode = m_globalData->propertyNames->eval != *ident && m_globalData->propertyNames->arguments != *ident;
+            m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
+            m_declaredVariables.add(ident->ustring().impl());
+            return isValidStrictMode;
+        }
+        
+        void declareWrite(const Identifier* ident)
+        {
+            ASSERT(m_strictMode);
+            m_writtenVariables.add(ident->impl());
+        }
+
+        void preventNewDecls() { m_allowsNewDecls = false; }
+        bool allowsNewDecls() const { return m_allowsNewDecls; }
+
+        bool declareParameter(const Identifier* ident)
+        {
+            bool isArguments = m_globalData->propertyNames->arguments == *ident;
+            bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && !isArguments;
+            m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode;
+            if (isArguments)
+                m_shadowsArguments = true;
+            return isValidStrictMode;
+        }
+        
+        void useVariable(const Identifier* ident, bool isEval)
+        {
+            m_usesEval |= isEval;
+            m_usedVariables.add(ident->ustring().impl());
+        }
+        
+        void setNeedsFullActivation() { m_needsFullActivation = true; }
+        
+        bool collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)
+        {
+            if (nestedScope->m_usesEval)
+                m_usesEval = true;
+            IdentifierSet::iterator end = nestedScope->m_usedVariables.end();
+            for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) {
+                if (nestedScope->m_declaredVariables.contains(*ptr))
+                    continue;
+                m_usedVariables.add(*ptr);
+                if (shouldTrackClosedVariables)
+                    m_closedVariables.add(*ptr);
+            }
+            if (nestedScope->m_writtenVariables.size()) {
+                IdentifierSet::iterator end = nestedScope->m_writtenVariables.end();
+                for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) {
+                    if (nestedScope->m_declaredVariables.contains(*ptr))
+                        continue;
+                    m_writtenVariables.add(*ptr);
+                }
+            }
+
+            return true;
+        }
+
+        void getUncapturedWrittenVariables(IdentifierSet& writtenVariables)
+        {
+            IdentifierSet::iterator end = m_writtenVariables.end();
+            for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) {
+                if (!m_declaredVariables.contains(*ptr))
+                    writtenVariables.add(*ptr);
+            }
+        }
+
+        void getCapturedVariables(IdentifierSet& capturedVariables)
+        {
+            if (m_needsFullActivation || m_usesEval) {
+                capturedVariables.swap(m_declaredVariables);
+                return;
+            }
+            for (IdentifierSet::iterator ptr = m_closedVariables.begin(); ptr != m_closedVariables.end(); ++ptr) {
+                if (!m_declaredVariables.contains(*ptr))
+                    continue;
+                capturedVariables.add(*ptr);
+            }
+        }
+        void setStrictMode() { m_strictMode = true; }
+        bool strictMode() const { return m_strictMode; }
+        bool isValidStrictMode() const { return m_isValidStrictMode; }
+        bool shadowsArguments() const { return m_shadowsArguments; }
+        
+        void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector<RefPtr<StringImpl> >& vector)
+        {
+            IdentifierSet::iterator end = capturedVariables.end();
+            for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) {
+                if (m_declaredVariables.contains(*it))
+                    continue;
+                vector.append(*it);
+            }
+            vector.shrinkToFit();
+        }
+
+        void saveFunctionInfo(SourceProviderCacheItem* info)
+        {
+            ASSERT(m_isFunction);
+            info->usesEval = m_usesEval;
+            copyCapturedVariablesToVector(m_writtenVariables, info->writtenVariables);
+            copyCapturedVariablesToVector(m_usedVariables, info->usedVariables);
+        }
+
+        void restoreFunctionInfo(const SourceProviderCacheItem* info)
+        {
+            ASSERT(m_isFunction);
+            m_usesEval = info->usesEval;
+            unsigned size = info->usedVariables.size();
+            for (unsigned i = 0; i < size; ++i)
+                m_usedVariables.add(info->usedVariables[i]);
+            size = info->writtenVariables.size();
+            for (unsigned i = 0; i < size; ++i)
+                m_writtenVariables.add(info->writtenVariables[i]);
+        }
+
+    private:
+        JSGlobalData* m_globalData;
+        bool m_shadowsArguments : 1;
+        bool m_usesEval : 1;
+        bool m_needsFullActivation : 1;
+        bool m_allowsNewDecls : 1;
+        bool m_strictMode : 1;
+        bool m_isFunction : 1;
+        bool m_isFunctionBoundary : 1;
+        bool m_isValidStrictMode : 1;
+        int m_loopDepth;
+        int m_switchDepth;
+
+        typedef Vector<ScopeLabelInfo, 2> LabelStack;
+        OwnPtr<LabelStack> m_labels;
+        IdentifierSet m_declaredVariables;
+        IdentifierSet m_usedVariables;
+        IdentifierSet m_closedVariables;
+        IdentifierSet m_writtenVariables;
+    };
+
+    typedef Vector<Scope, 10> ScopeStack;
+
+    struct ScopeRef {
+        ScopeRef(ScopeStack* scopeStack, unsigned index)
+            : m_scopeStack(scopeStack)
+            , m_index(index)
+        {
+        }
+        Scope* operator->() { return &m_scopeStack->at(m_index); }
+        unsigned index() const { return m_index; }
+
+        bool hasContainingScope()
+        {
+            return m_index && !m_scopeStack->at(m_index).isFunctionBoundary();
+        }
+
+        ScopeRef containingScope()
+        {
+            ASSERT(hasContainingScope());
+            return ScopeRef(m_scopeStack, m_index - 1);
+        }
+
+    private:
+        ScopeStack* m_scopeStack;
+        unsigned m_index;
+    };
+
+    struct AutoPopScopeRef : public ScopeRef {
+        AutoPopScopeRef(JSParser* parser, ScopeRef scope)
+            : ScopeRef(scope)
+            , m_parser(parser)
+        {
+        }
+
+        ~AutoPopScopeRef()
+        {
+            if (m_parser)
+                m_parser->popScope(*this, false);
+        }
+
+        void setPopped()
+        {
+            m_parser = 0;
+        }
+
+    private:
+        JSParser* m_parser;
+    };
+
+    ScopeRef currentScope()
+    {
+        return ScopeRef(&m_scopeStack, m_scopeStack.size() - 1);
+    }
+    
+    ScopeRef pushScope()
+    {
+        bool isFunction = false;
+        bool isStrict = false;
+        if (!m_scopeStack.isEmpty()) {
+            isStrict = m_scopeStack.last().strictMode();
+            isFunction = m_scopeStack.last().isFunction();
+        }
+        m_scopeStack.append(Scope(m_globalData, isFunction, isStrict));
+        return currentScope();
+    }
+
+    bool popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
+    {
+        ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
+        ASSERT(m_scopeStack.size() > 1);
+        bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
+        m_scopeStack.removeLast();
+        return result;
+    }
+
+    bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables)
+    {
+        return popScopeInternal(scope, shouldTrackClosedVariables);
+    }
+
+    bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables)
+    {
+        scope.setPopped();
+        return popScopeInternal(scope, shouldTrackClosedVariables);
+    }
+
+    bool declareVariable(const Identifier* ident)
+    {
+        unsigned i = m_scopeStack.size() - 1;
+        ASSERT(i < m_scopeStack.size());
+        while (!m_scopeStack[i].allowsNewDecls()) {
+            i--;
+            ASSERT(i < m_scopeStack.size());
+        }
+        return m_scopeStack[i].declareVariable(ident);
+    }
+    
+    void declareWrite(const Identifier* ident)
+    {
+        if (!m_syntaxAlreadyValidated)
+            m_scopeStack.last().declareWrite(ident);
+    }
+
+    ScopeStack m_scopeStack;
+
+    const SourceProviderCacheItem* findCachedFunctionInfo(int openBracePos) 
+    {
+        return m_functionCache ? m_functionCache->get(openBracePos) : 0;
+    }
+
+    SourceProviderCache* m_functionCache;
+};
+
+const char* jsParse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode parserMode, const SourceCode* source)
+{
+    JSParser parser(globalData->lexer, globalData, parameters, strictness == JSParseStrict, parserMode == JSParseFunctionCode, source->provider());
+    return parser.parseProgram();
+}
+
+JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider)
+    : m_lexer(lexer)
+    , m_stack(globalData->stack())
+    , m_error(false)
+    , m_errorMessage("Parse error")
+    , m_globalData(globalData)
+    , m_allowsIn(true)
+    , m_lastLine(0)
+    , m_lastTokenEnd(0)
+    , m_assignmentCount(0)
+    , m_nonLHSCount(0)
+    , m_syntaxAlreadyValidated(provider->isValid())
+    , m_statementDepth(0)
+    , m_nonTrivialExpressionCount(0)
+    , m_lastIdentifier(0)
+    , m_functionCache(m_lexer->sourceProvider()->cache())
+{
+    ScopeRef scope = pushScope();
+    if (isFunction)
+        scope->setIsFunction();
+    if (inStrictContext)
+        scope->setStrictMode();
+    if (parameters) {
+        for (unsigned i = 0; i < parameters->size(); i++)
+            scope->declareParameter(&parameters->at(i));
+    }
+    next();
+    m_lexer->setLastLineNumber(tokenLine());
+}
+
+const char* JSParser::parseProgram()
+{
+    unsigned oldFunctionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
+    ASTBuilder context(m_globalData, m_lexer);
+    if (m_lexer->isReparsing())
+        m_statementDepth--;
+    ScopeRef scope = currentScope();
+    SourceElements* sourceElements = parseSourceElements<CheckForStrictMode>(context);
+    if (!sourceElements || !consume(EOFTOK))
+        return m_errorMessage;
+    IdentifierSet capturedVariables;
+    scope->getCapturedVariables(capturedVariables);
+    CodeFeatures features = context.features();
+    if (scope->strictMode())
+        features |= StrictModeFeature;
+    if (scope->shadowsArguments())
+        features |= ShadowsArgumentsFeature;
+    
+    unsigned functionCacheSize = m_functionCache ? m_functionCache->byteSize() : 0;
+    if (functionCacheSize != oldFunctionCacheSize)
+        m_lexer->sourceProvider()->notifyCacheSizeChanged(functionCacheSize - oldFunctionCacheSize);
+
+    m_globalData->parser->didFinishParsing(sourceElements, context.varDeclarations(), context.funcDeclarations(), features,
+                                           m_lastLine, context.numConstants(), capturedVariables);
+    return 0;
+}
+
+bool JSParser::allowAutomaticSemicolon()
+{
+    return match(CLOSEBRACE) || match(EOFTOK) || m_lexer->prevTerminator();
+}
+
+template <JSParser::SourceElementsMode mode, class TreeBuilder> TreeSourceElements JSParser::parseSourceElements(TreeBuilder& context)
+{
+    TreeSourceElements sourceElements = context.createSourceElements();
+    bool seenNonDirective = false;
+    const Identifier* directive = 0;
+    unsigned startOffset = m_token.m_info.startOffset;
+    unsigned oldLastLineNumber = m_lexer->lastLineNumber();
+    unsigned oldLineNumber = m_lexer->lineNumber();
+    bool hasSetStrict = false;
+    while (TreeStatement statement = parseStatement(context, directive)) {
+        if (mode == CheckForStrictMode && !seenNonDirective) {
+            if (directive) {
+                if (!hasSetStrict && m_globalData->propertyNames->useStrictIdentifier == *directive) {
+                    setStrictMode();
+                    hasSetStrict = true;
+                    failIfFalse(isValidStrictMode());
+                    m_lexer->setOffset(startOffset);
+                    next();
+                    m_lexer->setLastLineNumber(oldLastLineNumber);
+                    m_lexer->setLineNumber(oldLineNumber);
+                    failIfTrue(m_error);
+                    continue;
+                }
+            } else
+                seenNonDirective = true;
+        }
+        context.appendStatement(sourceElements, statement);
+    }
+
+    if (m_error)
+        fail();
+    return sourceElements;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseVarDeclaration(TreeBuilder& context)
+{
+    ASSERT(match(VAR));
+    int start = tokenLine();
+    int end = 0;
+    int scratch;
+    const Identifier* scratch1 = 0;
+    TreeExpression scratch2 = 0;
+    int scratch3 = 0;
+    TreeExpression varDecls = parseVarDeclarationList(context, scratch, scratch1, scratch2, scratch3, scratch3, scratch3);
+    failIfTrue(m_error);
+    failIfFalse(autoSemiColon());
+
+    return context.createVarStatement(varDecls, start, end);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseConstDeclaration(TreeBuilder& context)
+{
+    ASSERT(match(CONSTTOKEN));
+    int start = tokenLine();
+    int end = 0;
+    TreeConstDeclList constDecls = parseConstDeclarationList(context);
+    failIfTrue(m_error);
+    failIfFalse(autoSemiColon());
+    
+    return context.createConstStatement(constDecls, start, end);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseDoWhileStatement(TreeBuilder& context)
+{
+    ASSERT(match(DO));
+    int startLine = tokenLine();
+    next();
+    const Identifier* unused = 0;
+    startLoop();
+    TreeStatement statement = parseStatement(context, unused);
+    endLoop();
+    failIfFalse(statement);
+    int endLine = tokenLine();
+    consumeOrFail(WHILE);
+    consumeOrFail(OPENPAREN);
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    consumeOrFail(CLOSEPAREN);
+    if (match(SEMICOLON))
+        next(); // Always performs automatic semicolon insertion.
+    return context.createDoWhileStatement(statement, expr, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseWhileStatement(TreeBuilder& context)
+{
+    ASSERT(match(WHILE));
+    int startLine = tokenLine();
+    next();
+    consumeOrFail(OPENPAREN);
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    int endLine = tokenLine();
+    consumeOrFail(CLOSEPAREN);
+    const Identifier* unused = 0;
+    startLoop();
+    TreeStatement statement = parseStatement(context, unused);
+    endLoop();
+    failIfFalse(statement);
+    return context.createWhileStatement(expr, statement, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseVarDeclarationList(TreeBuilder& context, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd)
+{
+    TreeExpression varDecls = 0;
+    do {
+        declarations++;
+        next();
+        matchOrFail(IDENT);
+
+        int varStart = tokenStart();
+        identStart = varStart;
+        const Identifier* name = m_token.m_data.ident;
+        lastIdent = name;
+        next();
+        bool hasInitializer = match(EQUAL);
+        failIfFalseIfStrict(declareVariable(name));
+        context.addVar(name, (hasInitializer || (!m_allowsIn && match(INTOKEN))) ? DeclarationStacks::HasInitializer : 0);
+        if (hasInitializer) {
+            int varDivot = tokenStart() + 1;
+            initStart = tokenStart();
+            next(TreeBuilder::DontBuildStrings); // consume '='
+            int initialAssignments = m_assignmentCount;
+            TreeExpression initializer = parseAssignmentExpression(context);
+            initEnd = lastTokenEnd();
+            lastInitializer = initializer;
+            failIfFalse(initializer);
+
+            TreeExpression node = context.createAssignResolve(*name, initializer, initialAssignments != m_assignmentCount, varStart, varDivot, lastTokenEnd());
+            if (!varDecls)
+                varDecls = node;
+            else
+                varDecls = context.combineCommaNodes(varDecls, node);
+        }
+    } while (match(COMMA));
+    return varDecls;
+}
+
+template <class TreeBuilder> TreeConstDeclList JSParser::parseConstDeclarationList(TreeBuilder& context)
+{
+    failIfTrue(strictMode());
+    TreeConstDeclList constDecls = 0;
+    TreeConstDeclList tail = 0;
+    do {
+        next();
+        matchOrFail(IDENT);
+        const Identifier* name = m_token.m_data.ident;
+        next();
+        bool hasInitializer = match(EQUAL);
+        declareVariable(name);
+        context.addVar(name, DeclarationStacks::IsConstant | (hasInitializer ? DeclarationStacks::HasInitializer : 0));
+        TreeExpression initializer = 0;
+        if (hasInitializer) {
+            next(TreeBuilder::DontBuildStrings); // consume '='
+            initializer = parseAssignmentExpression(context);
+        }
+        tail = context.appendConstDecl(tail, name, initializer);
+        if (!constDecls)
+            constDecls = tail;
+    } while (match(COMMA));
+    return constDecls;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseForStatement(TreeBuilder& context)
+{
+    ASSERT(match(FOR));
+    int startLine = tokenLine();
+    next();
+    consumeOrFail(OPENPAREN);
+    int nonLHSCount = m_nonLHSCount;
+    int declarations = 0;
+    int declsStart = 0;
+    int declsEnd = 0;
+    TreeExpression decls = 0;
+    bool hasDeclaration = false;
+    if (match(VAR)) {
+        /*
+         for (var IDENT in expression) statement
+         for (var IDENT = expression in expression) statement
+         for (var varDeclarationList; expressionOpt; expressionOpt)
+         */
+        hasDeclaration = true;
+        const Identifier* forInTarget = 0;
+        TreeExpression forInInitializer = 0;
+        m_allowsIn = false;
+        int initStart = 0;
+        int initEnd = 0;
+        decls = parseVarDeclarationList(context, declarations, forInTarget, forInInitializer, declsStart, initStart, initEnd);
+        m_allowsIn = true;
+        if (m_error)
+            fail();
+
+        // Remainder of a standard for loop is handled identically
+        if (match(SEMICOLON))
+            goto standardForLoop;
+
+        failIfFalse(declarations == 1);
+
+        // Handle for-in with var declaration
+        int inLocation = tokenStart();
+        if (!consume(INTOKEN))
+            fail();
+
+        TreeExpression expr = parseExpression(context);
+        failIfFalse(expr);
+        int exprEnd = lastTokenEnd();
+
+        int endLine = tokenLine();
+        consumeOrFail(CLOSEPAREN);
+
+        const Identifier* unused = 0;
+        startLoop();
+        TreeStatement statement = parseStatement(context, unused);
+        endLoop();
+        failIfFalse(statement);
+
+        return context.createForInLoop(forInTarget, forInInitializer, expr, statement, declsStart, inLocation, exprEnd, initStart, initEnd, startLine, endLine);
+    }
+
+    if (!match(SEMICOLON)) {
+        m_allowsIn = false;
+        declsStart = tokenStart();
+        decls = parseExpression(context);
+        declsEnd = lastTokenEnd();
+        m_allowsIn = true;
+        failIfFalse(decls);
+    }
+
+    if (match(SEMICOLON)) {
+    standardForLoop:
+        // Standard for loop
+        next();
+        TreeExpression condition = 0;
+
+        if (!match(SEMICOLON)) {
+            condition = parseExpression(context);
+            failIfFalse(condition);
+        }
+        consumeOrFail(SEMICOLON);
+
+        TreeExpression increment = 0;
+        if (!match(CLOSEPAREN)) {
+            increment = parseExpression(context);
+            failIfFalse(increment);
+        }
+        int endLine = tokenLine();
+        consumeOrFail(CLOSEPAREN);
+        const Identifier* unused = 0;
+        startLoop();
+        TreeStatement statement = parseStatement(context, unused);
+        endLoop();
+        failIfFalse(statement);
+        return context.createForLoop(decls, condition, increment, statement, hasDeclaration, startLine, endLine);
+    }
+
+    // For-in loop
+    failIfFalse(nonLHSCount == m_nonLHSCount);
+    consumeOrFail(INTOKEN);
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    int exprEnd = lastTokenEnd();
+    int endLine = tokenLine();
+    consumeOrFail(CLOSEPAREN);
+    const Identifier* unused = 0;
+    startLoop();
+    TreeStatement statement = parseStatement(context, unused);
+    endLoop();
+    failIfFalse(statement);
+    
+    return context.createForInLoop(decls, expr, statement, declsStart, declsEnd, exprEnd, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseBreakStatement(TreeBuilder& context)
+{
+    ASSERT(match(BREAK));
+    int startCol = tokenStart();
+    int endCol = tokenEnd();
+    int startLine = tokenLine();
+    int endLine = tokenLine();
+    next();
+
+    if (autoSemiColon()) {
+        failIfFalse(breakIsValid());
+        return context.createBreakStatement(startCol, endCol, startLine, endLine);
+    }
+    matchOrFail(IDENT);
+    const Identifier* ident = m_token.m_data.ident;
+    failIfFalse(getLabel(ident));
+    endCol = tokenEnd();
+    endLine = tokenLine();
+    next();
+    failIfFalse(autoSemiColon());
+    return context.createBreakStatement(ident, startCol, endCol, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseContinueStatement(TreeBuilder& context)
+{
+    ASSERT(match(CONTINUE));
+    int startCol = tokenStart();
+    int endCol = tokenEnd();
+    int startLine = tokenLine();
+    int endLine = tokenLine();
+    next();
+
+    if (autoSemiColon()) {
+        failIfFalse(continueIsValid());
+        return context.createContinueStatement(startCol, endCol, startLine, endLine);
+    }
+    matchOrFail(IDENT);
+    const Identifier* ident = m_token.m_data.ident;
+    ScopeLabelInfo* label = getLabel(ident);
+    failIfFalse(label);
+    failIfFalse(label->m_isLoop);
+    endCol = tokenEnd();
+    endLine = tokenLine();
+    next();
+    failIfFalse(autoSemiColon());
+    return context.createContinueStatement(ident, startCol, endCol, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseReturnStatement(TreeBuilder& context)
+{
+    ASSERT(match(RETURN));
+    failIfFalse(currentScope()->isFunction());
+    int startLine = tokenLine();
+    int endLine = startLine;
+    int start = tokenStart();
+    int end = tokenEnd();
+    next();
+    // We do the auto semicolon check before attempting to parse an expression
+    // as we need to ensure the a line break after the return correctly terminates
+    // the statement
+    if (match(SEMICOLON))
+        endLine  = tokenLine();
+    if (autoSemiColon())
+        return context.createReturnStatement(0, start, end, startLine, endLine);
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    end = lastTokenEnd();
+    if (match(SEMICOLON))
+        endLine  = tokenLine();
+    failIfFalse(autoSemiColon());
+    return context.createReturnStatement(expr, start, end, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseThrowStatement(TreeBuilder& context)
+{
+    ASSERT(match(THROW));
+    int eStart = tokenStart();
+    int startLine = tokenLine();
+    next();
+    
+    failIfTrue(autoSemiColon());
+
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    int eEnd = lastTokenEnd();
+    int endLine = tokenLine();
+    failIfFalse(autoSemiColon());
+
+    return context.createThrowStatement(expr, eStart, eEnd, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseWithStatement(TreeBuilder& context)
+{
+    ASSERT(match(WITH));
+    failIfTrue(strictMode());
+    currentScope()->setNeedsFullActivation();
+    int startLine = tokenLine();
+    next();
+    consumeOrFail(OPENPAREN);
+    int start = tokenStart();
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    int end = lastTokenEnd();
+
+    int endLine = tokenLine();
+    consumeOrFail(CLOSEPAREN);
+    const Identifier* unused = 0;
+    TreeStatement statement = parseStatement(context, unused);
+    failIfFalse(statement);
+
+    return context.createWithStatement(expr, statement, start, end, startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseSwitchStatement(TreeBuilder& context)
+{
+    ASSERT(match(SWITCH));
+    int startLine = tokenLine();
+    next();
+    consumeOrFail(OPENPAREN);
+    TreeExpression expr = parseExpression(context);
+    failIfFalse(expr);
+    int endLine = tokenLine();
+    consumeOrFail(CLOSEPAREN);
+    consumeOrFail(OPENBRACE);
+    startSwitch();
+    TreeClauseList firstClauses = parseSwitchClauses(context);
+    failIfTrue(m_error);
+
+    TreeClause defaultClause = parseSwitchDefaultClause(context);
+    failIfTrue(m_error);
+
+    TreeClauseList secondClauses = parseSwitchClauses(context);
+    failIfTrue(m_error);
+    endSwitch();
+    consumeOrFail(CLOSEBRACE);
+
+    return context.createSwitchStatement(expr, firstClauses, defaultClause, secondClauses, startLine, endLine);
+
+}
+
+template <class TreeBuilder> TreeClauseList JSParser::parseSwitchClauses(TreeBuilder& context)
+{
+    if (!match(CASE))
+        return 0;
+    next();
+    TreeExpression condition = parseExpression(context);
+    failIfFalse(condition);
+    consumeOrFail(COLON);
+    TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
+    failIfFalse(statements);
+    TreeClause clause = context.createClause(condition, statements);
+    TreeClauseList clauseList = context.createClauseList(clause);
+    TreeClauseList tail = clauseList;
+
+    while (match(CASE)) {
+        next();
+        TreeExpression condition = parseExpression(context);
+        failIfFalse(condition);
+        consumeOrFail(COLON);
+        TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
+        failIfFalse(statements);
+        clause = context.createClause(condition, statements);
+        tail = context.createClauseList(tail, clause);
+    }
+    return clauseList;
+}
+
+template <class TreeBuilder> TreeClause JSParser::parseSwitchDefaultClause(TreeBuilder& context)
+{
+    if (!match(DEFAULT))
+        return 0;
+    next();
+    consumeOrFail(COLON);
+    TreeSourceElements statements = parseSourceElements<DontCheckForStrictMode>(context);
+    failIfFalse(statements);
+    return context.createClause(0, statements);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseTryStatement(TreeBuilder& context)
+{
+    ASSERT(match(TRY));
+    TreeStatement tryBlock = 0;
+    const Identifier* ident = &m_globalData->propertyNames->nullIdentifier;
+    bool catchHasEval = false;
+    TreeStatement catchBlock = 0;
+    TreeStatement finallyBlock = 0;
+    int firstLine = tokenLine();
+    next();
+    matchOrFail(OPENBRACE);
+
+    tryBlock = parseBlockStatement(context);
+    failIfFalse(tryBlock);
+    int lastLine = m_lastLine;
+
+    if (match(CATCH)) {
+        currentScope()->setNeedsFullActivation();
+        next();
+        consumeOrFail(OPENPAREN);
+        matchOrFail(IDENT);
+        ident = m_token.m_data.ident;
+        next();
+        AutoPopScopeRef catchScope(this, pushScope());
+        failIfFalseIfStrict(catchScope->declareVariable(ident));
+        catchScope->preventNewDecls();
+        consumeOrFail(CLOSEPAREN);
+        matchOrFail(OPENBRACE);
+        int initialEvalCount = context.evalCount();
+        catchBlock = parseBlockStatement(context);
+        failIfFalse(catchBlock);
+        catchHasEval = initialEvalCount != context.evalCount();
+        failIfFalse(popScope(catchScope, TreeBuilder::NeedsFreeVariableInfo));
+    }
+
+    if (match(FINALLY)) {
+        next();
+        matchOrFail(OPENBRACE);
+        finallyBlock = parseBlockStatement(context);
+        failIfFalse(finallyBlock);
+    }
+    failIfFalse(catchBlock || finallyBlock);
+    return context.createTryStatement(tryBlock, ident, catchHasEval, catchBlock, finallyBlock, firstLine, lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseDebuggerStatement(TreeBuilder& context)
+{
+    ASSERT(match(DEBUGGER));
+    int startLine = tokenLine();
+    int endLine = startLine;
+    next();
+    if (match(SEMICOLON))
+        startLine = tokenLine();
+    failIfFalse(autoSemiColon());
+    return context.createDebugger(startLine, endLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseBlockStatement(TreeBuilder& context)
+{
+    ASSERT(match(OPENBRACE));
+    int start = tokenLine();
+    next();
+    if (match(CLOSEBRACE)) {
+        next();
+        return context.createBlockStatement(0, start, m_lastLine);
+    }
+    TreeSourceElements subtree = parseSourceElements<DontCheckForStrictMode>(context);
+    failIfFalse(subtree);
+    matchOrFail(CLOSEBRACE);
+    next();
+    return context.createBlockStatement(subtree, start, m_lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseStatement(TreeBuilder& context, const Identifier*& directive)
+{
+    DepthManager statementDepth(&m_statementDepth);
+    m_statementDepth++;
+    directive = 0;
+    int nonTrivialExpressionCount = 0;
+    failIfStackOverflow();
+    switch (m_token.m_type) {
+    case OPENBRACE:
+        return parseBlockStatement(context);
+    case VAR:
+        return parseVarDeclaration(context);
+    case CONSTTOKEN:
+        return parseConstDeclaration(context);
+    case FUNCTION:
+        failIfFalseIfStrict(m_statementDepth == 1);
+        return parseFunctionDeclaration(context);
+    case SEMICOLON:
+        next();
+        return context.createEmptyStatement();
+    case IF:
+        return parseIfStatement(context);
+    case DO:
+        return parseDoWhileStatement(context);
+    case WHILE:
+        return parseWhileStatement(context);
+    case FOR:
+        return parseForStatement(context);
+    case CONTINUE:
+        return parseContinueStatement(context);
+    case BREAK:
+        return parseBreakStatement(context);
+    case RETURN:
+        return parseReturnStatement(context);
+    case WITH:
+        return parseWithStatement(context);
+    case SWITCH:
+        return parseSwitchStatement(context);
+    case THROW:
+        return parseThrowStatement(context);
+    case TRY:
+        return parseTryStatement(context);
+    case DEBUGGER:
+        return parseDebuggerStatement(context);
+    case EOFTOK:
+    case CASE:
+    case CLOSEBRACE:
+    case DEFAULT:
+        // These tokens imply the end of a set of source elements
+        return 0;
+    case IDENT:
+        return parseExpressionOrLabelStatement(context);
+    case STRING:
+        directive = m_token.m_data.ident;
+        nonTrivialExpressionCount = m_nonTrivialExpressionCount;
+    default:
+        TreeStatement exprStatement = parseExpressionStatement(context);
+        if (directive && nonTrivialExpressionCount != m_nonTrivialExpressionCount)
+            directive = 0;
+        return exprStatement;
+    }
+}
+
+template <class TreeBuilder> TreeFormalParameterList JSParser::parseFormalParameters(TreeBuilder& context)
+{
+    matchOrFail(IDENT);
+    failIfFalseIfStrict(declareParameter(m_token.m_data.ident));
+    TreeFormalParameterList list = context.createFormalParameterList(*m_token.m_data.ident);
+    TreeFormalParameterList tail = list;
+    next();
+    while (match(COMMA)) {
+        next();
+        matchOrFail(IDENT);
+        const Identifier* ident = m_token.m_data.ident;
+        failIfFalseIfStrict(declareParameter(ident));
+        next();
+        tail = context.createFormalParameterList(tail, *ident);
+    }
+    return list;
+}
+
+template <class TreeBuilder> TreeFunctionBody JSParser::parseFunctionBody(TreeBuilder& context)
+{
+    if (match(CLOSEBRACE))
+        return context.createFunctionBody(strictMode());
+    DepthManager statementDepth(&m_statementDepth);
+    m_statementDepth = 0;
+    typename TreeBuilder::FunctionBodyBuilder bodyBuilder(m_globalData, m_lexer);
+    failIfFalse(parseSourceElements<CheckForStrictMode>(bodyBuilder));
+    return context.createFunctionBody(strictMode());
+}
+
+template <JSParser::FunctionRequirements requirements, bool nameIsInContainingScope, class TreeBuilder> bool JSParser::parseFunctionInfo(TreeBuilder& context, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, int& openBracePos, int& closeBracePos, int& bodyStartLine)
+{
+    AutoPopScopeRef functionScope(this, pushScope());
+    functionScope->setIsFunction();
+    if (match(IDENT)) {
+        name = m_token.m_data.ident;
+        failIfTrue(*name == m_globalData->propertyNames->underscoreProto);
+        next();
+        if (!nameIsInContainingScope)
+            failIfFalseIfStrict(functionScope->declareVariable(name));
+    } else if (requirements == FunctionNeedsName)
+        return false;
+    consumeOrFail(OPENPAREN);
+    if (!match(CLOSEPAREN)) {
+        parameters = parseFormalParameters(context);
+        failIfFalse(parameters);
+    }
+    consumeOrFail(CLOSEPAREN);
+    matchOrFail(OPENBRACE);
+
+    openBracePos = m_token.m_data.intValue;
+    bodyStartLine = tokenLine();
+
+    if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBracePos) : 0) {
+        // If we know about this function already, we can use the cached info and skip the parser to the end of the function.
+        body = context.createFunctionBody(strictMode());
+
+        functionScope->restoreFunctionInfo(cachedInfo);
+        failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
+
+        closeBracePos = cachedInfo->closeBracePos;
+        m_token = cachedInfo->closeBraceToken();
+        m_lexer->setOffset(m_token.m_info.endOffset);
+        m_lexer->setLineNumber(m_token.m_info.line);
+
+        next();
+        return true;
+    }
+
+    next();
+
+    body = parseFunctionBody(context);
+    failIfFalse(body);
+    if (functionScope->strictMode() && name) {
+        failIfTrue(m_globalData->propertyNames->arguments == *name);
+        failIfTrue(m_globalData->propertyNames->eval == *name);
+    }
+    closeBracePos = m_token.m_data.intValue;
+    
+    // Cache the tokenizer state and the function scope the first time the function is parsed.
+    // Any future reparsing can then skip the function.
+    static const int minimumFunctionLengthToCache = 64;
+    OwnPtr<SourceProviderCacheItem> newInfo;
+    int functionLength = closeBracePos - openBracePos;
+    if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) {
+        newInfo = adoptPtr(new SourceProviderCacheItem(m_token.m_info.line, closeBracePos));
+        functionScope->saveFunctionInfo(newInfo.get());
+    }
+    
+    failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo));
+    matchOrFail(CLOSEBRACE);
+
+    if (newInfo) {
+        unsigned approximateByteSize = newInfo->approximateByteSize();
+        m_functionCache->add(openBracePos, newInfo.release(), approximateByteSize);
+    }
+
+    next();
+    return true;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseFunctionDeclaration(TreeBuilder& context)
+{
+    ASSERT(match(FUNCTION));
+    next();
+    const Identifier* name = 0;
+    TreeFormalParameterList parameters = 0;
+    TreeFunctionBody body = 0;
+    int openBracePos = 0;
+    int closeBracePos = 0;
+    int bodyStartLine = 0;
+    failIfFalse((parseFunctionInfo<FunctionNeedsName, true>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
+    failIfFalse(name);
+    failIfFalseIfStrict(declareVariable(name));
+    return context.createFuncDeclStatement(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+}
+
+struct LabelInfo {
+    LabelInfo(const Identifier* ident, int start, int end)
+        : m_ident(ident)
+        , m_start(start)
+        , m_end(end)
+    {
+    }
+
+    const Identifier* m_ident;
+    int m_start;
+    int m_end;
+};
+
+template <class TreeBuilder> TreeStatement JSParser::parseExpressionOrLabelStatement(TreeBuilder& context)
+{
+
+    /* Expression and Label statements are ambiguous at LL(1), so we have a
+     * special case that looks for a colon as the next character in the input.
+     */
+    Vector<LabelInfo> labels;
+
+    do {
+        int start = tokenStart();
+        int startLine = tokenLine();
+        if (!nextTokenIsColon()) {
+            // If we hit this path we're making a expression statement, which
+            // by definition can't make use of continue/break so we can just
+            // ignore any labels we might have accumulated.
+            TreeExpression expression = parseExpression(context);
+            failIfFalse(expression);
+            failIfFalse(autoSemiColon());
+            return context.createExprStatement(expression, startLine, m_lastLine);
+        }
+        const Identifier* ident = m_token.m_data.ident;
+        int end = tokenEnd();
+        next();
+        consumeOrFail(COLON);
+        if (!m_syntaxAlreadyValidated) {
+            // This is O(N^2) over the current list of consecutive labels, but I
+            // have never seen more than one label in a row in the real world.
+            for (size_t i = 0; i < labels.size(); i++)
+                failIfTrue(ident->impl() == labels[i].m_ident->impl());
+            failIfTrue(getLabel(ident));
+            labels.append(LabelInfo(ident, start, end));
+        }
+    } while (match(IDENT));
+    bool isLoop = false;
+    switch (m_token.m_type) {
+    case FOR:
+    case WHILE:
+    case DO:
+        isLoop = true;
+        break;
+
+    default:
+        break;
+    }
+    const Identifier* unused = 0;
+    if (!m_syntaxAlreadyValidated) {
+        for (size_t i = 0; i < labels.size(); i++)
+            pushLabel(labels[i].m_ident, isLoop);
+    }
+    TreeStatement statement = parseStatement(context, unused);
+    if (!m_syntaxAlreadyValidated) {
+        for (size_t i = 0; i < labels.size(); i++)
+            popLabel();
+    }
+    failIfFalse(statement);
+    for (size_t i = 0; i < labels.size(); i++) {
+        const LabelInfo& info = labels[labels.size() - i - 1];
+        statement = context.createLabelStatement(info.m_ident, statement, info.m_start, info.m_end);
+    }
+    return statement;
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseExpressionStatement(TreeBuilder& context)
+{
+    int startLine = tokenLine();
+    TreeExpression expression = parseExpression(context);
+    failIfFalse(expression);
+    failIfFalse(autoSemiColon());
+    return context.createExprStatement(expression, startLine, m_lastLine);
+}
+
+template <class TreeBuilder> TreeStatement JSParser::parseIfStatement(TreeBuilder& context)
+{
+    ASSERT(match(IF));
+
+    int start = tokenLine();
+    next();
+
+    consumeOrFail(OPENPAREN);
+
+    TreeExpression condition = parseExpression(context);
+    failIfFalse(condition);
+    int end = tokenLine();
+    consumeOrFail(CLOSEPAREN);
+
+    const Identifier* unused = 0;
+    TreeStatement trueBlock = parseStatement(context, unused);
+    failIfFalse(trueBlock);
+
+    if (!match(ELSE))
+        return context.createIfStatement(condition, trueBlock, start, end);
+    
+    Vector<TreeExpression> exprStack;
+    Vector<pair<int, int> > posStack;
+    Vector<TreeStatement> statementStack;
+    bool trailingElse = false;
+    do {
+        next();
+        if (!match(IF)) {
+            const Identifier* unused = 0;
+            TreeStatement block = parseStatement(context, unused);
+            failIfFalse(block);
+            statementStack.append(block);
+            trailingElse = true;
+            break;
+        }
+        int innerStart = tokenLine();
+        next();
+        
+        consumeOrFail(OPENPAREN);
+        
+        TreeExpression innerCondition = parseExpression(context);
+        failIfFalse(innerCondition);
+        int innerEnd = tokenLine();
+        consumeOrFail(CLOSEPAREN);
+        const Identifier* unused = 0;
+        TreeStatement innerTrueBlock = parseStatement(context, unused);
+        failIfFalse(innerTrueBlock);     
+        exprStack.append(innerCondition);
+        posStack.append(make_pair(innerStart, innerEnd));
+        statementStack.append(innerTrueBlock);
+    } while (match(ELSE));
+
+    if (!trailingElse) {
+        TreeExpression condition = exprStack.last();
+        exprStack.removeLast();
+        TreeStatement trueBlock = statementStack.last();
+        statementStack.removeLast();
+        pair<int, int> pos = posStack.last();
+        posStack.removeLast();
+        statementStack.append(context.createIfStatement(condition, trueBlock, pos.first, pos.second));
+    }
+
+    while (!exprStack.isEmpty()) {
+        TreeExpression condition = exprStack.last();
+        exprStack.removeLast();
+        TreeStatement falseBlock = statementStack.last();
+        statementStack.removeLast();
+        TreeStatement trueBlock = statementStack.last();
+        statementStack.removeLast();
+        pair<int, int> pos = posStack.last();
+        posStack.removeLast();
+        statementStack.append(context.createIfStatement(condition, trueBlock, falseBlock, pos.first, pos.second));
+    }
+    
+    return context.createIfStatement(condition, trueBlock, statementStack.last(), start, end);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseExpression(TreeBuilder& context)
+{
+    failIfStackOverflow();
+    TreeExpression node = parseAssignmentExpression(context);
+    failIfFalse(node);
+    if (!match(COMMA))
+        return node;
+    next();
+    m_nonTrivialExpressionCount++;
+    m_nonLHSCount++;
+    TreeExpression right = parseAssignmentExpression(context);
+    failIfFalse(right);
+    typename TreeBuilder::Comma commaNode = context.createCommaExpr(node, right);
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        right = parseAssignmentExpression(context);
+        failIfFalse(right);
+        context.appendToComma(commaNode, right);
+    }
+    return commaNode;
+}
+
+
+template <typename TreeBuilder> TreeExpression JSParser::parseAssignmentExpression(TreeBuilder& context)
+{
+    failIfStackOverflow();
+    int start = tokenStart();
+    int initialAssignmentCount = m_assignmentCount;
+    int initialNonLHSCount = m_nonLHSCount;
+    TreeExpression lhs = parseConditionalExpression(context);
+    failIfFalse(lhs);
+    if (initialNonLHSCount != m_nonLHSCount)
+        return lhs;
+
+    int assignmentStack = 0;
+    Operator op;
+    bool hadAssignment = false;
+    while (true) {
+        switch (m_token.m_type) {
+        case EQUAL: op = OpEqual; break;
+        case PLUSEQUAL: op = OpPlusEq; break;
+        case MINUSEQUAL: op = OpMinusEq; break;
+        case MULTEQUAL: op = OpMultEq; break;
+        case DIVEQUAL: op = OpDivEq; break;
+        case LSHIFTEQUAL: op = OpLShift; break;
+        case RSHIFTEQUAL: op = OpRShift; break;
+        case URSHIFTEQUAL: op = OpURShift; break;
+        case ANDEQUAL: op = OpAndEq; break;
+        case XOREQUAL: op = OpXOrEq; break;
+        case OREQUAL: op = OpOrEq; break;
+        case MODEQUAL: op = OpModEq; break;
+        default:
+            goto end;
+        }
+        m_nonTrivialExpressionCount++;
+        hadAssignment = true;
+        context.assignmentStackAppend(assignmentStack, lhs, start, tokenStart(), m_assignmentCount, op);
+        start = tokenStart();
+        m_assignmentCount++;
+        next(TreeBuilder::DontBuildStrings);
+        if (strictMode() && m_lastIdentifier && context.isResolve(lhs)) {
+            failIfTrueIfStrict(m_globalData->propertyNames->eval == *m_lastIdentifier);
+            failIfTrueIfStrict(m_globalData->propertyNames->arguments == *m_lastIdentifier);
+            declareWrite(m_lastIdentifier);
+            m_lastIdentifier = 0;
+        }
+        lhs = parseConditionalExpression(context);
+        failIfFalse(lhs);
+        if (initialNonLHSCount != m_nonLHSCount)
+            break;
+    }
+end:
+    if (hadAssignment)
+        m_nonLHSCount++;
+
+    if (!TreeBuilder::CreatesAST)
+        return lhs;
+
+    while (assignmentStack)
+        lhs = context.createAssignment(assignmentStack, lhs, initialAssignmentCount, m_assignmentCount, lastTokenEnd());
+
+    return lhs;
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseConditionalExpression(TreeBuilder& context)
+{
+    TreeExpression cond = parseBinaryExpression(context);
+    failIfFalse(cond);
+    if (!match(QUESTION))
+        return cond;
+    m_nonTrivialExpressionCount++;
+    m_nonLHSCount++;
+    next(TreeBuilder::DontBuildStrings);
+    TreeExpression lhs = parseAssignmentExpression(context);
+    consumeOrFailWithFlags(COLON, TreeBuilder::DontBuildStrings);
+
+    TreeExpression rhs = parseAssignmentExpression(context);
+    failIfFalse(rhs);
+    return context.createConditionalExpr(cond, lhs, rhs);
+}
+
+ALWAYS_INLINE static bool isUnaryOp(JSTokenType token)
+{
+    return token & UnaryOpTokenFlag;
+}
+
+int JSParser::isBinaryOperator(JSTokenType token)
+{
+    if (m_allowsIn)
+        return token & (BinaryOpTokenPrecedenceMask << BinaryOpTokenAllowsInPrecedenceAdditionalShift);
+    return token & BinaryOpTokenPrecedenceMask;
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseBinaryExpression(TreeBuilder& context)
+{
+
+    int operandStackDepth = 0;
+    int operatorStackDepth = 0;
+    typename TreeBuilder::BinaryExprContext binaryExprContext(context);
+    while (true) {
+        int exprStart = tokenStart();
+        int initialAssignments = m_assignmentCount;
+        TreeExpression current = parseUnaryExpression(context);
+        failIfFalse(current);
+
+        context.appendBinaryExpressionInfo(operandStackDepth, current, exprStart, lastTokenEnd(), lastTokenEnd(), initialAssignments != m_assignmentCount);
+        int precedence = isBinaryOperator(m_token.m_type);
+        if (!precedence)
+            break;
+        m_nonTrivialExpressionCount++;
+        m_nonLHSCount++;
+        int operatorToken = m_token.m_type;
+        next(TreeBuilder::DontBuildStrings);
+
+        while (operatorStackDepth &&  context.operatorStackHasHigherPrecedence(operatorStackDepth, precedence)) {
+            ASSERT(operandStackDepth > 1);
+
+            typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
+            typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
+            context.shrinkOperandStackBy(operandStackDepth, 2);
+            context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
+            context.operatorStackPop(operatorStackDepth);
+        }
+        context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
+    }
+    while (operatorStackDepth) {
+        ASSERT(operandStackDepth > 1);
+
+        typename TreeBuilder::BinaryOperand rhs = context.getFromOperandStack(-1);
+        typename TreeBuilder::BinaryOperand lhs = context.getFromOperandStack(-2);
+        context.shrinkOperandStackBy(operandStackDepth, 2);
+        context.appendBinaryOperation(operandStackDepth, operatorStackDepth, lhs, rhs);
+        context.operatorStackPop(operatorStackDepth);
+    }
+    return context.popOperandStack(operandStackDepth);
+}
+
+
+template <bool complete, class TreeBuilder> TreeProperty JSParser::parseProperty(TreeBuilder& context)
+{
+    bool wasIdent = false;
+    switch (m_token.m_type) {
+    namedProperty:
+    case IDENT:
+        wasIdent = true;
+    case STRING: {
+        const Identifier* ident = m_token.m_data.ident;
+        if (complete || (wasIdent && (*ident == m_globalData->propertyNames->get || *ident == m_globalData->propertyNames->set)))
+            nextExpectIdentifier(Lexer::IgnoreReservedWords);
+        else
+            nextExpectIdentifier(Lexer::IgnoreReservedWords | TreeBuilder::DontBuildKeywords);
+
+        if (match(COLON)) {
+            next();
+            TreeExpression node = parseAssignmentExpression(context);
+            failIfFalse(node);
+            return context.template createProperty<complete>(ident, node, PropertyNode::Constant);
+        }
+        failIfFalse(wasIdent);
+        matchOrFail(IDENT);
+        const Identifier* accessorName = 0;
+        TreeFormalParameterList parameters = 0;
+        TreeFunctionBody body = 0;
+        int openBracePos = 0;
+        int closeBracePos = 0;
+        int bodyStartLine = 0;
+        PropertyNode::Type type;
+        if (*ident == m_globalData->propertyNames->get)
+            type = PropertyNode::Getter;
+        else if (*ident == m_globalData->propertyNames->set)
+            type = PropertyNode::Setter;
+        else
+            fail();
+        failIfFalse((parseFunctionInfo<FunctionNeedsName, false>(context, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
+        return context.template createGetterOrSetterProperty<complete>(type, accessorName, parameters, body, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+    }
+    case NUMBER: {
+        double propertyName = m_token.m_data.doubleValue;
+        next();
+        consumeOrFail(COLON);
+        TreeExpression node = parseAssignmentExpression(context);
+        failIfFalse(node);
+        return context.template createProperty<complete>(m_globalData, propertyName, node, PropertyNode::Constant);
+    }
+    default:
+        failIfFalse(m_token.m_type & KeywordTokenFlag);
+        goto namedProperty;
+    }
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseObjectLiteral(TreeBuilder& context)
+{
+    int startOffset = m_token.m_data.intValue;
+    consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings);
+
+    if (match(CLOSEBRACE)) {
+        next();
+        return context.createObjectLiteral();
+    }
+
+    TreeProperty property = parseProperty<false>(context);
+    failIfFalse(property);
+    if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+        m_lexer->setOffset(startOffset);
+        next();
+        return parseStrictObjectLiteral(context);
+    }
+    TreePropertyList propertyList = context.createPropertyList(property);
+    TreePropertyList tail = propertyList;
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
+        if (match(CLOSEBRACE))
+            break;
+        property = parseProperty<false>(context);
+        failIfFalse(property);
+        if (!m_syntaxAlreadyValidated && context.getType(property) != PropertyNode::Constant) {
+            m_lexer->setOffset(startOffset);
+            next();
+            return parseStrictObjectLiteral(context);
+        }
+        tail = context.createPropertyList(property, tail);
+    }
+
+    consumeOrFail(CLOSEBRACE);
+
+    return context.createObjectLiteral(propertyList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseStrictObjectLiteral(TreeBuilder& context)
+{
+    consumeOrFail(OPENBRACE);
+    
+    if (match(CLOSEBRACE)) {
+        next();
+        return context.createObjectLiteral();
+    }
+    
+    TreeProperty property = parseProperty<true>(context);
+    failIfFalse(property);
+    
+    typedef HashMap<RefPtr<StringImpl>, unsigned, IdentifierRepHash> ObjectValidationMap;
+    ObjectValidationMap objectValidator;
+    // Add the first property
+    if (!m_syntaxAlreadyValidated)
+        objectValidator.add(context.getName(property).impl(), context.getType(property));
+    
+    TreePropertyList propertyList = context.createPropertyList(property);
+    TreePropertyList tail = propertyList;
+    while (match(COMMA)) {
+        next();
+        // allow extra comma, see http://bugs.webkit.org/show_bug.cgi?id=5939
+        if (match(CLOSEBRACE))
+            break;
+        property = parseProperty<true>(context);
+        failIfFalse(property);
+        if (!m_syntaxAlreadyValidated) {
+            std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).impl(), context.getType(property));
+            if (!propertyEntryIter.second) {
+                failIfTrue(propertyEntryIter.first->second == PropertyNode::Constant);
+                failIfTrue(context.getType(property) == PropertyNode::Constant);
+                failIfTrue(context.getType(property) & propertyEntryIter.first->second);
+                propertyEntryIter.first->second |= context.getType(property);
+            }
+        }
+        tail = context.createPropertyList(property, tail);
+    }
+    
+    consumeOrFail(CLOSEBRACE);
+    
+    return context.createObjectLiteral(propertyList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseArrayLiteral(TreeBuilder& context)
+{
+    consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings);
+
+    int elisions = 0;
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        elisions++;
+    }
+    if (match(CLOSEBRACKET)) {
+        next(TreeBuilder::DontBuildStrings);
+        return context.createArray(elisions);
+    }
+
+    TreeExpression elem = parseAssignmentExpression(context);
+    failIfFalse(elem);
+    typename TreeBuilder::ElementList elementList = context.createElementList(elisions, elem);
+    typename TreeBuilder::ElementList tail = elementList;
+    elisions = 0;
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        elisions = 0;
+
+        while (match(COMMA)) {
+            next();
+            elisions++;
+        }
+
+        if (match(CLOSEBRACKET)) {
+            next(TreeBuilder::DontBuildStrings);
+            return context.createArray(elisions, elementList);
+        }
+        TreeExpression elem = parseAssignmentExpression(context);
+        failIfFalse(elem);
+        tail = context.createElementList(tail, elisions, elem);
+    }
+
+    consumeOrFail(CLOSEBRACKET);
+
+    return context.createArray(elementList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parsePrimaryExpression(TreeBuilder& context)
+{
+    switch (m_token.m_type) {
+    case OPENBRACE:
+        if (strictMode())
+            return parseStrictObjectLiteral(context);
+        return parseObjectLiteral(context);
+    case OPENBRACKET:
+        return parseArrayLiteral(context);
+    case OPENPAREN: {
+        next();
+        int oldNonLHSCount = m_nonLHSCount;
+        TreeExpression result = parseExpression(context);
+        m_nonLHSCount = oldNonLHSCount;
+        consumeOrFail(CLOSEPAREN);
+
+        return result;
+    }
+    case THISTOKEN: {
+        next();
+        return context.thisExpr();
+    }
+    case IDENT: {
+        int start = tokenStart();
+        const Identifier* ident = m_token.m_data.ident;
+        next();
+        currentScope()->useVariable(ident, m_globalData->propertyNames->eval == *ident);
+        m_lastIdentifier = ident;
+        return context.createResolve(ident, start);
+    }
+    case STRING: {
+        const Identifier* ident = m_token.m_data.ident;
+        next();
+        return context.createString(ident);
+    }
+    case NUMBER: {
+        double d = m_token.m_data.doubleValue;
+        next();
+        return context.createNumberExpr(d);
+    }
+    case NULLTOKEN: {
+        next();
+        return context.createNull();
+    }
+    case TRUETOKEN: {
+        next();
+        return context.createBoolean(true);
+    }
+    case FALSETOKEN: {
+        next();
+        return context.createBoolean(false);
+    }
+    case DIVEQUAL:
+    case DIVIDE: {
+        /* regexp */
+        const Identifier* pattern;
+        const Identifier* flags;
+        if (match(DIVEQUAL))
+            failIfFalse(m_lexer->scanRegExp(pattern, flags, '='));
+        else
+            failIfFalse(m_lexer->scanRegExp(pattern, flags));
+
+        int start = tokenStart();
+        next();
+        TreeExpression re = context.createRegExp(*pattern, *flags, start);
+        if (!re) {
+            m_errorMessage = Yarr::checkSyntax(pattern->ustring());
+            ASSERT(m_errorMessage);
+            fail();
+        }
+        return re;
+    }
+    default:
+        fail();
+    }
+}
+
+template <class TreeBuilder> TreeArguments JSParser::parseArguments(TreeBuilder& context)
+{
+    consumeOrFailWithFlags(OPENPAREN, TreeBuilder::DontBuildStrings);
+    if (match(CLOSEPAREN)) {
+        next(TreeBuilder::DontBuildStrings);
+        return context.createArguments();
+    }
+    TreeExpression firstArg = parseAssignmentExpression(context);
+    failIfFalse(firstArg);
+
+    TreeArgumentsList argList = context.createArgumentsList(firstArg);
+    TreeArgumentsList tail = argList;
+    while (match(COMMA)) {
+        next(TreeBuilder::DontBuildStrings);
+        TreeExpression arg = parseAssignmentExpression(context);
+        failIfFalse(arg);
+        tail = context.createArgumentsList(tail, arg);
+    }
+    consumeOrFail(CLOSEPAREN);
+    return context.createArguments(argList);
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseMemberExpression(TreeBuilder& context)
+{
+    TreeExpression base = 0;
+    int start = tokenStart();
+    int expressionStart = start;
+    int newCount = 0;
+    while (match(NEW)) {
+        next();
+        newCount++;
+    }
+
+    if (match(FUNCTION)) {
+        const Identifier* name = &m_globalData->propertyNames->nullIdentifier;
+        TreeFormalParameterList parameters = 0;
+        TreeFunctionBody body = 0;
+        int openBracePos = 0;
+        int closeBracePos = 0;
+        int bodyStartLine = 0;
+        next();
+        failIfFalse((parseFunctionInfo<FunctionNoRequirements, false>(context, name, parameters, body, openBracePos, closeBracePos, bodyStartLine)));
+        base = context.createFunctionExpr(name, body, parameters, openBracePos, closeBracePos, bodyStartLine, m_lastLine);
+    } else
+        base = parsePrimaryExpression(context);
+
+    failIfFalse(base);
+    while (true) {
+        switch (m_token.m_type) {
+        case OPENBRACKET: {
+            m_nonTrivialExpressionCount++;
+            int expressionEnd = lastTokenEnd();
+            next();
+            int nonLHSCount = m_nonLHSCount;
+            int initialAssignments = m_assignmentCount;
+            TreeExpression property = parseExpression(context);
+            failIfFalse(property);
+            base = context.createBracketAccess(base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEnd());
+            if (!consume(CLOSEBRACKET))
+                fail();
+            m_nonLHSCount = nonLHSCount;
+            break;
+        }
+        case OPENPAREN: {
+            m_nonTrivialExpressionCount++;
+            if (newCount) {
+                newCount--;
+                if (match(OPENPAREN)) {
+                    int exprEnd = lastTokenEnd();
+                    TreeArguments arguments = parseArguments(context);
+                    failIfFalse(arguments);
+                    base = context.createNewExpr(base, arguments, start, exprEnd, lastTokenEnd());
+                } else
+                    base = context.createNewExpr(base, start, lastTokenEnd());               
+            } else {
+                int nonLHSCount = m_nonLHSCount;
+                int expressionEnd = lastTokenEnd();
+                TreeArguments arguments = parseArguments(context);
+                failIfFalse(arguments);
+                base = context.makeFunctionCallNode(base, arguments, expressionStart, expressionEnd, lastTokenEnd());
+                m_nonLHSCount = nonLHSCount;
+            }
+            break;
+        }
+        case DOT: {
+            m_nonTrivialExpressionCount++;
+            int expressionEnd = lastTokenEnd();
+            nextExpectIdentifier(Lexer::IgnoreReservedWords | TreeBuilder::DontBuildKeywords);
+            matchOrFail(IDENT);
+            base = context.createDotAccess(base, m_token.m_data.ident, expressionStart, expressionEnd, tokenEnd());
+            next();
+            break;
+        }
+        default:
+            goto endMemberExpression;
+        }
+    }
+endMemberExpression:
+    while (newCount--)
+        base = context.createNewExpr(base, start, lastTokenEnd());
+    return base;
+}
+
+template <class TreeBuilder> TreeExpression JSParser::parseUnaryExpression(TreeBuilder& context)
+{
+    typename TreeBuilder::UnaryExprContext unaryExprContext(context);
+    AllowInOverride allowInOverride(this);
+    int tokenStackDepth = 0;
+    bool modifiesExpr = false;
+    bool requiresLExpr = false;
+    while (isUnaryOp(m_token.m_type)) {
+        if (strictMode()) {
+            switch (m_token.m_type) {
+            case PLUSPLUS:
+            case MINUSMINUS:
+            case AUTOPLUSPLUS:
+            case AUTOMINUSMINUS:
+                failIfTrue(requiresLExpr);
+                modifiesExpr = true;
+                requiresLExpr = true;
+                break;
+            case DELETETOKEN:
+                failIfTrue(requiresLExpr);
+                requiresLExpr = true;
+                break;
+            default:
+                failIfTrue(requiresLExpr);
+                break;
+            }
+        }
+        m_nonLHSCount++;
+        context.appendUnaryToken(tokenStackDepth, m_token.m_type, tokenStart());
+        next();
+        m_nonTrivialExpressionCount++;
+    }
+    int subExprStart = tokenStart();
+    TreeExpression expr = parseMemberExpression(context);
+    failIfFalse(expr);
+    bool isEvalOrArguments = false;
+    if (strictMode() && !m_syntaxAlreadyValidated) {
+        if (context.isResolve(expr)) {
+            isEvalOrArguments = *m_lastIdentifier == m_globalData->propertyNames->eval || *m_lastIdentifier == m_globalData->propertyNames->arguments;
+        }
+    }
+    failIfTrueIfStrict(isEvalOrArguments && modifiesExpr);
+    switch (m_token.m_type) {
+    case PLUSPLUS:
+        m_nonTrivialExpressionCount++;
+        m_nonLHSCount++;
+        expr = context.makePostfixNode(expr, OpPlusPlus, subExprStart, lastTokenEnd(), tokenEnd());
+        m_assignmentCount++;
+        failIfTrueIfStrict(isEvalOrArguments);
+        failIfTrueIfStrict(requiresLExpr);
+        next();
+        break;
+    case MINUSMINUS:
+        m_nonTrivialExpressionCount++;
+        m_nonLHSCount++;
+        expr = context.makePostfixNode(expr, OpMinusMinus, subExprStart, lastTokenEnd(), tokenEnd());
+        m_assignmentCount++;
+        failIfTrueIfStrict(isEvalOrArguments);
+        failIfTrueIfStrict(requiresLExpr);
+        next();
+        break;
+    default:
+        break;
+    }
+
+    int end = lastTokenEnd();
+
+    if (!TreeBuilder::CreatesAST && (m_syntaxAlreadyValidated || !strictMode()))
+        return expr;
+
+    while (tokenStackDepth) {
+        switch (context.unaryTokenStackLastType(tokenStackDepth)) {
+        case EXCLAMATION:
+            expr = context.createLogicalNot(expr);
+            break;
+        case TILDE:
+            expr = context.makeBitwiseNotNode(expr);
+            break;
+        case MINUS:
+            expr = context.makeNegateNode(expr);
+            break;
+        case PLUS:
+            expr = context.createUnaryPlus(expr);
+            break;
+        case PLUSPLUS:
+        case AUTOPLUSPLUS:
+            expr = context.makePrefixNode(expr, OpPlusPlus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
+            m_assignmentCount++;
+            break;
+        case MINUSMINUS:
+        case AUTOMINUSMINUS:
+            expr = context.makePrefixNode(expr, OpMinusMinus, context.unaryTokenStackLastStart(tokenStackDepth), subExprStart + 1, end);
+            m_assignmentCount++;
+            break;
+        case TYPEOF:
+            expr = context.makeTypeOfNode(expr);
+            break;
+        case VOIDTOKEN:
+            expr = context.createVoid(expr);
+            break;
+        case DELETETOKEN:
+            failIfTrueIfStrict(context.isResolve(expr));
+            expr = context.makeDeleteNode(expr, context.unaryTokenStackLastStart(tokenStackDepth), end, end);
+            break;
+        default:
+            // If we get here something has gone horribly horribly wrong
+            CRASH();
+        }
+        subExprStart = context.unaryTokenStackLastStart(tokenStackDepth);
+        context.unaryTokenStackRemoveLast(tokenStackDepth);
+    }
+    return expr;
+}
+
+}
+
+namespace WTF
+{
+    template <> struct VectorTraits<JSC::JSParser::Scope> : SimpleClassVectorTraits {
+        static const bool canInitializeWithMemset = false; // Not all Scope data members initialize to 0.
+    };
+}
diff --git a/parser/JSParser.h b/parser/JSParser.h
new file mode 100644 (file)
index 0000000..8bb7dbb
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 JSParser_h
+#define JSParser_h
+
+namespace JSC {
+
+class ExecState;
+class FunctionParameters;
+class Identifier;
+class JSGlobalData;
+class SourceCode;
+
+enum {
+    UnaryOpTokenFlag = 64,
+    KeywordTokenFlag = 128,
+    BinaryOpTokenPrecedenceShift = 8,
+    BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4,
+    BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift,
+};
+
+#define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)))
+#define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))
+
+enum JSTokenType {
+    NULLTOKEN = KeywordTokenFlag,
+    TRUETOKEN,
+    FALSETOKEN,
+    BREAK,
+    CASE,
+    DEFAULT,
+    FOR,
+    NEW,
+    VAR,
+    CONSTTOKEN,
+    CONTINUE,
+    FUNCTION,
+    RETURN,
+    IF,
+    THISTOKEN,
+    DO,
+    WHILE,
+    SWITCH,
+    WITH,
+    RESERVED,
+    THROW,
+    TRY,
+    CATCH,
+    FINALLY,
+    DEBUGGER,
+    ELSE,
+    OPENBRACE = 0,
+    CLOSEBRACE,
+    OPENPAREN,
+    CLOSEPAREN,
+    OPENBRACKET,
+    CLOSEBRACKET,
+    COMMA,
+    QUESTION,
+    NUMBER,
+    IDENT,
+    STRING,
+    SEMICOLON,
+    COLON,
+    DOT,
+    ERRORTOK,
+    EOFTOK,
+    EQUAL,
+    PLUSEQUAL,
+    MINUSEQUAL,
+    MULTEQUAL,
+    DIVEQUAL,
+    LSHIFTEQUAL,
+    RSHIFTEQUAL,
+    URSHIFTEQUAL,
+    ANDEQUAL,
+    MODEQUAL,
+    XOREQUAL,
+    OREQUAL,
+    LastUntaggedToken,
+
+    // Begin tagged tokens
+    PLUSPLUS = 0 | UnaryOpTokenFlag,
+    MINUSMINUS = 1 | UnaryOpTokenFlag,
+    EXCLAMATION = 2 | UnaryOpTokenFlag,
+    TILDE = 3 | UnaryOpTokenFlag,
+    AUTOPLUSPLUS = 4 | UnaryOpTokenFlag,
+    AUTOMINUSMINUS = 5 | UnaryOpTokenFlag,
+    TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag,
+    VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag,
+    DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag,
+    OR = 0 | BINARY_OP_PRECEDENCE(1),
+    AND = 1 | BINARY_OP_PRECEDENCE(2),
+    BITOR = 2 | BINARY_OP_PRECEDENCE(3),
+    BITXOR = 3 | BINARY_OP_PRECEDENCE(4),
+    BITAND = 4 | BINARY_OP_PRECEDENCE(5),
+    EQEQ = 5 | BINARY_OP_PRECEDENCE(6),
+    NE = 6 | BINARY_OP_PRECEDENCE(6),
+    STREQ = 7 | BINARY_OP_PRECEDENCE(6),
+    STRNEQ = 8 | BINARY_OP_PRECEDENCE(6),
+    LT = 9 | BINARY_OP_PRECEDENCE(7),
+    GT = 10 | BINARY_OP_PRECEDENCE(7),
+    LE = 11 | BINARY_OP_PRECEDENCE(7),
+    GE = 12 | BINARY_OP_PRECEDENCE(7),
+    INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7) | KeywordTokenFlag,
+    INTOKEN = 14 | IN_OP_PRECEDENCE(7) | KeywordTokenFlag,
+    LSHIFT = 15 | BINARY_OP_PRECEDENCE(8),
+    RSHIFT = 16 | BINARY_OP_PRECEDENCE(8),
+    URSHIFT = 17 | BINARY_OP_PRECEDENCE(8),
+    PLUS = 18 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
+    MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag,
+    TIMES = 20 | BINARY_OP_PRECEDENCE(10),
+    DIVIDE = 21 | BINARY_OP_PRECEDENCE(10),
+    MOD = 22 | BINARY_OP_PRECEDENCE(10)
+};
+
+union JSTokenData {
+    int intValue;
+    double doubleValue;
+    const Identifier* ident;
+};
+
+struct JSTokenInfo {
+    JSTokenInfo() : line(0) {}
+    int line;
+    int startOffset;
+    int endOffset;
+};
+
+struct JSToken {
+    JSTokenType m_type;
+    JSTokenData m_data;
+    JSTokenInfo m_info;
+};
+
+enum JSParserStrictness { JSParseNormal, JSParseStrict };
+enum JSParserMode { JSParseProgramCode, JSParseFunctionCode };
+
+const char* jsParse(JSGlobalData*, FunctionParameters*, JSParserStrictness, JSParserMode, const SourceCode*);
+}
+#endif // JSParser_h
index bdeb04936c2b1d4af970ea7482b7e55d9c093e22..cae6bb99daeacfce8f75fa9783c6976936b22817 100644 (file)
@@ -2,6 +2,7 @@
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
+ *  Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu)
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -24,7 +25,9 @@
 #include "Lexer.h"
 
 #include "JSFunction.h"
+
 #include "JSGlobalObjectFunctions.h"
+#include "Identifier.h"
 #include "NodeInfo.h"
 #include "Nodes.h"
 #include "dtoa.h"
 using namespace WTF;
 using namespace Unicode;
 
-// We can't specify the namespace in yacc's C output, so do it here instead.
-using namespace JSC;
-
-#include "Grammar.h"
+#include "JSParser.h"
+#include "KeywordLookup.h"
 #include "Lookup.h"
 #include "Lexer.lut.h"
 
 namespace JSC {
 
-static const UChar byteOrderMark = 0xFEFF;
+
+enum CharacterType {
+    // Types for the main switch
+
+    // The first three types are fixed, and also used for identifying
+    // ASCII alpha and alphanumeric characters (see isIdentStart and isIdentPart).
+    CharacterIdentifierStart,
+    CharacterZero,
+    CharacterNumber,
+
+    CharacterInvalid,
+    CharacterLineTerminator,
+    CharacterExclamationMark,
+    CharacterOpenParen,
+    CharacterCloseParen,
+    CharacterOpenBracket,
+    CharacterCloseBracket,
+    CharacterComma,
+    CharacterColon,
+    CharacterQuestion,
+    CharacterTilde,
+    CharacterQuote,
+    CharacterDot,
+    CharacterSlash,
+    CharacterBackSlash,
+    CharacterSemicolon,
+    CharacterOpenBrace,
+    CharacterCloseBrace,
+
+    CharacterAdd,
+    CharacterSub,
+    CharacterMultiply,
+    CharacterModulo,
+    CharacterAnd,
+    CharacterXor,
+    CharacterOr,
+    CharacterLess,
+    CharacterGreater,
+    CharacterEqual,
+
+    // Other types (only one so far)
+    CharacterWhiteSpace,
+};
+
+// 128 ASCII codes
+static const unsigned short typesOfASCIICharacters[128] = {
+/*   0 - Null               */ CharacterInvalid,
+/*   1 - Start of Heading   */ CharacterInvalid,
+/*   2 - Start of Text      */ CharacterInvalid,
+/*   3 - End of Text        */ CharacterInvalid,
+/*   4 - End of Transm.     */ CharacterInvalid,
+/*   5 - Enquiry            */ CharacterInvalid,
+/*   6 - Acknowledgment     */ CharacterInvalid,
+/*   7 - Bell               */ CharacterInvalid,
+/*   8 - Back Space         */ CharacterInvalid,
+/*   9 - Horizontal Tab     */ CharacterWhiteSpace,
+/*  10 - Line Feed          */ CharacterLineTerminator,
+/*  11 - Vertical Tab       */ CharacterWhiteSpace,
+/*  12 - Form Feed          */ CharacterWhiteSpace,
+/*  13 - Carriage Return    */ CharacterLineTerminator,
+/*  14 - Shift Out          */ CharacterInvalid,
+/*  15 - Shift In           */ CharacterInvalid,
+/*  16 - Data Line Escape   */ CharacterInvalid,
+/*  17 - Device Control 1   */ CharacterInvalid,
+/*  18 - Device Control 2   */ CharacterInvalid,
+/*  19 - Device Control 3   */ CharacterInvalid,
+/*  20 - Device Control 4   */ CharacterInvalid,
+/*  21 - Negative Ack.      */ CharacterInvalid,
+/*  22 - Synchronous Idle   */ CharacterInvalid,
+/*  23 - End of Transmit    */ CharacterInvalid,
+/*  24 - Cancel             */ CharacterInvalid,
+/*  25 - End of Medium      */ CharacterInvalid,
+/*  26 - Substitute         */ CharacterInvalid,
+/*  27 - Escape             */ CharacterInvalid,
+/*  28 - File Separator     */ CharacterInvalid,
+/*  29 - Group Separator    */ CharacterInvalid,
+/*  30 - Record Separator   */ CharacterInvalid,
+/*  31 - Unit Separator     */ CharacterInvalid,
+/*  32 - Space              */ CharacterWhiteSpace,
+/*  33 - !                  */ CharacterExclamationMark,
+/*  34 - "                  */ CharacterQuote,
+/*  35 - #                  */ CharacterInvalid,
+/*  36 - $                  */ CharacterIdentifierStart,
+/*  37 - %                  */ CharacterModulo,
+/*  38 - &                  */ CharacterAnd,
+/*  39 - '                  */ CharacterQuote,
+/*  40 - (                  */ CharacterOpenParen,
+/*  41 - )                  */ CharacterCloseParen,
+/*  42 - *                  */ CharacterMultiply,
+/*  43 - +                  */ CharacterAdd,
+/*  44 - ,                  */ CharacterComma,
+/*  45 - -                  */ CharacterSub,
+/*  46 - .                  */ CharacterDot,
+/*  47 - /                  */ CharacterSlash,
+/*  48 - 0                  */ CharacterZero,
+/*  49 - 1                  */ CharacterNumber,
+/*  50 - 2                  */ CharacterNumber,
+/*  51 - 3                  */ CharacterNumber,
+/*  52 - 4                  */ CharacterNumber,
+/*  53 - 5                  */ CharacterNumber,
+/*  54 - 6                  */ CharacterNumber,
+/*  55 - 7                  */ CharacterNumber,
+/*  56 - 8                  */ CharacterNumber,
+/*  57 - 9                  */ CharacterNumber,
+/*  58 - :                  */ CharacterColon,
+/*  59 - ;                  */ CharacterSemicolon,
+/*  60 - <                  */ CharacterLess,
+/*  61 - =                  */ CharacterEqual,
+/*  62 - >                  */ CharacterGreater,
+/*  63 - ?                  */ CharacterQuestion,
+/*  64 - @                  */ CharacterInvalid,
+/*  65 - A                  */ CharacterIdentifierStart,
+/*  66 - B                  */ CharacterIdentifierStart,
+/*  67 - C                  */ CharacterIdentifierStart,
+/*  68 - D                  */ CharacterIdentifierStart,
+/*  69 - E                  */ CharacterIdentifierStart,
+/*  70 - F                  */ CharacterIdentifierStart,
+/*  71 - G                  */ CharacterIdentifierStart,
+/*  72 - H                  */ CharacterIdentifierStart,
+/*  73 - I                  */ CharacterIdentifierStart,
+/*  74 - J                  */ CharacterIdentifierStart,
+/*  75 - K                  */ CharacterIdentifierStart,
+/*  76 - L                  */ CharacterIdentifierStart,
+/*  77 - M                  */ CharacterIdentifierStart,
+/*  78 - N                  */ CharacterIdentifierStart,
+/*  79 - O                  */ CharacterIdentifierStart,
+/*  80 - P                  */ CharacterIdentifierStart,
+/*  81 - Q                  */ CharacterIdentifierStart,
+/*  82 - R                  */ CharacterIdentifierStart,
+/*  83 - S                  */ CharacterIdentifierStart,
+/*  84 - T                  */ CharacterIdentifierStart,
+/*  85 - U                  */ CharacterIdentifierStart,
+/*  86 - V                  */ CharacterIdentifierStart,
+/*  87 - W                  */ CharacterIdentifierStart,
+/*  88 - X                  */ CharacterIdentifierStart,
+/*  89 - Y                  */ CharacterIdentifierStart,
+/*  90 - Z                  */ CharacterIdentifierStart,
+/*  91 - [                  */ CharacterOpenBracket,
+/*  92 - \                  */ CharacterBackSlash,
+/*  93 - ]                  */ CharacterCloseBracket,
+/*  94 - ^                  */ CharacterXor,
+/*  95 - _                  */ CharacterIdentifierStart,
+/*  96 - `                  */ CharacterInvalid,
+/*  97 - a                  */ CharacterIdentifierStart,
+/*  98 - b                  */ CharacterIdentifierStart,
+/*  99 - c                  */ CharacterIdentifierStart,
+/* 100 - d                  */ CharacterIdentifierStart,
+/* 101 - e                  */ CharacterIdentifierStart,
+/* 102 - f                  */ CharacterIdentifierStart,
+/* 103 - g                  */ CharacterIdentifierStart,
+/* 104 - h                  */ CharacterIdentifierStart,
+/* 105 - i                  */ CharacterIdentifierStart,
+/* 106 - j                  */ CharacterIdentifierStart,
+/* 107 - k                  */ CharacterIdentifierStart,
+/* 108 - l                  */ CharacterIdentifierStart,
+/* 109 - m                  */ CharacterIdentifierStart,
+/* 110 - n                  */ CharacterIdentifierStart,
+/* 111 - o                  */ CharacterIdentifierStart,
+/* 112 - p                  */ CharacterIdentifierStart,
+/* 113 - q                  */ CharacterIdentifierStart,
+/* 114 - r                  */ CharacterIdentifierStart,
+/* 115 - s                  */ CharacterIdentifierStart,
+/* 116 - t                  */ CharacterIdentifierStart,
+/* 117 - u                  */ CharacterIdentifierStart,
+/* 118 - v                  */ CharacterIdentifierStart,
+/* 119 - w                  */ CharacterIdentifierStart,
+/* 120 - x                  */ CharacterIdentifierStart,
+/* 121 - y                  */ CharacterIdentifierStart,
+/* 122 - z                  */ CharacterIdentifierStart,
+/* 123 - {                  */ CharacterOpenBrace,
+/* 124 - |                  */ CharacterOr,
+/* 125 - }                  */ CharacterCloseBrace,
+/* 126 - ~                  */ CharacterTilde,
+/* 127 - Delete             */ CharacterInvalid,
+};
 
 Lexer::Lexer(JSGlobalData* globalData)
     : m_isReparsing(false)
@@ -59,77 +234,17 @@ Lexer::~Lexer()
     m_keywordTable.deleteTable();
 }
 
-inline const UChar* Lexer::currentCharacter() const
+ALWAYS_INLINE const UChar* Lexer::currentCharacter() const
 {
-    return m_code - 4;
+    ASSERT(m_code <= m_codeEnd);
+    return m_code;
 }
 
-inline int Lexer::currentOffset() const
+ALWAYS_INLINE int Lexer::currentOffset() const
 {
     return currentCharacter() - m_codeStart;
 }
 
-ALWAYS_INLINE void Lexer::shift1()
-{
-    m_current = m_next1;
-    m_next1 = m_next2;
-    m_next2 = m_next3;
-    if (LIKELY(m_code < m_codeEnd))
-        m_next3 = m_code[0];
-    else
-        m_next3 = -1;
-
-    ++m_code;
-}
-
-ALWAYS_INLINE void Lexer::shift2()
-{
-    m_current = m_next2;
-    m_next1 = m_next3;
-    if (LIKELY(m_code + 1 < m_codeEnd)) {
-        m_next2 = m_code[0];
-        m_next3 = m_code[1];
-    } else {
-        m_next2 = m_code < m_codeEnd ? m_code[0] : -1;
-        m_next3 = -1;
-    }
-
-    m_code += 2;
-}
-
-ALWAYS_INLINE void Lexer::shift3()
-{
-    m_current = m_next3;
-    if (LIKELY(m_code + 2 < m_codeEnd)) {
-        m_next1 = m_code[0];
-        m_next2 = m_code[1];
-        m_next3 = m_code[2];
-    } else {
-        m_next1 = m_code < m_codeEnd ? m_code[0] : -1;
-        m_next2 = m_code + 1 < m_codeEnd ? m_code[1] : -1;
-        m_next3 = -1;
-    }
-
-    m_code += 3;
-}
-
-ALWAYS_INLINE void Lexer::shift4()
-{
-    if (LIKELY(m_code + 3 < m_codeEnd)) {
-        m_current = m_code[0];
-        m_next1 = m_code[1];
-        m_next2 = m_code[2];
-        m_next3 = m_code[3];
-    } else {
-        m_current = m_code < m_codeEnd ? m_code[0] : -1;
-        m_next1 = m_code + 1 < m_codeEnd ? m_code[1] : -1;
-        m_next2 = m_code + 2 < m_codeEnd ? m_code[2] : -1;
-        m_next3 = -1;
-    }
-
-    m_code += 4;
-}
-
 void Lexer::setCode(const SourceCode& source, ParserArena& arena)
 {
     m_arena = &arena.identifierArena();
@@ -150,60 +265,73 @@ void Lexer::setCode(const SourceCode& source, ParserArena& arena)
     m_buffer8.reserveInitialCapacity(initialReadBufferCapacity);
     m_buffer16.reserveInitialCapacity((m_codeEnd - m_code) / 2);
 
-    // ECMA-262 calls for stripping all Cf characters, but we only strip BOM characters.
-    // See <https://bugs.webkit.org/show_bug.cgi?id=4931> for details.
-    if (source.provider()->hasBOMs()) {
-        for (const UChar* p = m_codeStart; p < m_codeEnd; ++p) {
-            if (UNLIKELY(*p == byteOrderMark)) {
-                copyCodeWithoutBOMs();
-                break;
-            }
-        }
-    }
-
-    // Read the first characters into the 4-character buffer.
-    shift4();
+    if (LIKELY(m_code < m_codeEnd))
+        m_current = *m_code;
+    else
+        m_current = -1;
     ASSERT(currentOffset() == source.startOffset());
 }
 
-void Lexer::copyCodeWithoutBOMs()
+template <int shiftAmount, Lexer::ShiftType shouldBoundsCheck> ALWAYS_INLINE void Lexer::internalShift()
 {
-    // Note: In this case, the character offset data for debugging will be incorrect.
-    // If it's important to correctly debug code with extraneous BOMs, then the caller
-    // should strip the BOMs when creating the SourceProvider object and do its own
-    // mapping of offsets within the stripped text to original text offset.
-
-    m_codeWithoutBOMs.reserveCapacity(m_codeEnd - m_code);
-    for (const UChar* p = m_code; p < m_codeEnd; ++p) {
-        UChar c = *p;
-        if (c != byteOrderMark)
-            m_codeWithoutBOMs.append(c);
+    if (shouldBoundsCheck == DoBoundsCheck) {
+        // Faster than an if-else sequence
+        ASSERT(m_current != -1);
+        m_current = -1;
+        m_code += shiftAmount;
+        if (LIKELY(m_code < m_codeEnd))
+            m_current = *m_code;
+    } else {
+        m_code += shiftAmount;
+        m_current = *m_code;
     }
-    ptrdiff_t startDelta = m_codeStart - m_code;
-    m_code = m_codeWithoutBOMs.data();
-    m_codeStart = m_code + startDelta;
-    m_codeEnd = m_codeWithoutBOMs.data() + m_codeWithoutBOMs.size();
+}
+
+ALWAYS_INLINE void Lexer::shift()
+{
+    internalShift<1, DoBoundsCheck>();
+}
+
+ALWAYS_INLINE int Lexer::peek(int offset)
+{
+    // Only use if necessary
+    ASSERT(offset > 0 && offset < 5);
+    const UChar* code = m_code + offset;
+    return (code < m_codeEnd) ? *code : -1;
+}
+
+int Lexer::getUnicodeCharacter()
+{
+    int char1 = peek(1);
+    int char2 = peek(2);
+    int char3 = peek(3);
+
+    if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(char1) || !isASCIIHexDigit(char2) || !isASCIIHexDigit(char3)))
+        return -1;
+
+    int result = convertUnicode(m_current, char1, char2, char3);
+    shift();
+    shift();
+    shift();
+    shift();
+    return result;
 }
 
 void Lexer::shiftLineTerminator()
 {
     ASSERT(isLineTerminator(m_current));
 
+    int m_prev = m_current;
+    shift();
+
     // Allow both CRLF and LFCR.
-    if (m_current + m_next1 == '\n' + '\r')
-        shift2();
-    else
-        shift1();
+    if (m_prev + m_current == '\n' + '\r')
+        shift();
 
     ++m_lineNumber;
 }
 
-ALWAYS_INLINE const Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
-{
-    return &m_arena->makeIdentifier(m_globalData, characters, length);
-}
-
-inline bool Lexer::lastTokenWasRestrKeyword() const
+ALWAYS_INLINE bool Lexer::lastTokenWasRestrKeyword() const
 {
     return m_lastToken == CONTINUE || m_lastToken == BREAK || m_lastToken == RETURN || m_lastToken == THROW;
 }
@@ -215,7 +343,7 @@ static NEVER_INLINE bool isNonASCIIIdentStart(int c)
 
 static inline bool isIdentStart(int c)
 {
-    return isASCII(c) ? isASCIIAlpha(c) || c == '$' || c == '_' : isNonASCIIIdentStart(c);
+    return isASCII(c) ? typesOfASCIICharacters[c] == CharacterIdentifierStart : isNonASCIIIdentStart(c);
 }
 
 static NEVER_INLINE bool isNonASCIIIdentPart(int c)
@@ -224,28 +352,37 @@ static NEVER_INLINE bool isNonASCIIIdentPart(int c)
         | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector);
 }
 
-static inline bool isIdentPart(int c)
+static ALWAYS_INLINE bool isIdentPart(int c)
 {
-    return isASCII(c) ? isASCIIAlphanumeric(c) || c == '$' || c == '_' : isNonASCIIIdentPart(c);
+    // Character types are divided into two groups depending on whether they can be part of an
+    // identifier or not. Those whose type value is less or equal than CharacterNumber can be
+    // part of an identifier. (See the CharacterType definition for more details.)
+    return isASCII(c) ? typesOfASCIICharacters[c] <= CharacterNumber : isNonASCIIIdentPart(c);
 }
 
 static inline int singleEscape(int c)
 {
     switch (c) {
-        case 'b':
-            return 0x08;
-        case 't':
-            return 0x09;
-        case 'n':
-            return 0x0A;
-        case 'v':
-            return 0x0B;
-        case 'f':
-            return 0x0C;
-        case 'r':
-            return 0x0D;
-        default:
-            return c;
+    case 'b':
+        return 0x08;
+    case 't':
+        return 0x09;
+    case 'n':
+        return 0x0A;
+    case 'v':
+        return 0x0B;
+    case 'f':
+        return 0x0C;
+    case 'r':
+        return 0x0D;
+    case '\\':
+        return '\\';
+    case '\'':
+        return '\'';
+    case '"':
+        return '"';
+    default:
+        return 0;
     }
 }
 
@@ -268,639 +405,733 @@ inline void Lexer::record16(int c)
     record16(UChar(static_cast<unsigned short>(c)));
 }
 
-int Lexer::lex(void* p1, void* p2)
+template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer::parseIdentifier(JSTokenData* tokenData, unsigned lexType)
+{
+    const ptrdiff_t remaining = m_codeEnd - m_code;
+    if ((remaining >= maxTokenLength) && !(lexType & IgnoreReservedWords)) {
+        JSTokenType keyword = parseKeyword<shouldCreateIdentifier>(tokenData);
+        if (keyword != IDENT) {
+            ASSERT((!shouldCreateIdentifier) || tokenData->ident);
+            return keyword;
+        }
+    }
+    const UChar* identifierStart = currentCharacter();
+    bool bufferRequired = false;
+
+    while (true) {
+        if (LIKELY(isIdentPart(m_current))) {
+            shift();
+            continue;
+        }
+        if (LIKELY(m_current != '\\'))
+            break;
+
+        // \uXXXX unicode characters.
+        bufferRequired = true;
+        if (identifierStart != currentCharacter())
+            m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
+        shift();
+        if (UNLIKELY(m_current != 'u'))
+            return ERRORTOK;
+        shift();
+        int character = getUnicodeCharacter();
+        if (UNLIKELY(character == -1))
+            return ERRORTOK;
+        if (UNLIKELY(m_buffer16.size() ? !isIdentPart(character) : !isIdentStart(character)))
+            return ERRORTOK;
+        if  (shouldCreateIdentifier)
+            record16(character);
+        identifierStart = currentCharacter();
+    }
+    
+    int identifierLength;
+    const Identifier* ident = 0;
+    if (shouldCreateIdentifier) {
+        if (!bufferRequired)
+            identifierLength = currentCharacter() - identifierStart;
+        else {
+            if (identifierStart != currentCharacter())
+                m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
+            identifierStart = m_buffer16.data();
+            identifierLength = m_buffer16.size();
+        }
+
+        ident = makeIdentifier(identifierStart, identifierLength);
+        tokenData->ident = ident;
+    } else
+        tokenData->ident = 0;
+
+    m_delimited = false;
+
+    if (LIKELY(!bufferRequired && !(lexType & IgnoreReservedWords))) {
+        ASSERT(shouldCreateIdentifier);
+        // Keywords must not be recognized if there was an \uXXXX in the identifier.
+        if (remaining < maxTokenLength) {
+            const HashEntry* entry = m_keywordTable.entry(m_globalData, *ident);
+            ASSERT((remaining < maxTokenLength) || !entry);
+            return entry ? static_cast<JSTokenType>(entry->lexerValue()) : IDENT;
+        }
+        return IDENT;
+    }
+
+    m_buffer16.resize(0);
+    return IDENT;
+}
+
+bool Lexer::isKeyword(const Identifier& ident)
+{
+    return m_keywordTable.entry(m_globalData, ident);
+}
+
+template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer::parseString(JSTokenData* tokenData, bool strictMode)
+{
+    int stringQuoteCharacter = m_current;
+    shift();
+
+    const UChar* stringStart = currentCharacter();
+
+    while (m_current != stringQuoteCharacter) {
+        if (UNLIKELY(m_current == '\\')) {
+            if (stringStart != currentCharacter() && shouldBuildStrings)
+                m_buffer16.append(stringStart, currentCharacter() - stringStart);
+            shift();
+
+            int escape = singleEscape(m_current);
+
+            // Most common escape sequences first
+            if (escape) {
+                 if (shouldBuildStrings)
+                     record16(escape);
+                shift();
+            } else if (UNLIKELY(isLineTerminator(m_current)))
+                shiftLineTerminator();
+            else if (m_current == 'x') {
+                shift();
+                if (isASCIIHexDigit(m_current) && isASCIIHexDigit(peek(1))) {
+                    int prev = m_current;
+                    shift();
+                    if (shouldBuildStrings)
+                        record16(convertHex(prev, m_current));
+                    shift();
+                } else if (shouldBuildStrings)
+                    record16('x');
+            } else if (m_current == 'u') {
+                shift();
+                int character = getUnicodeCharacter();
+                if (character != -1) {
+                    if (shouldBuildStrings)
+                        record16(character);
+                } else if (m_current == stringQuoteCharacter) {
+                    if (shouldBuildStrings)
+                        record16('u');
+                } else // Only stringQuoteCharacter allowed after \u
+                    return false;
+            } else if (strictMode && isASCIIDigit(m_current)) {
+                // The only valid numeric escape in strict mode is '\0', and this must not be followed by a decimal digit.
+                int character1 = m_current;
+                shift();
+                if (character1 != '0' || isASCIIDigit(m_current))
+                    return false;
+                if (shouldBuildStrings)
+                    record16(0);
+            } else if (!strictMode && isASCIIOctalDigit(m_current)) {
+                // Octal character sequences
+                int character1 = m_current;
+                shift();
+                if (isASCIIOctalDigit(m_current)) {
+                    // Two octal characters
+                    int character2 = m_current;
+                    shift();
+                    if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) {
+                        if (shouldBuildStrings)
+                            record16((character1 - '0') * 64 + (character2 - '0') * 8 + m_current - '0');
+                        shift();
+                    } else {
+                        if (shouldBuildStrings)
+                            record16((character1 - '0') * 8 + character2 - '0');
+                    }
+                } else {
+                    if (shouldBuildStrings)
+                        record16(character1 - '0');
+                }
+            } else if (m_current != -1) {
+                if (shouldBuildStrings)
+                    record16(m_current);
+                shift();
+            } else
+                return false;
+
+            stringStart = currentCharacter();
+            continue;
+        }
+        // Fast check for characters that require special handling.
+        // Catches -1, \n, \r, 0x2028, and 0x2029 as efficiently
+        // as possible, and lets through all common ASCII characters.
+        if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
+            // New-line or end of input is not allowed
+            if (UNLIKELY(isLineTerminator(m_current)) || UNLIKELY(m_current == -1))
+                return false;
+            // Anything else is just a normal character
+        }
+        shift();
+    }
+
+    if (currentCharacter() != stringStart && shouldBuildStrings)
+        m_buffer16.append(stringStart, currentCharacter() - stringStart);
+    if (shouldBuildStrings)
+        tokenData->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
+    else
+        tokenData->ident = 0;
+
+    m_buffer16.resize(0);
+    return true;
+}
+
+ALWAYS_INLINE void Lexer::parseHex(double& returnValue)
+{
+    // Optimization: most hexadecimal values fit into 4 bytes.
+    uint32_t hexValue = 0;
+    int maximumDigits = 7;
+
+    // Shift out the 'x' prefix.
+    shift();
+
+    do {
+        hexValue = (hexValue << 4) + toASCIIHexValue(m_current);
+        shift();
+        --maximumDigits;
+    } while (isASCIIHexDigit(m_current) && maximumDigits >= 0);
+
+    if (maximumDigits >= 0) {
+        returnValue = hexValue;
+        return;
+    }
+
+    // No more place in the hexValue buffer.
+    // The values are shifted out and placed into the m_buffer8 vector.
+    for (int i = 0; i < 8; ++i) {
+         int digit = hexValue >> 28;
+         if (digit < 10)
+             record8(digit + '0');
+         else
+             record8(digit - 10 + 'a');
+         hexValue <<= 4;
+    }
+
+    while (isASCIIHexDigit(m_current)) {
+        record8(m_current);
+        shift();
+    }
+
+    returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 16);
+}
+
+ALWAYS_INLINE bool Lexer::parseOctal(double& returnValue)
+{
+    // Optimization: most octal values fit into 4 bytes.
+    uint32_t octalValue = 0;
+    int maximumDigits = 9;
+    // Temporary buffer for the digits. Makes easier
+    // to reconstruct the input characters when needed.
+    char digits[10];
+
+    do {
+        octalValue = octalValue * 8 + (m_current - '0');
+        digits[maximumDigits] = m_current;
+        shift();
+        --maximumDigits;
+    } while (isASCIIOctalDigit(m_current) && maximumDigits >= 0);
+
+    if (!isASCIIDigit(m_current) && maximumDigits >= 0) {
+        returnValue = octalValue;
+        return true;
+    }
+
+    for (int i = 9; i > maximumDigits; --i)
+         record8(digits[i]);
+
+    while (isASCIIOctalDigit(m_current)) {
+        record8(m_current);
+        shift();
+    }
+
+    if (isASCIIDigit(m_current))
+        return false;
+
+    returnValue = parseIntOverflow(m_buffer8.data(), m_buffer8.size(), 8);
+    return true;
+}
+
+ALWAYS_INLINE bool Lexer::parseDecimal(double& returnValue)
+{
+    // Optimization: most decimal values fit into 4 bytes.
+    uint32_t decimalValue = 0;
+
+    // Since parseOctal may be executed before parseDecimal,
+    // the m_buffer8 may hold ascii digits.
+    if (!m_buffer8.size()) {
+        int maximumDigits = 9;
+        // Temporary buffer for the digits. Makes easier
+        // to reconstruct the input characters when needed.
+        char digits[10];
+
+        do {
+            decimalValue = decimalValue * 10 + (m_current - '0');
+            digits[maximumDigits] = m_current;
+            shift();
+            --maximumDigits;
+        } while (isASCIIDigit(m_current) && maximumDigits >= 0);
+
+        if (maximumDigits >= 0 && m_current != '.' && (m_current | 0x20) != 'e') {
+            returnValue = decimalValue;
+            return true;
+        }
+
+        for (int i = 9; i > maximumDigits; --i)
+            record8(digits[i]);
+    }
+
+    while (isASCIIDigit(m_current)) {
+        record8(m_current);
+        shift();
+    }
+
+    return false;
+}
+
+ALWAYS_INLINE void Lexer::parseNumberAfterDecimalPoint()
+{
+    record8('.');
+    while (isASCIIDigit(m_current)) {
+        record8(m_current);
+        shift();
+    }
+}
+
+ALWAYS_INLINE bool Lexer::parseNumberAfterExponentIndicator()
+{
+    record8('e');
+    shift();
+    if (m_current == '+' || m_current == '-') {
+        record8(m_current);
+        shift();
+    }
+
+    if (!isASCIIDigit(m_current))
+        return false;
+
+    do {
+        record8(m_current);
+        shift();
+    } while (isASCIIDigit(m_current));
+    return true;
+}
+
+ALWAYS_INLINE bool Lexer::parseMultilineComment()
+{
+    while (true) {
+        while (UNLIKELY(m_current == '*')) {
+            shift();
+            if (m_current == '/') {
+                shift();
+                return true;
+            }
+        }
+
+        if (UNLIKELY(m_current == -1))
+            return false;
+
+        if (isLineTerminator(m_current))
+            shiftLineTerminator();
+        else
+            shift();
+    }
+}
+
+bool Lexer::nextTokenIsColon()
+{
+    const UChar* code = m_code;
+    while (code < m_codeEnd && (isWhiteSpace(*code) || isLineTerminator(*code)))
+        code++;
+        
+    return code < m_codeEnd && *code == ':';
+}
+
+JSTokenType Lexer::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexType, bool strictMode)
 {
     ASSERT(!m_error);
     ASSERT(m_buffer8.isEmpty());
     ASSERT(m_buffer16.isEmpty());
 
-    YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1);
-    YYLTYPE* llocp = static_cast<YYLTYPE*>(p2);
-    int token = 0;
+    JSTokenType token = ERRORTOK;
     m_terminator = false;
 
 start:
     while (isWhiteSpace(m_current))
-        shift1();
+        shift();
 
     int startOffset = currentOffset();
 
-    if (m_current == -1) {
-        if (!m_terminator && !m_delimited && !m_isReparsing) {
-            // automatic semicolon insertion if program incomplete
-            token = ';';
-            goto doneSemicolon;
-        }
-        return 0;
-    }
+    if (UNLIKELY(m_current == -1))
+        return EOFTOK;
 
     m_delimited = false;
-    switch (m_current) {
-        case '>':
-            if (m_next1 == '>' && m_next2 == '>') {
-                if (m_next3 == '=') {
-                    shift4();
+
+    CharacterType type;
+    if (LIKELY(isASCII(m_current)))
+        type = static_cast<CharacterType>(typesOfASCIICharacters[m_current]);
+    else if (isNonASCIIIdentStart(m_current))
+        type = CharacterIdentifierStart;
+    else if (isLineTerminator(m_current))
+        type = CharacterLineTerminator;
+    else
+        type = CharacterInvalid;
+
+    switch (type) {
+    case CharacterGreater:
+        shift();
+        if (m_current == '>') {
+            shift();
+            if (m_current == '>') {
+                shift();
+                if (m_current == '=') {
+                    shift();
                     token = URSHIFTEQUAL;
                     break;
                 }
-                shift3();
                 token = URSHIFT;
                 break;
             }
-            if (m_next1 == '>') {
-                if (m_next2 == '=') {
-                    shift3();
-                    token = RSHIFTEQUAL;
-                    break;
-                }
-                shift2();
-                token = RSHIFT;
-                break;
-            }
-            if (m_next1 == '=') {
-                shift2();
-                token = GE;
+            if (m_current == '=') {
+                shift();
+                token = RSHIFTEQUAL;
                 break;
             }
-            shift1();
-            token = '>';
+            token = RSHIFT;
             break;
-        case '=':
-            if (m_next1 == '=') {
-                if (m_next2 == '=') {
-                    shift3();
-                    token = STREQ;
-                    break;
-                }
-                shift2();
-                token = EQEQ;
-                break;
-            }
-            shift1();
-            token = '=';
+        }
+        if (m_current == '=') {
+            shift();
+            token = GE;
             break;
-        case '!':
-            if (m_next1 == '=') {
-                if (m_next2 == '=') {
-                    shift3();
-                    token = STRNEQ;
-                    break;
-                }
-                shift2();
-                token = NE;
+        }
+        token = GT;
+        break;
+    case CharacterEqual:
+        shift();
+        if (m_current == '=') {
+            shift();
+            if (m_current == '=') {
+                shift();
+                token = STREQ;
                 break;
             }
-            shift1();
-            token = '!';
+            token = EQEQ;
             break;
-        case '<':
-            if (m_next1 == '!' && m_next2 == '-' && m_next3 == '-') {
-                // <!-- marks the beginning of a line comment (for www usage)
-                shift4();
-                goto inSingleLineComment;
-            }
-            if (m_next1 == '<') {
-                if (m_next2 == '=') {
-                    shift3();
-                    token = LSHIFTEQUAL;
-                    break;
-                }
-                shift2();
-                token = LSHIFT;
-                break;
-            }
-            if (m_next1 == '=') {
-                shift2();
-                token = LE;
+        }
+        token = EQUAL;
+        break;
+    case CharacterLess:
+        shift();
+        if (m_current == '!' && peek(1) == '-' && peek(2) == '-') {
+            // <!-- marks the beginning of a line comment (for www usage)
+            goto inSingleLineComment;
+        }
+        if (m_current == '<') {
+            shift();
+            if (m_current == '=') {
+                shift();
+                token = LSHIFTEQUAL;
                 break;
             }
-            shift1();
-            token = '<';
+            token = LSHIFT;
             break;
-        case '+':
-            if (m_next1 == '+') {
-                shift2();
-                if (m_terminator) {
-                    token = AUTOPLUSPLUS;
-                    break;
-                }
-                token = PLUSPLUS;
-                break;
-            }
-            if (m_next1 == '=') {
-                shift2();
-                token = PLUSEQUAL;
-                break;
-            }
-            shift1();
-            token = '+';
+        }
+        if (m_current == '=') {
+            shift();
+            token = LE;
             break;
-        case '-':
-            if (m_next1 == '-') {
-                if (m_atLineStart && m_next2 == '>') {
-                    shift3();
-                    goto inSingleLineComment;
-                }
-                shift2();
-                if (m_terminator) {
-                    token = AUTOMINUSMINUS;
-                    break;
-                }
-                token = MINUSMINUS;
-                break;
-            }
-            if (m_next1 == '=') {
-                shift2();
-                token = MINUSEQUAL;
+        }
+        token = LT;
+        break;
+    case CharacterExclamationMark:
+        shift();
+        if (m_current == '=') {
+            shift();
+            if (m_current == '=') {
+                shift();
+                token = STRNEQ;
                 break;
             }
-            shift1();
-            token = '-';
+            token = NE;
             break;
-        case '*':
-            if (m_next1 == '=') {
-                shift2();
-                token = MULTEQUAL;
-                break;
-            }
-            shift1();
-            token = '*';
+        }
+        token = EXCLAMATION;
+        break;
+    case CharacterAdd:
+        shift();
+        if (m_current == '+') {
+            shift();
+            token = (!m_terminator) ? PLUSPLUS : AUTOPLUSPLUS;
+            break;
+        }
+        if (m_current == '=') {
+            shift();
+            token = PLUSEQUAL;
             break;
-        case '/':
-            if (m_next1 == '/') {
-                shift2();
+        }
+        token = PLUS;
+        break;
+    case CharacterSub:
+        shift();
+        if (m_current == '-') {
+            shift();
+            if (m_atLineStart && m_current == '>') {
+                shift();
                 goto inSingleLineComment;
             }
-            if (m_next1 == '*')
-                goto inMultiLineComment;
-            if (m_next1 == '=') {
-                shift2();
-                token = DIVEQUAL;
-                break;
-            }
-            shift1();
-            token = '/';
+            token = (!m_terminator) ? MINUSMINUS : AUTOMINUSMINUS;
             break;
-        case '&':
-            if (m_next1 == '&') {
-                shift2();
-                token = AND;
-                break;
-            }
-            if (m_next1 == '=') {
-                shift2();
-                token = ANDEQUAL;
-                break;
-            }
-            shift1();
-            token = '&';
+        }
+        if (m_current == '=') {
+            shift();
+            token = MINUSEQUAL;
             break;
-        case '^':
-            if (m_next1 == '=') {
-                shift2();
-                token = XOREQUAL;
-                break;
-            }
-            shift1();
-            token = '^';
+        }
+        token = MINUS;
+        break;
+    case CharacterMultiply:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = MULTEQUAL;
             break;
-        case '%':
-            if (m_next1 == '=') {
-                shift2();
-                token = MODEQUAL;
-                break;
-            }
-            shift1();
-            token = '%';
+        }
+        token = TIMES;
+        break;
+    case CharacterSlash:
+        shift();
+        if (m_current == '/') {
+            shift();
+            goto inSingleLineComment;
+        }
+        if (m_current == '*') {
+            shift();
+            if (parseMultilineComment())
+                goto start;
+            goto returnError;
+        }
+        if (m_current == '=') {
+            shift();
+            token = DIVEQUAL;
             break;
-        case '|':
-            if (m_next1 == '=') {
-                shift2();
-                token = OREQUAL;
-                break;
-            }
-            if (m_next1 == '|') {
-                shift2();
-                token = OR;
-                break;
-            }
-            shift1();
-            token = '|';
+        }
+        token = DIVIDE;
+        break;
+    case CharacterAnd:
+        shift();
+        if (m_current == '&') {
+            shift();
+            token = AND;
             break;
-        case '.':
-            if (isASCIIDigit(m_next1)) {
-                record8('.');
-                shift1();
-                goto inNumberAfterDecimalPoint;
-            }
-            token = '.';
-            shift1();
+        }
+        if (m_current == '=') {
+            shift();
+            token = ANDEQUAL;
             break;
-        case ',':
-        case '~':
-        case '?':
-        case ':':
-        case '(':
-        case ')':
-        case '[':
-        case ']':
-            token = m_current;
-            shift1();
+        }
+        token = BITAND;
+        break;
+    case CharacterXor:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = XOREQUAL;
             break;
-        case ';':
-            shift1();
-            m_delimited = true;
-            token = ';';
+        }
+        token = BITXOR;
+        break;
+    case CharacterModulo:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = MODEQUAL;
             break;
-        case '{':
-            lvalp->intValue = currentOffset();
-            shift1();
-            token = OPENBRACE;
+        }
+        token = MOD;
+        break;
+    case CharacterOr:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = OREQUAL;
             break;
-        case '}':
-            lvalp->intValue = currentOffset();
-            shift1();
-            m_delimited = true;
-            token = CLOSEBRACE;
+        }
+        if (m_current == '|') {
+            shift();
+            token = OR;
             break;
-        case '\\':
-            goto startIdentifierWithBackslash;
-        case '0':
-            goto startNumberWithZeroDigit;
-        case '1':
-        case '2':
-        case '3':
-        case '4':
-        case '5':
-        case '6':
-        case '7':
-        case '8':
-        case '9':
-            goto startNumber;
-        case '"':
-        case '\'':
-            goto startString;
-        default:
-            if (isIdentStart(m_current))
-                goto startIdentifierOrKeyword;
-            if (isLineTerminator(m_current)) {
-                shiftLineTerminator();
-                m_atLineStart = true;
-                m_terminator = true;
-                if (lastTokenWasRestrKeyword()) {
-                    token = ';';
-                    goto doneSemicolon;
+        }
+        token = BITOR;
+        break;
+    case CharacterOpenParen:
+        token = OPENPAREN;
+        shift();
+        break;
+    case CharacterCloseParen:
+        token = CLOSEPAREN;
+        shift();
+        break;
+    case CharacterOpenBracket:
+        token = OPENBRACKET;
+        shift();
+        break;
+    case CharacterCloseBracket:
+        token = CLOSEBRACKET;
+        shift();
+        break;
+    case CharacterComma:
+        token = COMMA;
+        shift();
+        break;
+    case CharacterColon:
+        token = COLON;
+        shift();
+        break;
+    case CharacterQuestion:
+        token = QUESTION;
+        shift();
+        break;
+    case CharacterTilde:
+        token = TILDE;
+        shift();
+        break;
+    case CharacterSemicolon:
+        m_delimited = true;
+        shift();
+        token = SEMICOLON;
+        break;
+    case CharacterOpenBrace:
+        tokenData->intValue = currentOffset();
+        shift();
+        token = OPENBRACE;
+        break;
+    case CharacterCloseBrace:
+        tokenData->intValue = currentOffset();
+        m_delimited = true;
+        shift();
+        token = CLOSEBRACE;
+        break;
+    case CharacterDot:
+        shift();
+        if (!isASCIIDigit(m_current)) {
+            token = DOT;
+            break;
+        }
+        goto inNumberAfterDecimalPoint;
+    case CharacterZero:
+        shift();
+        if ((m_current | 0x20) == 'x' && isASCIIHexDigit(peek(1))) {
+            parseHex(tokenData->doubleValue);
+            token = NUMBER;
+        } else {
+            record8('0');
+            if (isASCIIOctalDigit(m_current)) {
+                if (parseOctal(tokenData->doubleValue)) {
+                    if (strictMode)
+                        goto returnError;
+                    token = NUMBER;
                 }
-                goto start;
             }
-            goto returnError;
-    }
-
-    m_atLineStart = false;
-    goto returnToken;
-
-startString: {
-    int stringQuoteCharacter = m_current;
-    shift1();
-
-    const UChar* stringStart = currentCharacter();
-    while (m_current != stringQuoteCharacter) {
-        // Fast check for characters that require special handling.
-        // Catches -1, \n, \r, \, 0x2028, and 0x2029 as efficiently
-        // as possible, and lets through all common ASCII characters.
-        if (UNLIKELY(m_current == '\\') || UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) {
-            m_buffer16.append(stringStart, currentCharacter() - stringStart);
-            goto inString;
         }
-        shift1();
-    }
-    lvalp->ident = makeIdentifier(stringStart, currentCharacter() - stringStart);
-    shift1();
-    m_atLineStart = false;
-    m_delimited = false;
-    token = STRING;
-    goto returnToken;
+        // Fall through into CharacterNumber
+    case CharacterNumber:
+        if (LIKELY(token != NUMBER)) {
+            if (!parseDecimal(tokenData->doubleValue)) {
+                if (m_current == '.') {
+                    shift();
+inNumberAfterDecimalPoint:
+                    parseNumberAfterDecimalPoint();
+                }
+                if ((m_current | 0x20) == 'e')
+                    if (!parseNumberAfterExponentIndicator())
+                        goto returnError;
+                // Null-terminate string for strtod.
+                m_buffer8.append('\0');
+                tokenData->doubleValue = WTF::strtod(m_buffer8.data(), 0);
+            }
+            token = NUMBER;
+        }
 
-inString:
-    while (m_current != stringQuoteCharacter) {
-        if (m_current == '\\')
-            goto inStringEscapeSequence;
-        if (UNLIKELY(isLineTerminator(m_current)))
-            goto returnError;
-        if (UNLIKELY(m_current == -1))
+        // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
+        if (UNLIKELY(isIdentStart(m_current)))
             goto returnError;
-        record16(m_current);
-        shift1();
-    }
-    goto doneString;
-
-inStringEscapeSequence:
-    shift1();
-    if (m_current == 'x') {
-        shift1();
-        if (isASCIIHexDigit(m_current) && isASCIIHexDigit(m_next1)) {
-            record16(convertHex(m_current, m_next1));
-            shift2();
-            goto inString;
-        }
-        record16('x');
-        if (m_current == stringQuoteCharacter)
-            goto doneString;
-        goto inString;
-    }
-    if (m_current == 'u') {
-        shift1();
-        if (isASCIIHexDigit(m_current) && isASCIIHexDigit(m_next1) && isASCIIHexDigit(m_next2) && isASCIIHexDigit(m_next3)) {
-            record16(convertUnicode(m_current, m_next1, m_next2, m_next3));
-            shift4();
-            goto inString;
-        }
-        if (m_current == stringQuoteCharacter) {
-            record16('u');
-            goto doneString;
-        }
-        goto returnError;
-    }
-    if (isASCIIOctalDigit(m_current)) {
-        if (m_current >= '0' && m_current <= '3' && isASCIIOctalDigit(m_next1) && isASCIIOctalDigit(m_next2)) {
-            record16((m_current - '0') * 64 + (m_next1 - '0') * 8 + m_next2 - '0');
-            shift3();
-            goto inString;
-        }
-        if (isASCIIOctalDigit(m_next1)) {
-            record16((m_current - '0') * 8 + m_next1 - '0');
-            shift2();
-            goto inString;
+        m_buffer8.resize(0);
+        m_delimited = false;
+        break;
+    case CharacterQuote:
+        if (lexType & DontBuildStrings) {
+            if (UNLIKELY(!parseString<false>(tokenData, strictMode)))
+                goto returnError;
+        } else {
+            if (UNLIKELY(!parseString<true>(tokenData, strictMode)))
+                goto returnError;
         }
-        record16(m_current - '0');
-        shift1();
-        goto inString;
-    }
-    if (isLineTerminator(m_current)) {
+        shift();
+        m_delimited = false;
+        token = STRING;
+        break;
+    case CharacterIdentifierStart:
+        ASSERT(isIdentStart(m_current));
+        // Fall through into CharacterBackSlash.
+    case CharacterBackSlash:
+        if (lexType & DontBuildKeywords)
+            token = parseIdentifier<false>(tokenData, lexType);
+        else
+            token = parseIdentifier<true>(tokenData, lexType);
+        break;
+    case CharacterLineTerminator:
+        ASSERT(isLineTerminator(m_current));
         shiftLineTerminator();
-        goto inString;
-    }
-    if (m_current == -1)
-        goto returnError;
-    record16(singleEscape(m_current));
-    shift1();
-    goto inString;
-}
-
-startIdentifierWithBackslash:
-    shift1();
-    if (UNLIKELY(m_current != 'u'))
-        goto returnError;
-    shift1();
-    if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(m_next1) || !isASCIIHexDigit(m_next2) || !isASCIIHexDigit(m_next3)))
+        m_atLineStart = true;
+        m_terminator = true;
+        goto start;
+    case CharacterInvalid:
         goto returnError;
-    token = convertUnicode(m_current, m_next1, m_next2, m_next3);
-    if (UNLIKELY(!isIdentStart(token)))
+    default:
+        ASSERT_NOT_REACHED();
         goto returnError;
-    goto inIdentifierAfterCharacterCheck;
-
-startIdentifierOrKeyword: {
-    const UChar* identifierStart = currentCharacter();
-    shift1();
-    while (isIdentPart(m_current))
-        shift1();
-    if (LIKELY(m_current != '\\')) {
-        lvalp->ident = makeIdentifier(identifierStart, currentCharacter() - identifierStart);
-        goto doneIdentifierOrKeyword;
     }
-    m_buffer16.append(identifierStart, currentCharacter() - identifierStart);
-}
 
-    do {
-        shift1();
-        if (UNLIKELY(m_current != 'u'))
-            goto returnError;
-        shift1();
-        if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(m_next1) || !isASCIIHexDigit(m_next2) || !isASCIIHexDigit(m_next3)))
-            goto returnError;
-        token = convertUnicode(m_current, m_next1, m_next2, m_next3);
-        if (UNLIKELY(!isIdentPart(token)))
-            goto returnError;
-inIdentifierAfterCharacterCheck:
-        record16(token);
-        shift4();
-
-        while (isIdentPart(m_current)) {
-            record16(m_current);
-            shift1();
-        }
-    } while (UNLIKELY(m_current == '\\'));
-    goto doneIdentifier;
+    m_atLineStart = false;
+    goto returnToken;
 
 inSingleLineComment:
     while (!isLineTerminator(m_current)) {
         if (UNLIKELY(m_current == -1))
-            return 0;
-        shift1();
+            return EOFTOK;
+        shift();
     }
     shiftLineTerminator();
     m_atLineStart = true;
     m_terminator = true;
-    if (lastTokenWasRestrKeyword())
-        goto doneSemicolon;
-    goto start;
-
-inMultiLineComment:
-    shift2();
-    while (m_current != '*' || m_next1 != '/') {
-        if (isLineTerminator(m_current))
-            shiftLineTerminator();
-        else {
-            shift1();
-            if (UNLIKELY(m_current == -1))
-                goto returnError;
-        }
-    }
-    shift2();
-    m_atLineStart = false;
-    goto start;
-
-startNumberWithZeroDigit:
-    shift1();
-    if ((m_current | 0x20) == 'x' && isASCIIHexDigit(m_next1)) {
-        shift1();
-        goto inHex;
-    }
-    if (m_current == '.') {
-        record8('0');
-        record8('.');
-        shift1();
-        goto inNumberAfterDecimalPoint;
-    }
-    if ((m_current | 0x20) == 'e') {
-        record8('0');
-        record8('e');
-        shift1();
-        goto inExponentIndicator;
-    }
-    if (isASCIIOctalDigit(m_current))
-        goto inOctal;
-    if (isASCIIDigit(m_current))
-        goto startNumber;
-    lvalp->doubleValue = 0;
-    goto doneNumeric;
-
-inNumberAfterDecimalPoint:
-    while (isASCIIDigit(m_current)) {
-        record8(m_current);
-        shift1();
-    }
-    if ((m_current | 0x20) == 'e') {
-        record8('e');
-        shift1();
-        goto inExponentIndicator;
-    }
-    goto doneNumber;
-
-inExponentIndicator:
-    if (m_current == '+' || m_current == '-') {
-        record8(m_current);
-        shift1();
-    }
-    if (!isASCIIDigit(m_current))
-        goto returnError;
-    do {
-        record8(m_current);
-        shift1();
-    } while (isASCIIDigit(m_current));
-    goto doneNumber;
+    if (!lastTokenWasRestrKeyword())
+        goto start;
 
-inOctal: {
-    do {
-        record8(m_current);
-        shift1();
-    } while (isASCIIOctalDigit(m_current));
-    if (isASCIIDigit(m_current))
-        goto startNumber;
-
-    double dval = 0;
-
-    const char* end = m_buffer8.end();
-    for (const char* p = m_buffer8.data(); p < end; ++p) {
-        dval *= 8;
-        dval += *p - '0';
-    }
-    if (dval >= mantissaOverflowLowerBound)
-        dval = parseIntOverflow(m_buffer8.data(), end - m_buffer8.data(), 8);
-
-    m_buffer8.resize(0);
-
-    lvalp->doubleValue = dval;
-    goto doneNumeric;
-}
-
-inHex: {
-    do {
-        record8(m_current);
-        shift1();
-    } while (isASCIIHexDigit(m_current));
-
-    double dval = 0;
-
-    const char* end = m_buffer8.end();
-    for (const char* p = m_buffer8.data(); p < end; ++p) {
-        dval *= 16;
-        dval += toASCIIHexValue(*p);
-    }
-    if (dval >= mantissaOverflowLowerBound)
-        dval = parseIntOverflow(m_buffer8.data(), end - m_buffer8.data(), 16);
-
-    m_buffer8.resize(0);
-
-    lvalp->doubleValue = dval;
-    goto doneNumeric;
-}
-
-startNumber:
-    record8(m_current);
-    shift1();
-    while (isASCIIDigit(m_current)) {
-        record8(m_current);
-        shift1();
-    }
-    if (m_current == '.') {
-        record8('.');
-        shift1();
-        goto inNumberAfterDecimalPoint;
-    }
-    if ((m_current | 0x20) == 'e') {
-        record8('e');
-        shift1();
-        goto inExponentIndicator;
-    }
-
-    // Fall through into doneNumber.
-
-doneNumber:
-    // Null-terminate string for strtod.
-    m_buffer8.append('\0');
-    lvalp->doubleValue = WTF::strtod(m_buffer8.data(), 0);
-    m_buffer8.resize(0);
-
-    // Fall through into doneNumeric.
-
-doneNumeric:
-    // No identifiers allowed directly after numeric literal, e.g. "3in" is bad.
-    if (UNLIKELY(isIdentStart(m_current)))
-        goto returnError;
-
-    m_atLineStart = false;
-    m_delimited = false;
-    token = NUMBER;
-    goto returnToken;
-
-doneSemicolon:
-    token = ';';
+    token = SEMICOLON;
     m_delimited = true;
-    goto returnToken;
-
-doneIdentifier:
-    m_atLineStart = false;
-    m_delimited = false;
-    lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
-    m_buffer16.resize(0);
-    token = IDENT;
-    goto returnToken;
-
-doneIdentifierOrKeyword: {
-    m_atLineStart = false;
-    m_delimited = false;
-    m_buffer16.resize(0);
-    const HashEntry* entry = m_keywordTable.entry(m_globalData, *lvalp->ident);
-    token = entry ? entry->lexerValue() : IDENT;
-    goto returnToken;
-}
-
-doneString:
-    // Atomize constant strings in case they're later used in property lookup.
-    shift1();
-    m_atLineStart = false;
-    m_delimited = false;
-    lvalp->ident = makeIdentifier(m_buffer16.data(), m_buffer16.size());
-    m_buffer16.resize(0);
-    token = STRING;
-
     // Fall through into returnToken.
 
-returnToken: {
-    int lineNumber = m_lineNumber;
-    llocp->first_line = lineNumber;
-    llocp->last_line = lineNumber;
-    llocp->first_column = startOffset;
-    llocp->last_column = currentOffset();
-
+returnToken:
+    tokenInfo->line = m_lineNumber;
+    tokenInfo->startOffset = startOffset;
+    tokenInfo->endOffset = currentOffset();
     m_lastToken = token;
     return token;
-}
 
 returnError:
     m_error = true;
-    return -1;
+    return ERRORTOK;
 }
 
 bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
@@ -925,7 +1156,7 @@ bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UCh
             return false;
         }
 
-        shift1();
+        shift();
 
         if (current == '/' && !lastWasEscape && !inBrackets)
             break;
@@ -955,7 +1186,7 @@ bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UCh
 
     while (isIdentPart(m_current)) {
         record16(m_current);
-        shift1();
+        shift();
     }
 
     flags = makeIdentifier(m_buffer16.data(), m_buffer16.size());
@@ -975,7 +1206,7 @@ bool Lexer::skipRegExp()
         if (isLineTerminator(current) || current == -1)
             return false;
 
-        shift1();
+        shift();
 
         if (current == '/' && !lastWasEscape && !inBrackets)
             break;
@@ -999,7 +1230,7 @@ bool Lexer::skipRegExp()
     }
 
     while (isIdentPart(m_current))
-        shift1();
+        shift();
 
     return true;
 }
@@ -1007,7 +1238,6 @@ bool Lexer::skipRegExp()
 void Lexer::clear()
 {
     m_arena = 0;
-    m_codeWithoutBOMs.clear();
 
     Vector<char> newBuffer8;
     m_buffer8.swap(newBuffer8);
@@ -1020,26 +1250,8 @@ void Lexer::clear()
 
 SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
 {
-    if (m_codeWithoutBOMs.isEmpty())
-        return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine);
-
-    const UChar* data = m_source->provider()->data();
-    
-    ASSERT(openBrace < closeBrace);
-    int i;
-    for (i = m_source->startOffset(); i < openBrace; ++i) {
-        if (data[i] == byteOrderMark) {
-            openBrace++;
-            closeBrace++;
-        }
-    }
-    for (; i < closeBrace; ++i) {
-        if (data[i] == byteOrderMark)
-            closeBrace++;
-    }
-
-    ASSERT(openBrace < closeBrace);
-
+    ASSERT(m_source->provider()->data()[openBrace] == '{');
+    ASSERT(m_source->provider()->data()[closeBrace] == '}');
     return SourceCode(m_source->provider(), openBrace, closeBrace + 1, firstLine);
 }
 
index c76696cf3b3fa4e6872e70af753c185a5e21db1f..46501aa882be672ffe34b680ec4cd19fb25973ed 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu)
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #ifndef Lexer_h
 #define Lexer_h
 
+#include "JSParser.h"
 #include "Lookup.h"
 #include "ParserArena.h"
 #include "SourceCode.h"
 #include <wtf/ASCIICType.h>
+#include <wtf/AlwaysInline.h>
 #include <wtf/SegmentedVector.h>
 #include <wtf/Vector.h>
 #include <wtf/unicode/Unicode.h>
@@ -34,7 +37,8 @@ namespace JSC {
 
     class RegExp;
 
-    class Lexer : public Noncopyable {
+    class Lexer {
+        WTF_MAKE_NONCOPYABLE(Lexer); WTF_MAKE_FAST_ALLOCATED;
     public:
         // Character manipulation functions.
         static bool isWhiteSpace(int character);
@@ -45,10 +49,19 @@ namespace JSC {
         // Functions to set up parsing.
         void setCode(const SourceCode&, ParserArena&);
         void setIsReparsing() { m_isReparsing = true; }
+        bool isReparsing() const { return m_isReparsing; }
 
         // Functions for the parser itself.
-        int lex(void* lvalp, void* llocp);
+        enum LexType {
+            IgnoreReservedWords = 1, 
+            DontBuildStrings = 2,
+            DontBuildKeywords = 4
+        };
+        JSTokenType lex(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode);
+        bool nextTokenIsColon();
         int lineNumber() const { return m_lineNumber; }
+        void setLastLineNumber(int lastLineNumber) { m_lastLineNumber = lastLineNumber; }
+        int lastLineNumber() const { return m_lastLineNumber; }
         bool prevTerminator() const { return m_terminator; }
         SourceCode sourceCode(int openBrace, int closeBrace, int firstLine);
         bool scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix = 0);
@@ -57,6 +70,28 @@ namespace JSC {
         // Functions for use after parsing.
         bool sawError() const { return m_error; }
         void clear();
+        int currentOffset() { return m_code - m_codeStart; }
+        void setOffset(int offset)
+        {
+            m_error = 0;
+            m_code = m_codeStart + offset;
+            m_buffer8.resize(0);
+            m_buffer16.resize(0);
+            // Faster than an if-else sequence
+            m_current = -1;
+            if (LIKELY(m_code < m_codeEnd))
+                m_current = *m_code;
+        }
+        void setLineNumber(int line)
+        {
+            m_lineNumber = line;
+        }
+
+        SourceProvider* sourceProvider() const { return m_source->provider(); }
+        
+        JSTokenType lexExpectIdentifier(JSTokenData*, JSTokenInfo*, unsigned, bool strictMode);
+
+        bool isKeyword(const Identifier&);
 
     private:
         friend class JSGlobalData;
@@ -64,28 +99,40 @@ namespace JSC {
         Lexer(JSGlobalData*);
         ~Lexer();
 
-        void shift1();
-        void shift2();
-        void shift3();
-        void shift4();
-        void shiftLineTerminator();
-
         void record8(int);
         void record16(int);
         void record16(UChar);
 
         void copyCodeWithoutBOMs();
 
-        int currentOffset() const;
-        const UChar* currentCharacter() const;
+        ALWAYS_INLINE void shift();
+        ALWAYS_INLINE int peek(int offset);
+        int getUnicodeCharacter();
+        void shiftLineTerminator();
+
+        ALWAYS_INLINE const UChar* currentCharacter() const;
+        ALWAYS_INLINE int currentOffset() const;
+
+        ALWAYS_INLINE const Identifier* makeIdentifier(const UChar* characters, size_t length);
 
-        const Identifier* makeIdentifier(const UChar* characters, size_t length);
+        ALWAYS_INLINE bool lastTokenWasRestrKeyword() const;
 
-        bool lastTokenWasRestrKeyword() const;
+        enum ShiftType { DoBoundsCheck, DoNotBoundsCheck };
+        template <int shiftAmount, ShiftType shouldBoundsCheck> void internalShift();
+        template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType parseKeyword(JSTokenData*);
+        template <bool shouldBuildIdentifiers> ALWAYS_INLINE JSTokenType parseIdentifier(JSTokenData*, unsigned);
+        template <bool shouldBuildStrings> ALWAYS_INLINE bool parseString(JSTokenData*, bool strictMode);
+        ALWAYS_INLINE void parseHex(double& returnValue);
+        ALWAYS_INLINE bool parseOctal(double& returnValue);
+        ALWAYS_INLINE bool parseDecimal(double& returnValue);
+        ALWAYS_INLINE void parseNumberAfterDecimalPoint();
+        ALWAYS_INLINE bool parseNumberAfterExponentIndicator();
+        ALWAYS_INLINE bool parseMultilineComment();
 
         static const size_t initialReadBufferCapacity = 32;
 
         int m_lineNumber;
+        int m_lastLineNumber;
 
         Vector<char> m_buffer8;
         Vector<UChar> m_buffer16;
@@ -103,25 +150,20 @@ namespace JSC {
 
         // current and following unicode characters (int to allow for -1 for end-of-file marker)
         int m_current;
-        int m_next1;
-        int m_next2;
-        int m_next3;
-        
+
         IdentifierArena* m_arena;
 
         JSGlobalData* m_globalData;
 
         const HashTable m_keywordTable;
-
-        Vector<UChar> m_codeWithoutBOMs;
     };
 
-    inline bool Lexer::isWhiteSpace(int ch)
+    ALWAYS_INLINE bool Lexer::isWhiteSpace(int ch)
     {
-        return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : WTF::Unicode::isSeparatorSpace(ch);
+        return isASCII(ch) ? (ch == ' ' || ch == '\t' || ch == 0xB || ch == 0xC) : (WTF::Unicode::isSeparatorSpace(ch) || ch == 0xFEFF);
     }
 
-    inline bool Lexer::isLineTerminator(int ch)
+    ALWAYS_INLINE bool Lexer::isLineTerminator(int ch)
     {
         return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028;
     }
@@ -135,11 +177,54 @@ namespace JSC {
     {
         return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
     }
+    
+    ALWAYS_INLINE const Identifier* Lexer::makeIdentifier(const UChar* characters, size_t length)
+    {
+        return &m_arena->makeIdentifier(m_globalData, characters, length);
+    }
 
-    // A bridge for yacc from the C world to the C++ world.
-    inline int jscyylex(void* lvalp, void* llocp, void* globalData)
+    ALWAYS_INLINE JSTokenType Lexer::lexExpectIdentifier(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsigned lexType, bool strictMode)
     {
-        return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp);
+        ASSERT((lexType & IgnoreReservedWords));
+        const UChar* start = m_code;
+        const UChar* ptr = start;
+        const UChar* end = m_codeEnd;
+        if (ptr >= end) {
+            ASSERT(ptr == end);
+            goto slowCase;
+        }
+        if (!WTF::isASCIIAlpha(*ptr))
+            goto slowCase;
+        ++ptr;
+        while (ptr < end) {
+            if (!WTF::isASCIIAlphanumeric(*ptr))
+                break;
+            ++ptr;
+        }
+
+        // Here's the shift
+        if (ptr < end) {
+            if ((!WTF::isASCII(*ptr)) || (*ptr == '\\') || (*ptr == '_') || (*ptr == '$'))
+                goto slowCase;
+            m_current = *ptr;
+        } else
+            m_current = -1;
+
+        m_code = ptr;
+
+        // Create the identifier if needed
+        if (lexType & DontBuildKeywords)
+            tokenData->ident = 0;
+        else
+            tokenData->ident = makeIdentifier(start, ptr - start);
+        tokenInfo->line = m_lineNumber;
+        tokenInfo->startOffset = start - m_codeStart;
+        tokenInfo->endOffset = currentOffset();
+        m_lastToken = IDENT;
+        return IDENT;
+        
+    slowCase:
+        return lex(tokenData, tokenInfo, lexType, strictMode);
     }
 
 } // namespace JSC
index dd3b9816f657f77d8514c5096c28ecf8ed31ffd1..4e094b6e9b99693e8b49d1b29953d40c8a037d83 100644 (file)
@@ -43,7 +43,7 @@ namespace JSC {
     }
 
     inline Node::Node(JSGlobalData* globalData)
-        : m_line(globalData->lexer->lineNumber())
+        : m_line(globalData->lexer->lastLineNumber())
     {
     }
 
index 4b97e9aadb9e2e2c624e422447053d833e910070..34aa6746dc0174a39621416cf0a95f88b6768c2c 100644 (file)
@@ -67,7 +67,7 @@ void SourceElements::append(StatementNode* statement)
     m_statements.append(statement);
 }
 
-inline StatementNode* SourceElements::singleStatement() const
+StatementNode* SourceElements::singleStatement() const
 {
     size_t size = m_statements.size();
     return size == 1 ? m_statements[0] : 0;
@@ -75,7 +75,7 @@ inline StatementNode* SourceElements::singleStatement() const
 
 // -----------------------------ScopeNodeData ---------------------------
 
-ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
+ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, int numConstants)
     : m_numConstants(numConstants)
     , m_statements(statements)
 {
@@ -84,21 +84,22 @@ ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, Var
         m_varStack.swap(*varStack);
     if (funcStack)
         m_functionStack.swap(*funcStack);
+    m_capturedVariables.swap(capturedVariables);
 }
 
 // ------------------------------ ScopeNode -----------------------------
 
-ScopeNode::ScopeNode(JSGlobalData* globalData)
+ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext)
     : StatementNode(globalData)
     , ParserArenaRefCounted(globalData)
-    , m_features(NoFeatures)
+    , m_features(inStrictContext ? StrictModeFeature : NoFeatures)
 {
 }
 
-ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
+ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, CodeFeatures features, int numConstants)
     : StatementNode(globalData)
     , ParserArenaRefCounted(globalData)
-    , m_data(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants))
+    , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, capturedVariables, numConstants)))
     , m_features(features)
     , m_source(source)
 {
@@ -111,14 +112,14 @@ StatementNode* ScopeNode::singleStatement() const
 
 // ------------------------------ ProgramNode -----------------------------
 
-inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
-    : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
+inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+    : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants)
 {
 }
 
-PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
 {
-    RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
+    RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
 
     ASSERT(node->data()->m_arena.last() == node);
     node->data()->m_arena.removeLast();
@@ -129,14 +130,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem
 
 // ------------------------------ EvalNode -----------------------------
 
-inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
-    : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
+inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
+    : ScopeNode(globalData, source, children, varStack, funcStack, capturedVariables, features, numConstants)
 {
 }
 
-PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
+PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& source, CodeFeatures features, int numConstants)
 {
-    RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
+    RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, capturedVariables, source, features, numConstants);
 
     ASSERT(node->data()->m_arena.last() == node);
     node->data()->m_arena.removeLast();
@@ -153,13 +154,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
         append(parameter->ident());
 }
 
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
-    : ScopeNode(globalData)
+inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, bool inStrictContext)
+    : ScopeNode(globalData, inStrictContext)
 {
 }
 
-inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
-    : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
+inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+    : ScopeNode(globalData, sourceCode, children, varStack, funcStack, capturedVariables, features, numConstants)
 {
 }
 
@@ -176,14 +177,14 @@ void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters,
     m_ident = ident;
 }
 
-FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
+FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData, bool inStrictContext)
 {
-    return new FunctionBodyNode(globalData);
+    return new FunctionBodyNode(globalData, inStrictContext);
 }
 
-PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
+PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, IdentifierSet& capturedVariables, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
 {
-    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
+    RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, capturedVariables, sourceCode, features, numConstants);
 
     ASSERT(node->data()->m_arena.last() == node);
     node->data()->m_arena.removeLast();
index 78521657fce8877c10d15cc4a9650d441157298a..6e73c00ccce939286826b3beb5a67d2537d82d4b 100644 (file)
@@ -57,7 +57,11 @@ namespace JSC {
     const CodeFeatures WithFeature = 1 << 4;
     const CodeFeatures CatchFeature = 1 << 5;
     const CodeFeatures ThisFeature = 1 << 6;
-    const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature;
+    const CodeFeatures StrictModeFeature = 1 << 7;
+    const CodeFeatures ShadowsArgumentsFeature = 1 << 8;
+    
+    
+    const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature;
 
     enum Operator {
         OpEqual,
@@ -81,6 +85,8 @@ namespace JSC {
         OpLogicalOr
     };
 
+    typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
+
     namespace DeclarationStacks {
         enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
         typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
@@ -152,6 +158,7 @@ namespace JSC {
         virtual bool isCommaNode() const { return false; }
         virtual bool isSimpleArray() const { return false; }
         virtual bool isAdd() const { return false; }
+        virtual bool isSubtract() const { return false; }
         virtual bool hasConditionContextCodegen() const { return false; }
 
         virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); }
@@ -265,9 +272,7 @@ namespace JSC {
         uint16_t endOffset() const { return m_endOffset; }
 
     protected:
-        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message);
-        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message, const UString&);
-        RegisterID* emitThrowError(BytecodeGenerator&, ErrorType, const char* message, const Identifier&);
+        RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message);
 
     private:
         uint32_t m_divot;
@@ -404,12 +409,13 @@ namespace JSC {
 
     class PropertyNode : public ParserArenaFreeable {
     public:
-        enum Type { Constant, Getter, Setter };
+        enum Type { Constant = 1, Getter = 2, Setter = 4 };
 
         PropertyNode(JSGlobalData*, const Identifier& name, ExpressionNode* value, Type);
         PropertyNode(JSGlobalData*, double name, ExpressionNode* value, Type);
 
         const Identifier& name() const { return m_name; }
+        Type type() const { return m_type; }
 
     private:
         friend class PropertyListNode;
@@ -805,6 +811,9 @@ namespace JSC {
 
         RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
 
+        ExpressionNode* lhs() { return m_expr1; };
+        ExpressionNode* rhs() { return m_expr2; };
+
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
@@ -853,6 +862,8 @@ namespace JSC {
     class SubNode : public BinaryOpNode {
     public:
         SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+        virtual bool isSubtract() const { return true; }
     };
 
     class LeftShiftNode : public BinaryOpNode {
@@ -1142,6 +1153,7 @@ namespace JSC {
     public:
         BlockNode(JSGlobalData*, SourceElements* = 0);
 
+        StatementNode* singleStatement() const;
         StatementNode* lastStatement() const;
 
     private:
@@ -1293,6 +1305,8 @@ namespace JSC {
     public:
         ReturnNode(JSGlobalData*, ExpressionNode* value);
 
+        ExpressionNode* value() { return m_value; }
+
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
@@ -1362,17 +1376,20 @@ namespace JSC {
         ParameterNode* m_next;
     };
 
-    struct ScopeNodeData : FastAllocBase {
+    struct ScopeNodeData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, int numConstants);
+        ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants);
 
         ParserArena m_arena;
         VarStack m_varStack;
         FunctionStack m_functionStack;
         int m_numConstants;
         SourceElements* m_statements;
+        IdentifierSet m_capturedVariables;
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
@@ -1380,8 +1397,8 @@ namespace JSC {
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
-        ScopeNode(JSGlobalData*);
-        ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, CodeFeatures, int numConstants);
+        ScopeNode(JSGlobalData*, bool inStrictContext);
+        ScopeNode(JSGlobalData*, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants);
 
         using ParserArenaRefCounted::operator new;
 
@@ -1396,10 +1413,15 @@ namespace JSC {
         CodeFeatures features() { return m_features; }
 
         bool usesEval() const { return m_features & EvalFeature; }
-        bool usesArguments() const { return m_features & ArgumentsFeature; }
+        bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); }
+        bool isStrictMode() const { return m_features & StrictModeFeature; }
         void setUsesArguments() { m_features |= ArgumentsFeature; }
         bool usesThis() const { return m_features & ThisFeature; }
-        bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
+        bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); }
+        bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); }
+        bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); }
+        size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); }
+        bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); }
 
         VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; }
         FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; }
@@ -1427,29 +1449,32 @@ namespace JSC {
 
     class ProgramNode : public ScopeNode {
     public:
-        static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+        static const bool isFunctionNode = false;
+        static PassRefPtr<ProgramNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         static const bool scopeIsFunction = false;
 
     private:
-        ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+        ProgramNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
 
     class EvalNode : public ScopeNode {
     public:
-        static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+        static const bool isFunctionNode = false;
+        static PassRefPtr<EvalNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         static const bool scopeIsFunction = false;
 
     private:
-        EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+        EvalNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
     };
 
     class FunctionParameters : public Vector<Identifier>, public RefCounted<FunctionParameters> {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); }
 
@@ -1459,8 +1484,9 @@ namespace JSC {
 
     class FunctionBodyNode : public ScopeNode {
     public:
-        static FunctionBodyNode* create(JSGlobalData*);
-        static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+        static const bool isFunctionNode = true;
+        static FunctionBodyNode* create(JSGlobalData*, bool isStrictMode);
+        static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         FunctionParameters* parameters() const { return m_parameters.get(); }
         size_t parameterCount() const { return m_parameters->size(); }
@@ -1475,8 +1501,8 @@ namespace JSC {
         static const bool scopeIsFunction = true;
 
     private:
-        FunctionBodyNode(JSGlobalData*);
-        FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants);
+        FunctionBodyNode(JSGlobalData*, bool inStrictContext);
+        FunctionBodyNode(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants);
 
         Identifier m_ident;
         RefPtr<FunctionParameters> m_parameters;
index 039fc46fec9a2f2ffae30ec2ad3f95d84d4fcb5e..fc1e986683ee6dce40932af61bbf93633b8e978b 100644 (file)
 #include "Parser.h"
 
 #include "Debugger.h"
+#include "JSParser.h"
 #include "Lexer.h"
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-
-#ifndef yyparse
-extern int jscyyparse(void*);
-#endif
 
 namespace JSC {
 
-void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
+void Parser::parse(JSGlobalData* globalData, FunctionParameters* parameters, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg)
 {
+    ASSERT(globalData);
     m_sourceElements = 0;
 
     int defaultErrLine;
@@ -52,24 +48,25 @@ void Parser::parse(JSGlobalData* globalData, int* errLine, UString* errMsg)
     Lexer& lexer = *globalData->lexer;
     lexer.setCode(*m_source, m_arena);
 
-    int parseError = jscyyparse(globalData);
-    bool lexError = lexer.sawError();
+    const char* parseError = jsParse(globalData, parameters, strictness, mode, m_source);
     int lineNumber = lexer.lineNumber();
+    bool lexError = lexer.sawError();
     lexer.clear();
 
     if (parseError || lexError) {
         *errLine = lineNumber;
-        *errMsg = "Parse error";
+        *errMsg = parseError ? parseError : "Parse error";
         m_sourceElements = 0;
     }
 }
 
 void Parser::didFinishParsing(SourceElements* sourceElements, ParserArenaData<DeclarationStacks::VarStack>* varStack, 
-                              ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants)
+                              ParserArenaData<DeclarationStacks::FunctionStack>* funcStack, CodeFeatures features, int lastLine, int numConstants, IdentifierSet& capturedVars)
 {
     m_sourceElements = sourceElements;
     m_varDeclarations = varStack;
     m_funcDeclarations = funcStack;
+    m_capturedVariables.swap(capturedVars);
     m_features = features;
     m_lastLine = lastLine;
     m_numConstants = numConstants;
index 894f709828e50217d13be2134efeae0eb4fc660a..58398d1d3335f164b5225c0cce7c59dffe6e1982 100644 (file)
@@ -24,6 +24,7 @@
 #define Parser_h
 
 #include "Debugger.h"
+#include "ExceptionHelpers.h"
 #include "Executable.h"
 #include "JSGlobalObject.h"
 #include "Lexer.h"
 namespace JSC {
 
     class FunctionBodyNode;
+    
     class ProgramNode;
     class UString;
 
     template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; };
 
-    class Parser : public Noncopyable {
+    class Parser {
+        WTF_MAKE_NONCOPYABLE(Parser); WTF_MAKE_FAST_ALLOCATED;
     public:
+        Parser() { }
         template <class ParsedNode>
-        PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, Debugger*, ExecState*, const SourceCode& source, int* errLine = 0, UString* errMsg = 0);
+        PassRefPtr<ParsedNode> parse(JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, FunctionParameters*, JSParserStrictness strictness, JSObject** exception);
 
         void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*, 
-                              ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
+                              ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features,
+                              int lastLine, int numConstants, IdentifierSet&);
 
         ParserArena& arena() { return m_arena; }
 
     private:
-        void parse(JSGlobalData*, int* errLine, UString* errMsg);
+        void parse(JSGlobalData*, FunctionParameters*, JSParserStrictness strictness, JSParserMode mode, int* errLine, UString* errMsg);
+
+        // Used to determine type of error to report.
+        bool isFunctionBodyNode(ScopeNode*) { return false; }
+        bool isFunctionBodyNode(FunctionBodyNode*) { return true; }
 
         ParserArena m_arena;
         const SourceCode* m_source;
         SourceElements* m_sourceElements;
         ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
         ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+        IdentifierSet m_capturedVariables;
         CodeFeatures m_features;
         int m_lastLine;
         int m_numConstants;
     };
 
     template <class ParsedNode>
-    PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, int* errLine, UString* errMsg)
+    PassRefPtr<ParsedNode> Parser::parse(JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, FunctionParameters* parameters, JSParserStrictness strictness, JSObject** exception)
     {
+        ASSERT(lexicalGlobalObject);
+        ASSERT(exception && !*exception);
+        int errLine;
+        UString errMsg;
+
         m_source = &source;
         if (ParsedNode::scopeIsFunction)
-            globalData->lexer->setIsReparsing();
-        parse(globalData, errLine, errMsg);
+            lexicalGlobalObject->globalData().lexer->setIsReparsing();
+        parse(&lexicalGlobalObject->globalData(), parameters, strictness, ParsedNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, &errLine, &errMsg);
 
         RefPtr<ParsedNode> result;
         if (m_sourceElements) {
-            result = ParsedNode::create(globalData,
-            m_sourceElements,
-            m_varDeclarations ? &m_varDeclarations->data : 0,
-            m_funcDeclarations ? &m_funcDeclarations->data : 0,
-            source,
-            m_features,
-            m_numConstants);
+            result = ParsedNode::create(&lexicalGlobalObject->globalData(),
+                m_sourceElements,
+                m_varDeclarations ? &m_varDeclarations->data : 0,
+                m_funcDeclarations ? &m_funcDeclarations->data : 0,
+                m_capturedVariables,
+                source,
+                m_features,
+                m_numConstants);
             result->setLoc(m_source->firstLine(), m_lastLine);
+        } else if (lexicalGlobalObject) {
+            // We can never see a syntax error when reparsing a function, since we should have
+            // reported the error when parsing the containing program or eval code. So if we're
+            // parsing a function body node, we assume that what actually happened here is that
+            // we ran out of stack while parsing. If we see an error while parsing eval or program
+            // code we assume that it was a syntax error since running out of stack is much less
+            // likely, and we are currently unable to distinguish between the two cases.
+            if (isFunctionBodyNode(static_cast<ParsedNode*>(0)))
+                *exception = createStackOverflowError(lexicalGlobalObject);
+            else
+                *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, source);
         }
 
         m_arena.reset();
@@ -94,7 +121,7 @@ namespace JSC {
         m_funcDeclarations = 0;
 
         if (debugger && !ParsedNode::scopeIsFunction)
-            debugger->sourceParsed(debuggerExecState, source, *errLine, *errMsg);
+            debugger->sourceParsed(debuggerExecState, source.provider(), errLine, errMsg);
         return result.release();
     }
 
index a8e81595384a2c882cee7b7aab9bd52b2b2c95de..9c96de7625b00aa89e4036fcd7b8a766826216d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "ParserArena.h"
 
 #include "Nodes.h"
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
 ParserArena::ParserArena()
     : m_freeableMemory(0)
     , m_freeablePoolEnd(0)
-    , m_identifierArena(new IdentifierArena)
+    , m_identifierArena(adoptPtr(new IdentifierArena))
 {
 }
 
index eef8e939394c1cff51222066000607f7d07284d7..1563e498f416cef00c3cb9fff3b6a52426ba3794 100644 (file)
@@ -34,32 +34,53 @@ namespace JSC {
     class ParserArenaDeletable;
     class ParserArenaRefCounted;
 
-    class IdentifierArena : public FastAllocBase {
+    class IdentifierArena {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
+        IdentifierArena()
+        {
+            clear();
+        }
+
         ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length);
         const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
 
-        void clear() { m_identifiers.clear(); }
+        void clear()
+        {
+            m_identifiers.clear();
+            for (unsigned  i = 0; i < 128; i++)
+                m_shortIdentifiers[i] = 0;
+        }
         bool isEmpty() const { return m_identifiers.isEmpty(); }
 
     private:
+        static const int MaximumCachableCharacter = 128;
         typedef SegmentedVector<Identifier, 64> IdentifierVector;
         IdentifierVector m_identifiers;
+        FixedArray<Identifier*, MaximumCachableCharacter> m_shortIdentifiers;
     };
 
     ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const UChar* characters, size_t length)
     {
+        if (length == 1 && characters[0] < MaximumCachableCharacter) {
+            if (Identifier* ident = m_shortIdentifiers[characters[0]])
+                return *ident;
+            m_identifiers.append(Identifier(globalData, characters, length));
+            m_shortIdentifiers[characters[0]] = &m_identifiers.last();
+            return m_identifiers.last();
+        }
         m_identifiers.append(Identifier(globalData, characters, length));
         return m_identifiers.last();
     }
 
     inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number)
     {
-        m_identifiers.append(Identifier(globalData, UString::from(number)));
+        m_identifiers.append(Identifier(globalData, UString::number(number)));
         return m_identifiers.last();
     }
 
-    class ParserArena : Noncopyable {
+    class ParserArena {
+        WTF_MAKE_NONCOPYABLE(ParserArena);
     public:
         ParserArena();
         ~ParserArena();
index 1c59eeda406b1223be80588a5db635085d7cd6f5..e9b6b5614ed967e19d0f7f14d7307504ea43a2cd 100644 (file)
 #ifndef SourceProvider_h
 #define SourceProvider_h
 
+#include "SourceProviderCache.h"
 #include "UString.h"
+#include <wtf/PassOwnPtr.h>
 #include <wtf/RefCounted.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/text/TextPosition.h>
 
 namespace JSC {
 
-    enum SourceBOMPresence { SourceHasNoBOMs, SourceCouldHaveBOMs };
-
     class SourceProvider : public RefCounted<SourceProvider> {
     public:
-        SourceProvider(const UString& url, SourceBOMPresence hasBOMs = SourceCouldHaveBOMs)
+        SourceProvider(const UString& url, SourceProviderCache* cache = 0)
             : m_url(url)
-            , m_hasBOMs(hasBOMs)
+            , m_validated(false)
+            , m_cache(cache ? cache : new SourceProviderCache)
+            , m_cacheOwned(!cache)
+        {
+        }
+        virtual ~SourceProvider()
         {
+            if (m_cacheOwned)
+                delete m_cache;
         }
-        virtual ~SourceProvider() { }
 
         virtual UString getRange(int start, int end) const = 0;
         virtual const UChar* data() const = 0;
         virtual int length() const = 0;
         
         const UString& url() { return m_url; }
+        virtual TextPosition1 startPosition() const { return TextPosition1::minimumPosition(); }
         intptr_t asID() { return reinterpret_cast<intptr_t>(this); }
 
-        SourceBOMPresence hasBOMs() const { return m_hasBOMs; }
+        bool isValid() const { return m_validated; }
+        void setValid() { m_validated = true; }
 
+        SourceProviderCache* cache() const { return m_cache; }
+        void notifyCacheSizeChanged(int delta) { if (!m_cacheOwned) cacheSizeChanged(delta); }
+        
     private:
+        virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); }
+
         UString m_url;
-        SourceBOMPresence m_hasBOMs;
+        bool m_validated;
+        SourceProviderCache* m_cache;
+        bool m_cacheOwned;
     };
 
     class UStringSourceProvider : public SourceProvider {
@@ -66,9 +83,12 @@ namespace JSC {
             return adoptRef(new UStringSourceProvider(source, url));
         }
 
-        UString getRange(int start, int end) const { return m_source.substr(start, end - start); }
-        const UChar* data() const { return m_source.data(); }
-        int length() const { return m_source.size(); }
+        UString getRange(int start, int end) const
+        {
+            return m_source.substringSharingImpl(start, end - start);
+        }
+        const UChar* data() const { return m_source.characters(); }
+        int length() const { return m_source.length(); }
 
     private:
         UStringSourceProvider(const UString& source, const UString& url)
diff --git a/parser/SourceProviderCache.cpp b/parser/SourceProviderCache.cpp
new file mode 100644 (file)
index 0000000..afeec52
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+#include "config.h"
+#include "SourceProviderCache.h"
+
+#include "SourceProviderCacheItem.h"
+
+namespace JSC {
+
+SourceProviderCache::~SourceProviderCache()
+{
+    clear();
+}
+
+void SourceProviderCache::clear()
+{
+    deleteAllValues(m_map);
+    m_map.clear();
+    m_contentByteSize = 0;
+}
+
+unsigned SourceProviderCache::byteSize() const
+{ 
+    return m_contentByteSize + sizeof(*this) + m_map.capacity() * sizeof(SourceProviderCacheItem*);
+}
+
+void SourceProviderCache::add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem> item, unsigned size)
+{
+    m_map.add(sourcePosition, item.leakPtr());
+    m_contentByteSize += size;
+}
+
+}
diff --git a/parser/SourceProviderCache.h b/parser/SourceProviderCache.h
new file mode 100644 (file)
index 0000000..4df46f7
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include <wtf/HashMap.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace JSC {
+
+class SourceProviderCacheItem;
+
+class SourceProviderCache {
+public:
+    SourceProviderCache() : m_contentByteSize(0) {}
+    ~SourceProviderCache();
+
+    void clear();
+    unsigned byteSize() const;
+    void add(int sourcePosition, PassOwnPtr<SourceProviderCacheItem>, unsigned size);
+    const SourceProviderCacheItem* get(int sourcePosition) const { return m_map.get(sourcePosition); }
+
+private:
+    HashMap<int, SourceProviderCacheItem*> m_map;
+    unsigned m_contentByteSize;
+};
+
+}
diff --git a/parser/SourceProviderCacheItem.h b/parser/SourceProviderCacheItem.h
new file mode 100644 (file)
index 0000000..b9ab225
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "JSParser.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+
+class SourceProviderCacheItem {
+public:
+    SourceProviderCacheItem(int closeBraceLine, int closeBracePos)
+        : closeBraceLine(closeBraceLine) 
+        , closeBracePos(closeBracePos)
+    {
+    }
+    unsigned approximateByteSize() const
+    {
+        // The identifiers are uniqued strings so most likely there are few names that actually use any additional memory.
+        static const unsigned assummedAverageIdentifierSize = sizeof(RefPtr<StringImpl>) + 2;
+        unsigned size = sizeof(*this);
+        size += usedVariables.size() * assummedAverageIdentifierSize;
+        size += writtenVariables.size() * assummedAverageIdentifierSize;
+        return size;
+    }
+    JSToken closeBraceToken() const 
+    {
+        JSToken token;
+        token.m_type = CLOSEBRACE;
+        token.m_data.intValue = closeBracePos;
+        token.m_info.startOffset = closeBracePos;
+        token.m_info.endOffset = closeBracePos + 1;
+        token.m_info.line = closeBraceLine; 
+        return token;
+    }
+    
+    int closeBraceLine;
+    int closeBracePos;
+    bool usesEval;
+    Vector<RefPtr<StringImpl> > usedVariables;
+    Vector<RefPtr<StringImpl> > writtenVariables;
+};
+
+}
diff --git a/parser/SyntaxChecker.h b/parser/SyntaxChecker.h
new file mode 100644 (file)
index 0000000..2392244
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 SyntaxChecker_h
+#define SyntaxChecker_h
+
+#include "Lexer.h"
+#include <yarr/YarrSyntaxChecker.h>
+
+namespace JSC {
+class SyntaxChecker {
+public:
+    struct BinaryExprContext {
+        BinaryExprContext(SyntaxChecker& context)
+            : m_context(&context)
+        {
+            m_context->m_topBinaryExprs.append(m_context->m_topBinaryExpr);
+            m_context->m_topBinaryExpr = 0;
+        }
+        ~BinaryExprContext()
+        {
+            m_context->m_topBinaryExpr = m_context->m_topBinaryExprs.last();
+            m_context->m_topBinaryExprs.removeLast();
+        }
+    private:
+        SyntaxChecker* m_context;
+    };
+    struct UnaryExprContext {
+        UnaryExprContext(SyntaxChecker& context)
+            : m_context(&context)
+        {
+            m_context->m_topUnaryTokens.append(m_context->m_topUnaryToken);
+            m_context->m_topUnaryToken = 0;
+        }
+        ~UnaryExprContext()
+        {
+            m_context->m_topUnaryToken = m_context->m_topUnaryTokens.last();
+            m_context->m_topUnaryTokens.removeLast();
+        }
+    private:
+        SyntaxChecker* m_context;
+    };
+    
+    SyntaxChecker(JSGlobalData* , Lexer*)
+    {
+    }
+
+    typedef SyntaxChecker FunctionBodyBuilder;
+    enum { NoneExpr = 0,
+        ResolveEvalExpr, ResolveExpr, NumberExpr, StringExpr,
+        ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
+        FunctionExpr, BracketExpr, DotExpr, CallExpr,
+        NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
+        ConditionalExpr, AssignmentExpr, TypeofExpr,
+        DeleteExpr, ArrayLiteralExpr };
+    typedef int ExpressionType;
+
+    typedef ExpressionType Expression;
+    typedef int SourceElements;
+    typedef int Arguments;
+    typedef ExpressionType Comma;
+    struct Property {
+        ALWAYS_INLINE Property(void* = 0)
+            : type((PropertyNode::Type)0)
+        {
+        }
+        ALWAYS_INLINE Property(const Identifier* ident, PropertyNode::Type ty)
+        : name(ident)
+        , type(ty)
+        {
+        }
+        ALWAYS_INLINE Property(PropertyNode::Type ty)
+            : name(0)
+            , type(ty)
+        {
+        }
+        ALWAYS_INLINE bool operator!() { return !type; }
+        const Identifier* name;
+        PropertyNode::Type type;
+    };
+    typedef int PropertyList;
+    typedef int ElementList;
+    typedef int ArgumentsList;
+    typedef int FormalParameterList;
+    typedef int FunctionBody;
+    typedef int Statement;
+    typedef int ClauseList;
+    typedef int Clause;
+    typedef int ConstDeclList;
+    typedef int BinaryOperand;
+    
+    static const bool CreatesAST = false;
+    static const bool NeedsFreeVariableInfo = false;
+    static const bool CanUseFunctionCache = true;
+    static const unsigned DontBuildKeywords = Lexer::DontBuildKeywords;
+    static const unsigned DontBuildStrings = Lexer::DontBuildStrings;
+
+    int createSourceElements() { return 1; }
+    ExpressionType makeFunctionCallNode(int, int, int, int, int) { return CallExpr; }
+    void appendToComma(ExpressionType& base, ExpressionType right) { base = right; }
+    ExpressionType createCommaExpr(ExpressionType, ExpressionType right) { return right; }
+    ExpressionType makeAssignNode(ExpressionType, Operator, ExpressionType, bool, bool, int, int, int) { return AssignmentExpr; }
+    ExpressionType makePrefixNode(ExpressionType, Operator, int, int, int) { return PreExpr; }
+    ExpressionType makePostfixNode(ExpressionType, Operator, int, int, int) { return PostExpr; }
+    ExpressionType makeTypeOfNode(ExpressionType) { return TypeofExpr; }
+    ExpressionType makeDeleteNode(ExpressionType, int, int, int) { return DeleteExpr; }
+    ExpressionType makeNegateNode(ExpressionType) { return UnaryExpr; }
+    ExpressionType makeBitwiseNotNode(ExpressionType) { return UnaryExpr; }
+    ExpressionType createLogicalNot(ExpressionType) { return UnaryExpr; }
+    ExpressionType createUnaryPlus(ExpressionType) { return UnaryExpr; }
+    ExpressionType createVoid(ExpressionType) { return UnaryExpr; }
+    ExpressionType thisExpr() { return ThisExpr; }
+    ExpressionType createResolve(const Identifier*, int) { return ResolveExpr; }
+    ExpressionType createObjectLiteral() { return ObjectLiteralExpr; }
+    ExpressionType createObjectLiteral(int) { return ObjectLiteralExpr; }
+    ExpressionType createArray(int) { return ArrayLiteralExpr; }
+    ExpressionType createArray(int, int) { return ArrayLiteralExpr; }
+    ExpressionType createNumberExpr(double) { return NumberExpr; }
+    ExpressionType createString(const Identifier*) { return StringExpr; }
+    ExpressionType createBoolean(bool) { return BoolExpr; }
+    ExpressionType createNull() { return NullExpr; }
+    ExpressionType createBracketAccess(ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
+    ExpressionType createDotAccess(ExpressionType, const Identifier*, int, int, int) { return DotExpr; }
+    ExpressionType createRegExp(const Identifier& pattern, const Identifier&, int) { return Yarr::checkSyntax(pattern.ustring()) ? 0 : RegExpExpr; }
+    ExpressionType createNewExpr(ExpressionType, int, int, int, int) { return NewExpr; }
+    ExpressionType createNewExpr(ExpressionType, int, int) { return NewExpr; }
+    ExpressionType createConditionalExpr(ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
+    ExpressionType createAssignResolve(const Identifier&, ExpressionType, bool, int, int, int) { return AssignmentExpr; }
+    ExpressionType createFunctionExpr(const Identifier*, int, int, int, int, int, int) { return FunctionExpr; }
+    int createFunctionBody(bool) { return 1; }
+    int createArguments() { return 1; }
+    int createArguments(int) { return 1; }
+    int createArgumentsList(int) { return 1; }
+    int createArgumentsList(int, int) { return 1; }
+    template <bool complete> Property createProperty(const Identifier* name, int, PropertyNode::Type type)
+    {
+        if (!complete)
+            return Property(type);
+        ASSERT(name);
+        return Property(name, type);
+    }
+    template <bool complete> Property createProperty(JSGlobalData* globalData, double name, int, PropertyNode::Type type)
+    {
+        if (!complete)
+            return Property(type);
+        return Property(&globalData->parser->arena().identifierArena().makeNumericIdentifier(globalData, name), type);
+    }
+    int createPropertyList(Property) { return 1; }
+    int createPropertyList(Property, int) { return 1; }
+    int createElementList(int, int) { return 1; }
+    int createElementList(int, int, int) { return 1; }
+    int createFormalParameterList(const Identifier&) { return 1; }
+    int createFormalParameterList(int, const Identifier&) { return 1; }
+    int createClause(int, int) { return 1; }
+    int createClauseList(int) { return 1; }
+    int createClauseList(int, int) { return 1; }
+    void setUsesArguments(int) { }
+    int createFuncDeclStatement(const Identifier*, int, int, int, int, int, int) { return 1; }
+    int createBlockStatement(int, int, int) { return 1; }
+    int createExprStatement(int, int, int) { return 1; }
+    int createIfStatement(int, int, int, int) { return 1; }
+    int createIfStatement(int, int, int, int, int) { return 1; }
+    int createForLoop(int, int, int, int, bool, int, int) { return 1; }
+    int createForInLoop(const Identifier*, int, int, int, int, int, int, int, int, int, int) { return 1; }
+    int createForInLoop(int, int, int, int, int, int, int, int) { return 1; }
+    int createEmptyStatement() { return 1; }
+    int createVarStatement(int, int, int) { return 1; }
+    int createReturnStatement(int, int, int, int, int) { return 1; }
+    int createBreakStatement(int, int, int, int) { return 1; }
+    int createBreakStatement(const Identifier*, int, int, int, int) { return 1; }
+    int createContinueStatement(int, int, int, int) { return 1; }
+    int createContinueStatement(const Identifier*, int, int, int, int) { return 1; }
+    int createTryStatement(int, const Identifier*, bool, int, int, int, int) { return 1; }
+    int createSwitchStatement(int, int, int, int, int, int) { return 1; }
+    int createWhileStatement(int, int, int, int) { return 1; }
+    int createWithStatement(int, int, int, int, int, int) { return 1; }
+    int createDoWhileStatement(int, int, int, int) { return 1; }
+    int createLabelStatement(const Identifier*, int, int, int) { return 1; }
+    int createThrowStatement(int, int, int, int, int) { return 1; }
+    int createDebugger(int, int) { return 1; }
+    int createConstStatement(int, int, int) { return 1; }
+    int appendConstDecl(int, const Identifier*, int) { return 1; }
+    template <bool strict> Property createGetterOrSetterProperty(PropertyNode::Type type, const Identifier* name, int, int, int, int, int, int)
+    {
+        ASSERT(name);
+        if (!strict)
+            return Property(type);
+        return Property(name, type);
+    }
+
+    void appendStatement(int, int) { }
+    void addVar(const Identifier*, bool) { }
+    int combineCommaNodes(int, int) { return 1; }
+    int evalCount() const { return 0; }
+    void appendBinaryExpressionInfo(int& operandStackDepth, int expr, int, int, int, bool)
+    {
+        if (!m_topBinaryExpr)
+            m_topBinaryExpr = expr;
+        else
+            m_topBinaryExpr = BinaryExpr;
+        operandStackDepth++;
+    }
+    
+    // Logic to handle datastructures used during parsing of binary expressions
+    void operatorStackPop(int& operatorStackDepth) { operatorStackDepth--; }
+    bool operatorStackHasHigherPrecedence(int&, int) { return true; }
+    BinaryOperand getFromOperandStack(int) { return m_topBinaryExpr; }
+    void shrinkOperandStackBy(int& operandStackDepth, int amount) { operandStackDepth -= amount; }
+    void appendBinaryOperation(int& operandStackDepth, int&, BinaryOperand, BinaryOperand) { operandStackDepth++; }
+    void operatorStackAppend(int& operatorStackDepth, int, int) { operatorStackDepth++; }
+    int popOperandStack(int&) { int res = m_topBinaryExpr; m_topBinaryExpr = 0; return res; }
+    
+    void appendUnaryToken(int& stackDepth, int tok, int) { stackDepth = 1; m_topUnaryToken = tok; }
+    int unaryTokenStackLastType(int&) { return m_topUnaryToken; }
+    int unaryTokenStackLastStart(int&) { return 0; }
+    void unaryTokenStackRemoveLast(int& stackDepth) { stackDepth = 0; }
+    
+    void assignmentStackAppend(int, int, int, int, int, Operator) { }
+    int createAssignment(int, int, int, int, int) { ASSERT_NOT_REACHED(); return 1; }
+    const Identifier& getName(const Property& property) const { ASSERT(property.name); return *property.name; }
+    PropertyNode::Type getType(const Property& property) const { return property.type; }
+    bool isResolve(ExpressionType expr) const { return expr == ResolveExpr || expr == ResolveEvalExpr; }
+    
+private:
+    int m_topBinaryExpr;
+    int m_topUnaryToken;
+    Vector<int, 8> m_topBinaryExprs;
+    Vector<int, 8> m_topUnaryTokens;
+};
+
+}
+
+#endif
diff --git a/pcre/AUTHORS b/pcre/AUTHORS
deleted file mode 100644 (file)
index dbac2a5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-Originally written by:  Philip Hazel
-Email local part:       ph10
-Email domain:           cam.ac.uk
-
-University of Cambridge Computing Service,
-Cambridge, England. Phone: +44 1223 334714.
-
-Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
-
-Adapted for JavaScriptCore and WebKit by Apple Inc.
-
-Copyright (c) 2005, 2006, 2007 Apple Inc. All rights reserved.
diff --git a/pcre/COPYING b/pcre/COPYING
deleted file mode 100644 (file)
index 6ffdc24..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
-This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed.
-
-Copyright (c) 1997-2005 University of Cambridge. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the name of Apple
-      Inc. nor the names of their contributors may be used to endorse or
-      promote products derived from this software without specific prior
-      written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
diff --git a/pcre/dftables b/pcre/dftables
deleted file mode 100755 (executable)
index 669b948..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/perl -w
-#
-# This is JavaScriptCore's variant of the PCRE library. While this library
-# started out as a copy of PCRE, many of the features of PCRE have been
-# removed. This library now supports only the regular expression features
-# required by the JavaScript language specification, and has only the functions
-# needed by JavaScriptCore and the rest of WebKit.
-# 
-#                  Originally written by Philip Hazel
-#            Copyright (c) 1997-2006 University of Cambridge
-#  Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 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:
-# 
-#     * Redistributions of source code must retain the above copyright notice,
-#       this list of conditions and the following disclaimer.
-# 
-#     * 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.
-# 
-#     * Neither the name of the University of Cambridge nor the names of its
-#       contributors may be used to endorse or promote products derived from
-#       this software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
-# -----------------------------------------------------------------------------
-
-# This is a freestanding support program to generate a file containing
-# character tables. The tables are built according to the default C
-# locale.
-
-use strict;
-
-use File::Basename;
-use File::Spec;
-use File::Temp qw(tempfile);
-use Getopt::Long;
-
-sub readHeaderValues();
-
-my %pcre_internal;
-
-if (scalar(@ARGV) < 1) {
-    print STDERR "Usage: ", basename($0), " [--preprocessor=program] output-file\n";
-    exit 1;
-}
-
-my $outputFile;
-my $preprocessor;
-GetOptions('preprocessor=s' => \$preprocessor);
-if (not $preprocessor) {
-    $preprocessor = "cpp";
-}
-
-$outputFile = $ARGV[0];
-die('Must specify output file.') unless defined($outputFile);
-
-readHeaderValues();
-
-open(OUT, ">", $outputFile) or die "$!";
-binmode(OUT);
-
-printf(OUT
-    "/*************************************************\n" .
-    "*      Perl-Compatible Regular Expressions       *\n" .
-    "*************************************************/\n\n" .
-    "/* This file is automatically written by the dftables auxiliary \n" .
-    "program. If you edit it by hand, you might like to edit the Makefile to \n" .
-    "prevent its ever being regenerated.\n\n");
-printf(OUT
-    "This file contains the default tables for characters with codes less than\n" .
-    "128 (ASCII characters). These tables are used when no external tables are\n" .
-    "passed to PCRE. */\n\n" .
-    "const unsigned char jsc_pcre_default_tables[%d] = {\n\n" .
-    "/* This table is a lower casing table. */\n\n", $pcre_internal{tables_length});
-
-if ($pcre_internal{lcc_offset} != 0) {
-    die "lcc_offset != 0";
-}
-
-printf(OUT "  ");
-for (my $i = 0; $i < 128; $i++) {
-    if (($i & 7) == 0 && $i != 0) {
-        printf(OUT "\n  ");
-    }
-    printf(OUT "0x%02X", ord(lc(chr($i))));
-    if ($i != 127) {
-        printf(OUT ", ");
-    }
-}
-printf(OUT ",\n\n");
-
-printf(OUT "/* This table is a case flipping table. */\n\n");
-
-if ($pcre_internal{fcc_offset} != 128) {
-  die "fcc_offset != 128";
-}
-
-printf(OUT "  ");
-for (my $i = 0; $i < 128; $i++) {
-    if (($i & 7) == 0 && $i != 0) {
-        printf(OUT "\n  ");
-    }
-    my $c = chr($i);
-    printf(OUT "0x%02X", $c =~ /[[:lower:]]/ ? ord(uc($c)) : ord(lc($c)));
-    if ($i != 127) {
-        printf(OUT ", ");
-    }
-}
-printf(OUT ",\n\n");
-
-printf(OUT
-    "/* This table contains bit maps for various character classes.\n" .
-    "Each map is 32 bytes long and the bits run from the least\n" .
-    "significant end of each byte. The classes are: space, digit, word. */\n\n");
-
-if ($pcre_internal{cbits_offset} != $pcre_internal{fcc_offset} + 128) {
-    die "cbits_offset != fcc_offset + 128";
-}
-
-my @cbit_table = (0) x $pcre_internal{cbit_length};
-for (my $i = ord('0'); $i <= ord('9'); $i++) {
-    $cbit_table[$pcre_internal{cbit_digit} + $i / 8] |= 1 << ($i & 7);
-}
-$cbit_table[$pcre_internal{cbit_word} + ord('_') / 8] |= 1 << (ord('_') & 7);
-for (my $i = 0; $i < 128; $i++) {
-    my $c = chr($i);
-    if ($c =~ /[[:alnum:]]/) {
-        $cbit_table[$pcre_internal{cbit_word} + $i / 8] |= 1 << ($i & 7);
-    }
-    if ($c =~ /[[:space:]]/) {
-        $cbit_table[$pcre_internal{cbit_space} + $i / 8] |= 1 << ($i & 7);
-    }
-}
-
-printf(OUT "  ");
-for (my $i = 0; $i < $pcre_internal{cbit_length}; $i++) {
-    if (($i & 7) == 0 && $i != 0) {
-        if (($i & 31) == 0) {
-            printf(OUT "\n");
-        }
-        printf(OUT "\n  ");
-    }
-    printf(OUT "0x%02X", $cbit_table[$i]);
-    if ($i != $pcre_internal{cbit_length} - 1) {
-        printf(OUT ", ");
-    }
-}
-printf(OUT ",\n\n");
-
-printf(OUT
-    "/* This table identifies various classes of character by individual bits:\n" .
-    "  0x%02x   white space character\n" .
-    "  0x%02x   hexadecimal digit\n" .
-    "  0x%02x   alphanumeric or '_'\n*/\n\n",
-    $pcre_internal{ctype_space}, $pcre_internal{ctype_xdigit}, $pcre_internal{ctype_word});
-
-if ($pcre_internal{ctypes_offset} != $pcre_internal{cbits_offset} + $pcre_internal{cbit_length}) {
-    die "ctypes_offset != cbits_offset + cbit_length";
-}
-
-printf(OUT "  ");
-for (my $i = 0; $i < 128; $i++) {
-    my $x = 0;
-    my $c = chr($i);
-    if ($c =~ /[[:space:]]/) {
-        $x += $pcre_internal{ctype_space};
-    }
-    if ($c =~ /[[:xdigit:]]/) {
-        $x += $pcre_internal{ctype_xdigit};
-    }
-    if ($c =~ /[[:alnum:]_]/) {
-        $x += $pcre_internal{ctype_word};
-    }
-    printf(OUT "0x%02X", $x);
-    if ($i != 127) {
-        printf(OUT ", ");
-    } else {
-        printf(OUT "};");
-    }
-    if (($i & 7) == 7) {
-        printf(OUT " /* ");
-        my $d = chr($i - 7);
-        if ($d =~ /[[:print:]]/) {
-            printf(OUT " %c -", $i - 7);
-        } else {
-            printf(OUT "%3d-", $i - 7);
-        }
-        if ($c =~ m/[[:print:]]/) {
-            printf(OUT " %c ", $i);
-        } else {
-            printf(OUT "%3d", $i);
-        }
-        printf(OUT " */\n");
-        if ($i != 127) {
-            printf(OUT "  ");
-        }
-    }
-}
-
-if ($pcre_internal{tables_length} != $pcre_internal{ctypes_offset} + 128) {
-    die "tables_length != ctypes_offset + 128";
-}
-
-printf(OUT "\n\n/* End of chartables.c */\n");
-
-close(OUT);
-
-exit 0;
-
-sub readHeaderValues()
-{
-    my @variables = qw(
-        cbit_digit
-        cbit_length
-        cbit_space
-        cbit_word
-        cbits_offset
-        ctype_space
-        ctype_word
-        ctype_xdigit
-        ctypes_offset
-        fcc_offset
-        lcc_offset
-        tables_length
-    );
-
-    local $/ = undef;
-
-    my $headerPath = File::Spec->catfile(dirname($0), "pcre_internal.h");
-    my ($fh, $tempFile) = tempfile(
-        basename($0) . "-XXXXXXXX",
-        DIR => File::Spec->tmpdir(),
-        SUFFIX => ".in",
-        UNLINK => 0,
-    );
-
-    print $fh "#define DFTABLES\n\n";
-
-    open(HEADER, "<", $headerPath) or die "$!";
-    print $fh <HEADER>;
-    close(HEADER);
-
-    print $fh "\n\n";
-
-    for my $v (@variables) {
-        print $fh "\$pcre_internal{\"$v\"} = $v;\n";
-    }
-
-    close($fh);
-
-    open(CPP, "$preprocessor \"$tempFile\" |") or die "$!";
-    my $content = <CPP>;
-    close(CPP);
-    
-    eval $content;
-    die "$@" if $@;
-    unlink $tempFile;
-}
diff --git a/pcre/pcre.h b/pcre/pcre.h
deleted file mode 100644 (file)
index 55044fd..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This is the public header file for JavaScriptCore's variant of the PCRE
-library. While this library started out as a copy of PCRE, many of the
-features of PCRE have been removed. This library now supports only the
-regular expression features required by the JavaScript language
-specification, and has only the functions needed by JavaScriptCore and the
-rest of WebKit.
-
-           Copyright (c) 1997-2005 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 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:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-// FIXME: This file needs to be renamed to JSRegExp.h; it's no longer PCRE.
-
-#ifndef JSRegExp_h
-#define JSRegExp_h
-
-#include <wtf/unicode/Unicode.h>
-
-struct JSRegExp;
-
-enum JSRegExpIgnoreCaseOption { JSRegExpDoNotIgnoreCase, JSRegExpIgnoreCase };
-enum JSRegExpMultilineOption { JSRegExpSingleLine, JSRegExpMultiline };
-
-/* jsRegExpExecute error codes */
-const int JSRegExpErrorNoMatch = -1;
-const int JSRegExpErrorHitLimit = -2;
-const int JSRegExpErrorNoMemory = -3;
-const int JSRegExpErrorInternal = -4;
-
-JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
-    JSRegExpIgnoreCaseOption, JSRegExpMultilineOption,
-    unsigned* numSubpatterns, const char** errorMessage);
-
-int jsRegExpExecute(const JSRegExp*,
-    const UChar* subject, int subjectLength, int startOffset,
-    int* offsetsVector, int offsetsVectorLength);
-
-void jsRegExpFree(JSRegExp*);
-
-#endif
diff --git a/pcre/pcre.pri b/pcre/pcre.pri
deleted file mode 100644 (file)
index 4f59e17..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# Perl Compatible Regular Expressions - Qt4 build info
-VPATH += $$PWD
-INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp
-DEPENDPATH += $$PWD
-
-SOURCES += \
-    pcre_compile.cpp \
-    pcre_exec.cpp \
-    pcre_tables.cpp \
-    pcre_ucp_searchfuncs.cpp \
-    pcre_xclass.cpp
-
diff --git a/pcre/pcre_compile.cpp b/pcre/pcre_compile.cpp
deleted file mode 100644 (file)
index 2bedca6..0000000
+++ /dev/null
@@ -1,2706 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-/* This module contains the external function jsRegExpExecute(), along with
-supporting internal functions that are not used by other modules. */
-
-#include "config.h"
-
-#include "pcre_internal.h"
-
-#include <string.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/FastMalloc.h>
-
-using namespace WTF;
-
-/* Negative values for the firstchar and reqchar variables */
-
-#define REQ_UNSET (-2)
-#define REQ_NONE  (-1)
-
-/*************************************************
-*      Code parameters and static tables         *
-*************************************************/
-
-/* Maximum number of items on the nested bracket stacks at compile time. This
-applies to the nesting of all kinds of parentheses. It does not limit
-un-nested, non-capturing parentheses. This number can be made bigger if
-necessary - it is used to dimension one int and one unsigned char vector at
-compile time. */
-
-#define BRASTACK_SIZE 200
-
-/* Table for handling escaped characters in the range '0'-'z'. Positive returns
-are simple data values; negative values are for special things like \d and so
-on. Zero means further processing is needed (for things like \x), or the escape
-is invalid. */
-
-static const short escapes[] = {
-     0,      0,      0,      0,      0,      0,      0,      0,   /* 0 - 7 */
-     0,      0,    ':',    ';',    '<',    '=',    '>',    '?',   /* 8 - ? */
-   '@',      0, -ESC_B,      0, -ESC_D,      0,      0,      0,   /* @ - G */
-     0,      0,      0,      0,      0,      0,      0,      0,   /* H - O */
-     0,      0,      0, -ESC_S,      0,      0,      0, -ESC_W,   /* P - W */
-     0,      0,      0,    '[',   '\\',    ']',    '^',    '_',   /* X - _ */
-   '`',      7, -ESC_b,      0, -ESC_d,      0,   '\f',      0,   /* ` - g */
-     0,      0,      0,      0,      0,      0,   '\n',      0,   /* h - o */
-     0,      0,    '\r', -ESC_s,   '\t',      0,  '\v', -ESC_w,   /* p - w */
-     0,      0,      0                                            /* x - z */
-};
-
-/* Error code numbers. They are given names so that they can more easily be
-tracked. */
-
-enum ErrorCode {
-    ERR0, ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9,
-    ERR10, ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17
-};
-
-/* The texts of compile-time error messages. These are "char *" because they
-are passed to the outside world. */
-
-static const char* errorText(ErrorCode code)
-{
-    static const char errorTexts[] =
-      /* 1 */
-      "\\ at end of pattern\0"
-      "\\c at end of pattern\0"
-      "character value in \\x{...} sequence is too large\0"
-      "numbers out of order in {} quantifier\0"
-      /* 5 */
-      "number too big in {} quantifier\0"
-      "missing terminating ] for character class\0"
-      "internal error: code overflow\0"
-      "range out of order in character class\0"
-      "nothing to repeat\0"
-      /* 10 */
-      "unmatched parentheses\0"
-      "internal error: unexpected repeat\0"
-      "unrecognized character after (?\0"
-      "failed to get memory\0"
-      "missing )\0"
-      /* 15 */
-      "reference to non-existent subpattern\0"
-      "regular expression too large\0"
-      "parentheses nested too deeply"
-    ;
-
-    int i = code;
-    const char* text = errorTexts;
-    while (i > 1)
-        i -= !*text++;
-    return text;
-}
-
-/* Structure for passing "static" information around between the functions
-doing the compiling. */
-
-struct CompileData {
-    CompileData() {
-        topBackref = 0;
-        backrefMap = 0;
-        reqVaryOpt = 0;
-        needOuterBracket = false;
-        numCapturingBrackets = 0;
-    }
-    int topBackref;            /* Maximum back reference */
-    unsigned backrefMap;       /* Bitmap of low back refs */
-    int reqVaryOpt;            /* "After variable item" flag for reqByte */
-    bool needOuterBracket;
-    int numCapturingBrackets;
-};
-
-/* Definitions to allow mutual recursion */
-
-static bool compileBracket(int, int*, unsigned char**, const UChar**, const UChar*, ErrorCode*, int, int*, int*, CompileData&);
-static bool bracketIsAnchored(const unsigned char* code);
-static bool bracketNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap);
-static int bracketFindFirstAssertedCharacter(const unsigned char* code, bool inassert);
-
-/*************************************************
-*            Handle escapes                      *
-*************************************************/
-
-/* This function is called when a \ has been encountered. It either returns a
-positive value for a simple escape such as \n, or a negative value which
-encodes one of the more complicated things such as \d. When UTF-8 is enabled,
-a positive value greater than 255 may be returned. On entry, ptr is pointing at
-the \. On exit, it is on the final character of the escape sequence.
-
-Arguments:
-  ptrPtr         points to the pattern position pointer
-  errorCodePtr   points to the errorcode variable
-  bracount       number of previous extracting brackets
-  options        the options bits
-  isClass        true if inside a character class
-
-Returns:         zero or positive => a data character
-                 negative => a special escape sequence
-                 on error, errorPtr is set
-*/
-
-static int checkEscape(const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* errorCodePtr, int bracount, bool isClass)
-{
-    const UChar* ptr = *ptrPtr + 1;
-
-    /* If backslash is at the end of the pattern, it's an error. */
-    if (ptr == patternEnd) {
-        *errorCodePtr = ERR1;
-        *ptrPtr = ptr;
-        return 0;
-    }
-    
-    int c = *ptr;
-    
-    /* Non-alphamerics are literals. For digits or letters, do an initial lookup in
-     a table. A non-zero result is something that can be returned immediately.
-     Otherwise further processing may be required. */
-    
-    if (c < '0' || c > 'z') { /* Not alphameric */
-    } else if (int escapeValue = escapes[c - '0']) {
-        c = escapeValue;
-        if (isClass) {
-            if (-c == ESC_b)
-                c = '\b'; /* \b is backslash in a class */
-            else if (-c == ESC_B)
-                c = 'B'; /* and \B is a capital B in a class (in browsers event though ECMAScript 15.10.2.19 says it raises an error) */
-        }
-    /* Escapes that need further processing, or are illegal. */
-    
-    } else {
-        switch (c) {
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-                /* Escape sequences starting with a non-zero digit are backreferences,
-                 unless there are insufficient brackets, in which case they are octal
-                 escape sequences. Those sequences end on the first non-octal character
-                 or when we overflow 0-255, whichever comes first. */
-                
-                if (!isClass) {
-                    const UChar* oldptr = ptr;
-                    c -= '0';
-                    while ((ptr + 1 < patternEnd) && isASCIIDigit(ptr[1]) && c <= bracount)
-                        c = c * 10 + *(++ptr) - '0';
-                    if (c <= bracount) {
-                        c = -(ESC_REF + c);
-                        break;
-                    }
-                    ptr = oldptr;      /* Put the pointer back and fall through */
-                }
-                
-                /* Handle an octal number following \. If the first digit is 8 or 9,
-                 this is not octal. */
-                
-                if ((c = *ptr) >= '8') {
-                    c = '\\';
-                    ptr -= 1;
-                    break;
-                }
-
-            /* \0 always starts an octal number, but we may drop through to here with a
-             larger first octal digit. */
-
-            case '0': {
-                c -= '0';
-                int i;
-                for (i = 1; i <= 2; ++i) {
-                    if (ptr + i >= patternEnd || ptr[i] < '0' || ptr[i] > '7')
-                        break;
-                    int cc = c * 8 + ptr[i] - '0';
-                    if (cc > 255)
-                        break;
-                    c = cc;
-                }
-                ptr += i - 1;
-                break;
-            }
-
-            case 'x': {
-                c = 0;
-                int i;
-                for (i = 1; i <= 2; ++i) {
-                    if (ptr + i >= patternEnd || !isASCIIHexDigit(ptr[i])) {
-                        c = 'x';
-                        i = 1;
-                        break;
-                    }
-                    int cc = ptr[i];
-                    if (cc >= 'a')
-                        cc -= 32;             /* Convert to upper case */
-                    c = c * 16 + cc - ((cc < 'A') ? '0' : ('A' - 10));
-                }
-                ptr += i - 1;
-                break;
-            }
-
-            case 'u': {
-                c = 0;
-                int i;
-                for (i = 1; i <= 4; ++i) {
-                    if (ptr + i >= patternEnd || !isASCIIHexDigit(ptr[i])) {
-                        c = 'u';
-                        i = 1;
-                        break;
-                    }
-                    int cc = ptr[i];
-                    if (cc >= 'a')
-                        cc -= 32;             /* Convert to upper case */
-                    c = c * 16 + cc - ((cc < 'A') ? '0' : ('A' - 10));
-                }
-                ptr += i - 1;
-                break;
-            }
-
-            case 'c':
-                if (++ptr == patternEnd) {
-                    *errorCodePtr = ERR2;
-                    return 0;
-                }
-                
-                c = *ptr;
-
-                /* To match Firefox, inside a character class, we also accept
-                   numbers and '_' as control characters */
-                if ((!isClass && !isASCIIAlpha(c)) || (!isASCIIAlphanumeric(c) && c != '_')) {
-                    c = '\\';
-                    ptr -= 2;
-                    break;
-                }
-
-                /* A letter is upper-cased; then the 0x40 bit is flipped. This coding
-                 is ASCII-specific, but then the whole concept of \cx is ASCII-specific. */
-                c = toASCIIUpper(c) ^ 0x40;
-                break;
-            }
-    }
-    
-    *ptrPtr = ptr;
-    return c;
-}
-
-/*************************************************
-*            Check for counted repeat            *
-*************************************************/
-
-/* This function is called when a '{' is encountered in a place where it might
-start a quantifier. It looks ahead to see if it really is a quantifier or not.
-It is only a quantifier if it is one of the forms {ddd} {ddd,} or {ddd,ddd}
-where the ddds are digits.
-
-Arguments:
-  p         pointer to the first char after '{'
-
-Returns:    true or false
-*/
-
-static bool isCountedRepeat(const UChar* p, const UChar* patternEnd)
-{
-    if (p >= patternEnd || !isASCIIDigit(*p))
-        return false;
-    p++;
-    while (p < patternEnd && isASCIIDigit(*p))
-        p++;
-    if (p < patternEnd && *p == '}')
-        return true;
-    
-    if (p >= patternEnd || *p++ != ',')
-        return false;
-    if (p < patternEnd && *p == '}')
-        return true;
-    
-    if (p >= patternEnd || !isASCIIDigit(*p))
-        return false;
-    p++;
-    while (p < patternEnd && isASCIIDigit(*p))
-        p++;
-    
-    return (p < patternEnd && *p == '}');
-}
-
-/*************************************************
-*         Read repeat counts                     *
-*************************************************/
-
-/* Read an item of the form {n,m} and return the values. This is called only
-after isCountedRepeat() has confirmed that a repeat-count quantifier exists,
-so the syntax is guaranteed to be correct, but we need to check the values.
-
-Arguments:
-  p              pointer to first char after '{'
-  minp           pointer to int for min
-  maxp           pointer to int for max
-                 returned as -1 if no max
-  errorCodePtr   points to error code variable
-
-Returns:         pointer to '}' on success;
-                 current ptr on error, with errorCodePtr set non-zero
-*/
-
-static const UChar* readRepeatCounts(const UChar* p, int* minp, int* maxp, ErrorCode* errorCodePtr)
-{
-    int min = 0;
-    int max = -1;
-    
-    /* Read the minimum value and do a paranoid check: a negative value indicates
-     an integer overflow. */
-    
-    while (isASCIIDigit(*p))
-        min = min * 10 + *p++ - '0';
-    if (min < 0 || min > 65535) {
-        *errorCodePtr = ERR5;
-        return p;
-    }
-    
-    /* Read the maximum value if there is one, and again do a paranoid on its size.
-     Also, max must not be less than min. */
-    
-    if (*p == '}')
-        max = min;
-    else {
-        if (*(++p) != '}') {
-            max = 0;
-            while (isASCIIDigit(*p))
-                max = max * 10 + *p++ - '0';
-            if (max < 0 || max > 65535) {
-                *errorCodePtr = ERR5;
-                return p;
-            }
-            if (max < min) {
-                *errorCodePtr = ERR4;
-                return p;
-            }
-        }
-    }
-    
-    /* Fill in the required variables, and pass back the pointer to the terminating
-     '}'. */
-    
-    *minp = min;
-    *maxp = max;
-    return p;
-}
-
-/*************************************************
-*      Find first significant op code            *
-*************************************************/
-
-/* This is called by several functions that scan a compiled expression looking
-for a fixed first character, or an anchoring op code etc. It skips over things
-that do not influence this.
-
-Arguments:
-  code         pointer to the start of the group
-Returns:       pointer to the first significant opcode
-*/
-
-static const unsigned char* firstSignificantOpcode(const unsigned char* code)
-{
-    while (*code == OP_BRANUMBER)
-        code += 3;
-    return code;
-}
-
-static const unsigned char* firstSignificantOpcodeSkippingAssertions(const unsigned char* code)
-{
-    while (true) {
-        switch (*code) {
-            case OP_ASSERT_NOT:
-                advanceToEndOfBracket(code);
-                code += 1 + LINK_SIZE;
-                break;
-            case OP_WORD_BOUNDARY:
-            case OP_NOT_WORD_BOUNDARY:
-                ++code;
-                break;
-            case OP_BRANUMBER:
-                code += 3;
-                break;
-            default:
-                return code;
-        }
-    }
-}
-
-/*************************************************
-*           Get othercase range                  *
-*************************************************/
-
-/* This function is passed the start and end of a class range, in UTF-8 mode
-with UCP support. It searches up the characters, looking for internal ranges of
-characters in the "other" case. Each call returns the next one, updating the
-start address.
-
-Arguments:
-  cptr        points to starting character value; updated
-  d           end value
-  ocptr       where to put start of othercase range
-  odptr       where to put end of othercase range
-
-Yield:        true when range returned; false when no more
-*/
-
-static bool getOthercaseRange(int* cptr, int d, int* ocptr, int* odptr)
-{
-    int c, othercase = 0;
-    
-    for (c = *cptr; c <= d; c++) {
-        if ((othercase = jsc_pcre_ucp_othercase(c)) >= 0)
-            break;
-    }
-    
-    if (c > d)
-        return false;
-    
-    *ocptr = othercase;
-    int next = othercase + 1;
-    
-    for (++c; c <= d; c++) {
-        if (jsc_pcre_ucp_othercase(c) != next)
-            break;
-        next++;
-    }
-    
-    *odptr = next - 1;
-    *cptr = c;
-    
-    return true;
-}
-
-/*************************************************
- *       Convert character value to UTF-8         *
- *************************************************/
-
-/* This function takes an integer value in the range 0 - 0x7fffffff
- and encodes it as a UTF-8 character in 0 to 6 bytes.
- Arguments:
- cvalue     the character value
- buffer     pointer to buffer for result - at least 6 bytes long
- Returns:     number of characters placed in the buffer
- */
-
-static int encodeUTF8(int cvalue, unsigned char *buffer)
-{
-    int i;
-    for (i = 0; i < jsc_pcre_utf8_table1_size; i++)
-        if (cvalue <= jsc_pcre_utf8_table1[i])
-            break;
-    buffer += i;
-    for (int j = i; j > 0; j--) {
-        *buffer-- = 0x80 | (cvalue & 0x3f);
-        cvalue >>= 6;
-    }
-    *buffer = jsc_pcre_utf8_table2[i] | cvalue;
-    return i + 1;
-}
-
-/*************************************************
-*           Compile one branch                   *
-*************************************************/
-
-/* Scan the pattern, compiling it into the code vector.
-
-Arguments:
-  options        the option bits
-  brackets       points to number of extracting brackets used
-  codePtr        points to the pointer to the current code point
-  ptrPtr         points to the current pattern pointer
-  errorCodePtr   points to error code variable
-  firstbyteptr   set to initial literal character, or < 0 (REQ_UNSET, REQ_NONE)
-  reqbyteptr     set to the last literal character required, else < 0
-  cd             contains pointers to tables etc.
-
-Returns:         true on success
-                 false, with *errorCodePtr set non-zero on error
-*/
-
-static inline bool safelyCheckNextChar(const UChar* ptr, const UChar* patternEnd, UChar expected)
-{
-    return ((ptr + 1 < patternEnd) && ptr[1] == expected);
-}
-
-static bool
-compileBranch(int options, int* brackets, unsigned char** codePtr,
-               const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* errorCodePtr, int *firstbyteptr,
-               int* reqbyteptr, CompileData& cd)
-{
-    int repeatType, opType;
-    int repeatMin = 0, repeat_max = 0;      /* To please picky compilers */
-    int bravalue = 0;
-    int reqvary, tempreqvary;
-    int c;
-    unsigned char* code = *codePtr;
-    unsigned char* tempcode;
-    bool didGroupSetFirstByte = false;
-    const UChar* ptr = *ptrPtr;
-    const UChar* tempptr;
-    unsigned char* previous = NULL;
-    unsigned char classbits[32];
-    
-    bool class_utf8;
-    unsigned char* class_utf8data;
-    unsigned char utf8_char[6];
-    
-    /* Initialize no first byte, no required byte. REQ_UNSET means "no char
-     matching encountered yet". It gets changed to REQ_NONE if we hit something that
-     matches a non-fixed char first char; reqByte just remains unset if we never
-     find one.
-     
-     When we hit a repeat whose minimum is zero, we may have to adjust these values
-     to take the zero repeat into account. This is implemented by setting them to
-     zeroFirstByte and zeroReqByte when such a repeat is encountered. The individual
-     item types that can be repeated set these backoff variables appropriately. */
-    
-    int firstByte = REQ_UNSET;
-    int reqByte = REQ_UNSET;
-    int zeroReqByte = REQ_UNSET;
-    int zeroFirstByte = REQ_UNSET;
-    
-    /* The variable reqCaseOpt contains either the REQ_IGNORE_CASE value or zero,
-     according to the current setting of the ignores-case flag. REQ_IGNORE_CASE is a bit
-     value > 255. It is added into the firstByte or reqByte variables to record the
-     case status of the value. This is used only for ASCII characters. */
-    
-    int reqCaseOpt = (options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0;
-    
-    /* Switch on next character until the end of the branch */
-    
-    for (;; ptr++) {
-        bool negateClass;
-        bool shouldFlipNegation; /* If a negative special such as \S is used, we should negate the whole class to properly support Unicode. */
-        int classCharCount;
-        int classLastChar;
-        int skipBytes;
-        int subReqByte;
-        int subFirstByte;
-        int mcLength;
-        unsigned char mcbuffer[8];
-        
-        /* Next byte in the pattern */
-        
-        c = ptr < patternEnd ? *ptr : 0;
-        
-        /* Fill in length of a previous callout, except when the next thing is
-         a quantifier. */
-        
-        bool isQuantifier = c == '*' || c == '+' || c == '?' || (c == '{' && isCountedRepeat(ptr + 1, patternEnd));
-        
-        switch (c) {
-            /* The branch terminates at end of string, |, or ). */
-                
-            case 0:
-                if (ptr < patternEnd)
-                    goto NORMAL_CHAR;
-                // End of string; fall through
-            case '|':
-            case ')':
-                *firstbyteptr = firstByte;
-                *reqbyteptr = reqByte;
-                *codePtr = code;
-                *ptrPtr = ptr;
-                return true;
-                
-            /* Handle single-character metacharacters. In multiline mode, ^ disables
-             the setting of any following char as a first character. */
-
-            case '^':
-                if (options & MatchAcrossMultipleLinesOption) {
-                    if (firstByte == REQ_UNSET)
-                        firstByte = REQ_NONE;
-                    *code++ = OP_BOL;
-                } else
-                    *code++ = OP_CIRC;
-                previous = NULL;
-                break;
-
-            case '$':
-                previous = NULL;
-                if (options & MatchAcrossMultipleLinesOption)
-                  *code++ = OP_EOL;
-                else
-                  *code++ = OP_DOLL;
-                break;
-
-            /* There can never be a first char if '.' is first, whatever happens about
-             repeats. The value of reqByte doesn't change either. */
-
-            case '.':
-                if (firstByte == REQ_UNSET)
-                    firstByte = REQ_NONE;
-                zeroFirstByte = firstByte;
-                zeroReqByte = reqByte;
-                previous = code;
-                *code++ = OP_NOT_NEWLINE;
-                break;
-                
-            /* Character classes. If the included characters are all < 256, we build a
-             32-byte bitmap of the permitted characters, except in the special case
-             where there is only one such character. For negated classes, we build the
-             map as usual, then invert it at the end. However, we use a different opcode
-             so that data characters > 255 can be handled correctly.
-             
-             If the class contains characters outside the 0-255 range, a different
-             opcode is compiled. It may optionally have a bit map for characters < 256,
-             but those above are are explicitly listed afterwards. A flag byte tells
-             whether the bitmap is present, and whether this is a negated class or not.
-             */
-                
-            case '[': {
-                previous = code;
-                shouldFlipNegation = false;
-                
-                /* PCRE supports POSIX class stuff inside a class. Perl gives an error if
-                 they are encountered at the top level, so we'll do that too. */
-                
-                /* If the first character is '^', set the negation flag and skip it. */
-
-                if (ptr + 1 >= patternEnd) {
-                    *errorCodePtr = ERR6;
-                    return false;
-                }
-
-                if (ptr[1] == '^') {
-                    negateClass = true;
-                    ++ptr;
-                } else
-                    negateClass = false;
-                
-                /* Keep a count of chars with values < 256 so that we can optimize the case
-                 of just a single character (as long as it's < 256). For higher valued UTF-8
-                 characters, we don't yet do any optimization. */
-                
-                classCharCount = 0;
-                classLastChar = -1;
-                
-                class_utf8 = false;                       /* No chars >= 256 */
-                class_utf8data = code + LINK_SIZE + 34;   /* For UTF-8 items */
-                
-                /* Initialize the 32-char bit map to all zeros. We have to build the
-                 map in a temporary bit of store, in case the class contains only 1
-                 character (< 256), because in that case the compiled code doesn't use the
-                 bit map. */
-                
-                memset(classbits, 0, 32 * sizeof(unsigned char));
-                
-                /* Process characters until ] is reached. The first pass
-                 through the regex checked the overall syntax, so we don't need to be very
-                 strict here. At the start of the loop, c contains the first byte of the
-                 character. */
-
-                while ((++ptr < patternEnd) && (c = *ptr) != ']') {
-                    /* Backslash may introduce a single character, or it may introduce one
-                     of the specials, which just set a flag. Escaped items are checked for
-                     validity in the pre-compiling pass. The sequence \b is a special case.
-                     Inside a class (and only there) it is treated as backspace. Elsewhere
-                     it marks a word boundary. Other escapes have preset maps ready to
-                     or into the one we are building. We assume they have more than one
-                     character in them, so set classCharCount bigger than one. */
-                    
-                    if (c == '\\') {
-                        c = checkEscape(&ptr, patternEnd, errorCodePtr, cd.numCapturingBrackets, true);
-                        if (c < 0) {
-                            classCharCount += 2;     /* Greater than 1 is what matters */
-                            switch (-c) {
-                                case ESC_d:
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= classBitmapForChar(c + cbit_digit);
-                                    continue;
-                                    
-                                case ESC_D:
-                                    shouldFlipNegation = true;
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= ~classBitmapForChar(c + cbit_digit);
-                                    continue;
-                                    
-                                case ESC_w:
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= classBitmapForChar(c + cbit_word);
-                                    continue;
-                                    
-                                case ESC_W:
-                                    shouldFlipNegation = true;
-                                    for (c = 0; c < 32; c++)
-                                        classbits[c] |= ~classBitmapForChar(c + cbit_word);
-                                    continue;
-                                    
-                                case ESC_s:
-                                    for (c = 0; c < 32; c++)
-                                         classbits[c] |= classBitmapForChar(c + cbit_space);
-                                    continue;
-                                    
-                                case ESC_S:
-                                    shouldFlipNegation = true;
-                                    for (c = 0; c < 32; c++)
-                                         classbits[c] |= ~classBitmapForChar(c + cbit_space);
-                                    continue;
-                                    
-                                    /* Unrecognized escapes are faulted if PCRE is running in its
-                                     strict mode. By default, for compatibility with Perl, they are
-                                     treated as literals. */
-                                    
-                                default:
-                                    c = *ptr;              /* The final character */
-                                    classCharCount -= 2;  /* Undo the default count from above */
-                            }
-                        }
-                        
-                        /* Fall through if we have a single character (c >= 0). This may be
-                         > 256 in UTF-8 mode. */
-                        
-                    }   /* End of backslash handling */
-                    
-                    /* A single character may be followed by '-' to form a range. However,
-                     Perl does not permit ']' to be the end of the range. A '-' character
-                     here is treated as a literal. */
-                    
-                    if ((ptr + 2 < patternEnd) && ptr[1] == '-' && ptr[2] != ']') {
-                        ptr += 2;
-                        
-                        int d = *ptr;
-                        
-                        /* The second part of a range can be a single-character escape, but
-                         not any of the other escapes. Perl 5.6 treats a hyphen as a literal
-                         in such circumstances. */
-                        
-                        if (d == '\\') {
-                            const UChar* oldptr = ptr;
-                            d = checkEscape(&ptr, patternEnd, errorCodePtr, cd.numCapturingBrackets, true);
-                            
-                            /* \X is literal X; any other special means the '-' was literal */
-                            if (d < 0) {
-                                ptr = oldptr - 2;
-                                goto LONE_SINGLE_CHARACTER;  /* A few lines below */
-                            }
-                        }
-                        
-                        /* The check that the two values are in the correct order happens in
-                         the pre-pass. Optimize one-character ranges */
-                        
-                        if (d == c)
-                            goto LONE_SINGLE_CHARACTER;  /* A few lines below */
-                        
-                        /* In UTF-8 mode, if the upper limit is > 255, or > 127 for caseless
-                         matching, we have to use an XCLASS with extra data items. Caseless
-                         matching for characters > 127 is available only if UCP support is
-                         available. */
-                        
-                        if ((d > 255 || ((options & IgnoreCaseOption) && d > 127))) {
-                            class_utf8 = true;
-                            
-                            /* With UCP support, we can find the other case equivalents of
-                             the relevant characters. There may be several ranges. Optimize how
-                             they fit with the basic range. */
-                            
-                            if (options & IgnoreCaseOption) {
-                                int occ, ocd;
-                                int cc = c;
-                                int origd = d;
-                                while (getOthercaseRange(&cc, origd, &occ, &ocd)) {
-                                    if (occ >= c && ocd <= d)
-                                        continue;  /* Skip embedded ranges */
-                                    
-                                    if (occ < c  && ocd >= c - 1)        /* Extend the basic range */
-                                    {                                  /* if there is overlap,   */
-                                        c = occ;                           /* noting that if occ < c */
-                                        continue;                          /* we can't have ocd > d  */
-                                    }                                  /* because a subrange is  */
-                                    if (ocd > d && occ <= d + 1)         /* always shorter than    */
-                                    {                                  /* the basic range.       */
-                                        d = ocd;
-                                        continue;
-                                    }
-                                    
-                                    if (occ == ocd)
-                                        *class_utf8data++ = XCL_SINGLE;
-                                    else {
-                                        *class_utf8data++ = XCL_RANGE;
-                                        class_utf8data += encodeUTF8(occ, class_utf8data);
-                                    }
-                                    class_utf8data += encodeUTF8(ocd, class_utf8data);
-                                }
-                            }
-                            
-                            /* Now record the original range, possibly modified for UCP caseless
-                             overlapping ranges. */
-                            
-                            *class_utf8data++ = XCL_RANGE;
-                            class_utf8data += encodeUTF8(c, class_utf8data);
-                            class_utf8data += encodeUTF8(d, class_utf8data);
-                            
-                            /* With UCP support, we are done. Without UCP support, there is no
-                             caseless matching for UTF-8 characters > 127; we can use the bit map
-                             for the smaller ones. */
-                            
-                            continue;    /* With next character in the class */
-                        }
-                        
-                        /* We use the bit map for all cases when not in UTF-8 mode; else
-                         ranges that lie entirely within 0-127 when there is UCP support; else
-                         for partial ranges without UCP support. */
-                        
-                        for (; c <= d; c++) {
-                            classbits[c/8] |= (1 << (c&7));
-                            if (options & IgnoreCaseOption) {
-                                int uc = flipCase(c);
-                                classbits[uc/8] |= (1 << (uc&7));
-                            }
-                            classCharCount++;                /* in case a one-char range */
-                            classLastChar = c;
-                        }
-                        
-                        continue;   /* Go get the next char in the class */
-                    }
-                    
-                    /* Handle a lone single character - we can get here for a normal
-                     non-escape char, or after \ that introduces a single character or for an
-                     apparent range that isn't. */
-                    
-                LONE_SINGLE_CHARACTER:
-                    
-                    /* Handle a character that cannot go in the bit map */
-                    
-                    if ((c > 255 || ((options & IgnoreCaseOption) && c > 127))) {
-                        class_utf8 = true;
-                        *class_utf8data++ = XCL_SINGLE;
-                        class_utf8data += encodeUTF8(c, class_utf8data);
-                        
-                        if (options & IgnoreCaseOption) {
-                            int othercase;
-                            if ((othercase = jsc_pcre_ucp_othercase(c)) >= 0) {
-                                *class_utf8data++ = XCL_SINGLE;
-                                class_utf8data += encodeUTF8(othercase, class_utf8data);
-                            }
-                        }
-                    } else {
-                        /* Handle a single-byte character */
-                        classbits[c/8] |= (1 << (c&7));
-                        if (options & IgnoreCaseOption) {
-                            c = flipCase(c);
-                            classbits[c/8] |= (1 << (c&7));
-                        }
-                        classCharCount++;
-                        classLastChar = c;
-                    }
-                }
-                
-                /* If classCharCount is 1, we saw precisely one character whose value is
-                 less than 256. In non-UTF-8 mode we can always optimize. In UTF-8 mode, we
-                 can optimize the negative case only if there were no characters >= 128
-                 because OP_NOT and the related opcodes like OP_NOTSTAR operate on
-                 single-bytes only. This is an historical hangover. Maybe one day we can
-                 tidy these opcodes to handle multi-byte characters.
-                 
-                 The optimization throws away the bit map. We turn the item into a
-                 1-character OP_CHAR[NC] if it's positive, or OP_NOT if it's negative. Note
-                 that OP_NOT does not support multibyte characters. In the positive case, it
-                 can cause firstByte to be set. Otherwise, there can be no first char if
-                 this item is first, whatever repeat count may follow. In the case of
-                 reqByte, save the previous value for reinstating. */
-                
-                if (classCharCount == 1 && (!class_utf8 && (!negateClass || classLastChar < 128))) {
-                    zeroReqByte = reqByte;
-                    
-                    /* The OP_NOT opcode works on one-byte characters only. */
-                    
-                    if (negateClass) {
-                        if (firstByte == REQ_UNSET)
-                            firstByte = REQ_NONE;
-                        zeroFirstByte = firstByte;
-                        *code++ = OP_NOT;
-                        *code++ = classLastChar;
-                        break;
-                    }
-                    
-                    /* For a single, positive character, get the value into c, and
-                     then we can handle this with the normal one-character code. */
-                    
-                    c = classLastChar;
-                    goto NORMAL_CHAR;
-                }       /* End of 1-char optimization */
-                
-                /* The general case - not the one-char optimization. If this is the first
-                 thing in the branch, there can be no first char setting, whatever the
-                 repeat count. Any reqByte setting must remain unchanged after any kind of
-                 repeat. */
-                
-                if (firstByte == REQ_UNSET) firstByte = REQ_NONE;
-                zeroFirstByte = firstByte;
-                zeroReqByte = reqByte;
-                
-                /* If there are characters with values > 255, we have to compile an
-                 extended class, with its own opcode. If there are no characters < 256,
-                 we can omit the bitmap. */
-                
-                if (class_utf8 && !shouldFlipNegation) {
-                    *class_utf8data++ = XCL_END;    /* Marks the end of extra data */
-                    *code++ = OP_XCLASS;
-                    code += LINK_SIZE;
-                    *code = negateClass? XCL_NOT : 0;
-                    
-                    /* If the map is required, install it, and move on to the end of
-                     the extra data */
-                    
-                    if (classCharCount > 0) {
-                        *code++ |= XCL_MAP;
-                        memcpy(code, classbits, 32);
-                        code = class_utf8data;
-                    }
-                    
-                    /* If the map is not required, slide down the extra data. */
-                    
-                    else {
-                        int len = class_utf8data - (code + 33);
-                        memmove(code + 1, code + 33, len);
-                        code += len + 1;
-                    }
-                    
-                    /* Now fill in the complete length of the item */
-                    
-                    putLinkValue(previous + 1, code - previous);
-                    break;   /* End of class handling */
-                }
-                
-                /* If there are no characters > 255, negate the 32-byte map if necessary,
-                 and copy it into the code vector. If this is the first thing in the branch,
-                 there can be no first char setting, whatever the repeat count. Any reqByte
-                 setting must remain unchanged after any kind of repeat. */
-                
-                *code++ = (negateClass == shouldFlipNegation) ? OP_CLASS : OP_NCLASS;
-                if (negateClass)
-                    for (c = 0; c < 32; c++)
-                        code[c] = ~classbits[c];
-                else
-                    memcpy(code, classbits, 32);
-                code += 32;
-                break;
-            }
-                
-            /* Various kinds of repeat; '{' is not necessarily a quantifier, but this
-             has been tested above. */
-
-            case '{':
-                if (!isQuantifier)
-                    goto NORMAL_CHAR;
-                ptr = readRepeatCounts(ptr + 1, &repeatMin, &repeat_max, errorCodePtr);
-                if (*errorCodePtr)
-                    goto FAILED;
-                goto REPEAT;
-                
-            case '*':
-                repeatMin = 0;
-                repeat_max = -1;
-                goto REPEAT;
-                
-            case '+':
-                repeatMin = 1;
-                repeat_max = -1;
-                goto REPEAT;
-                
-            case '?':
-                repeatMin = 0;
-                repeat_max = 1;
-                
-            REPEAT:
-                if (!previous) {
-                    *errorCodePtr = ERR9;
-                    goto FAILED;
-                }
-                
-                if (repeatMin == 0) {
-                    firstByte = zeroFirstByte;    /* Adjust for zero repeat */
-                    reqByte = zeroReqByte;        /* Ditto */
-                }
-                
-                /* Remember whether this is a variable length repeat */
-                
-                reqvary = (repeatMin == repeat_max) ? 0 : REQ_VARY;
-                
-                opType = 0;                    /* Default single-char op codes */
-                
-                /* Save start of previous item, in case we have to move it up to make space
-                 for an inserted OP_ONCE for the additional '+' extension. */
-                /* FIXME: Probably don't need this because we don't use OP_ONCE. */
-                
-                tempcode = previous;
-                
-                /* If the next character is '+', we have a possessive quantifier. This
-                 implies greediness, whatever the setting of the PCRE_UNGREEDY option.
-                 If the next character is '?' this is a minimizing repeat, by default,
-                 but if PCRE_UNGREEDY is set, it works the other way round. We change the
-                 repeat type to the non-default. */
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '?')) {
-                    repeatType = 1;
-                    ptr++;
-                } else
-                    repeatType = 0;
-                
-                /* If previous was a character match, abolish the item and generate a
-                 repeat item instead. If a char item has a minumum of more than one, ensure
-                 that it is set in reqByte - it might not be if a sequence such as x{3} is
-                 the first thing in a branch because the x will have gone into firstByte
-                 instead.  */
-                
-                if (*previous == OP_CHAR || *previous == OP_CHAR_IGNORING_CASE) {
-                    /* Deal with UTF-8 characters that take up more than one byte. It's
-                     easier to write this out separately than try to macrify it. Use c to
-                     hold the length of the character in bytes, plus 0x80 to flag that it's a
-                     length rather than a small character. */
-                    
-                    if (code[-1] & 0x80) {
-                        unsigned char *lastchar = code - 1;
-                        while((*lastchar & 0xc0) == 0x80)
-                            lastchar--;
-                        c = code - lastchar;            /* Length of UTF-8 character */
-                        memcpy(utf8_char, lastchar, c); /* Save the char */
-                        c |= 0x80;                      /* Flag c as a length */
-                    }
-                    else {
-                        c = code[-1];
-                        if (repeatMin > 1)
-                            reqByte = c | reqCaseOpt | cd.reqVaryOpt;
-                    }
-                    
-                    goto OUTPUT_SINGLE_REPEAT;   /* Code shared with single character types */
-                }
-                
-                else if (*previous == OP_ASCII_CHAR || *previous == OP_ASCII_LETTER_IGNORING_CASE) {
-                    c = previous[1];
-                    if (repeatMin > 1)
-                        reqByte = c | reqCaseOpt | cd.reqVaryOpt;
-                    goto OUTPUT_SINGLE_REPEAT;
-                }
-                
-                /* If previous was a single negated character ([^a] or similar), we use
-                 one of the special opcodes, replacing it. The code is shared with single-
-                 character repeats by setting opt_type to add a suitable offset into
-                 repeatType. OP_NOT is currently used only for single-byte chars. */
-                
-                else if (*previous == OP_NOT) {
-                    opType = OP_NOTSTAR - OP_STAR;  /* Use "not" opcodes */
-                    c = previous[1];
-                    goto OUTPUT_SINGLE_REPEAT;
-                }
-                
-                /* If previous was a character type match (\d or similar), abolish it and
-                 create a suitable repeat item. The code is shared with single-character
-                 repeats by setting opType to add a suitable offset into repeatType. */
-                
-                else if (*previous <= OP_NOT_NEWLINE) {
-                    opType = OP_TYPESTAR - OP_STAR;  /* Use type opcodes */
-                    c = *previous;
-                    
-                OUTPUT_SINGLE_REPEAT:
-                    int prop_type = -1;
-                    int prop_value = -1;
-                    
-                    unsigned char* oldcode = code;
-                    code = previous;                  /* Usually overwrite previous item */
-                    
-                    /* If the maximum is zero then the minimum must also be zero; Perl allows
-                     this case, so we do too - by simply omitting the item altogether. */
-                    
-                    if (repeat_max == 0)
-                        goto END_REPEAT;
-                    
-                    /* Combine the opType with the repeatType */
-                    
-                    repeatType += opType;
-                    
-                    /* A minimum of zero is handled either as the special case * or ?, or as
-                     an UPTO, with the maximum given. */
-                    
-                    if (repeatMin == 0) {
-                        if (repeat_max == -1)
-                            *code++ = OP_STAR + repeatType;
-                        else if (repeat_max == 1)
-                            *code++ = OP_QUERY + repeatType;
-                        else {
-                            *code++ = OP_UPTO + repeatType;
-                            put2ByteValueAndAdvance(code, repeat_max);
-                        }
-                    }
-                    
-                    /* A repeat minimum of 1 is optimized into some special cases. If the
-                     maximum is unlimited, we use OP_PLUS. Otherwise, the original item it
-                     left in place and, if the maximum is greater than 1, we use OP_UPTO with
-                     one less than the maximum. */
-                    
-                    else if (repeatMin == 1) {
-                        if (repeat_max == -1)
-                            *code++ = OP_PLUS + repeatType;
-                        else {
-                            code = oldcode;                 /* leave previous item in place */
-                            if (repeat_max == 1)
-                                goto END_REPEAT;
-                            *code++ = OP_UPTO + repeatType;
-                            put2ByteValueAndAdvance(code, repeat_max - 1);
-                        }
-                    }
-                    
-                    /* The case {n,n} is just an EXACT, while the general case {n,m} is
-                     handled as an EXACT followed by an UPTO. */
-                    
-                    else {
-                        *code++ = OP_EXACT + opType;  /* NB EXACT doesn't have repeatType */
-                        put2ByteValueAndAdvance(code, repeatMin);
-                        
-                        /* If the maximum is unlimited, insert an OP_STAR. Before doing so,
-                         we have to insert the character for the previous code. For a repeated
-                         Unicode property match, there are two extra bytes that define the
-                         required property. In UTF-8 mode, long characters have their length in
-                         c, with the 0x80 bit as a flag. */
-                        
-                        if (repeat_max < 0) {
-                            if (c >= 128) {
-                                memcpy(code, utf8_char, c & 7);
-                                code += c & 7;
-                            } else {
-                                *code++ = c;
-                                if (prop_type >= 0) {
-                                    *code++ = prop_type;
-                                    *code++ = prop_value;
-                                }
-                            }
-                            *code++ = OP_STAR + repeatType;
-                        }
-                        
-                        /* Else insert an UPTO if the max is greater than the min, again
-                         preceded by the character, for the previously inserted code. */
-                        
-                        else if (repeat_max != repeatMin) {
-                            if (c >= 128) {
-                                memcpy(code, utf8_char, c & 7);
-                                code += c & 7;
-                            } else
-                                *code++ = c;
-                            if (prop_type >= 0) {
-                                *code++ = prop_type;
-                                *code++ = prop_value;
-                            }
-                            repeat_max -= repeatMin;
-                            *code++ = OP_UPTO + repeatType;
-                            put2ByteValueAndAdvance(code, repeat_max);
-                        }
-                    }
-                    
-                    /* The character or character type itself comes last in all cases. */
-                    
-                    if (c >= 128) {
-                        memcpy(code, utf8_char, c & 7);
-                        code += c & 7;
-                    } else
-                        *code++ = c;
-                    
-                    /* For a repeated Unicode property match, there are two extra bytes that
-                     define the required property. */
-                    
-                    if (prop_type >= 0) {
-                        *code++ = prop_type;
-                        *code++ = prop_value;
-                    }
-                }
-                
-                /* If previous was a character class or a back reference, we put the repeat
-                 stuff after it, but just skip the item if the repeat was {0,0}. */
-                
-                else if (*previous == OP_CLASS ||
-                         *previous == OP_NCLASS ||
-                         *previous == OP_XCLASS ||
-                         *previous == OP_REF)
-                {
-                    if (repeat_max == 0) {
-                        code = previous;
-                        goto END_REPEAT;
-                    }
-                    
-                    if (repeatMin == 0 && repeat_max == -1)
-                        *code++ = OP_CRSTAR + repeatType;
-                    else if (repeatMin == 1 && repeat_max == -1)
-                        *code++ = OP_CRPLUS + repeatType;
-                    else if (repeatMin == 0 && repeat_max == 1)
-                        *code++ = OP_CRQUERY + repeatType;
-                    else {
-                        *code++ = OP_CRRANGE + repeatType;
-                        put2ByteValueAndAdvance(code, repeatMin);
-                        if (repeat_max == -1)
-                            repeat_max = 0;  /* 2-byte encoding for max */
-                        put2ByteValueAndAdvance(code, repeat_max);
-                    }
-                }
-                
-                /* If previous was a bracket group, we may have to replicate it in certain
-                 cases. */
-                
-                else if (*previous >= OP_BRA) {
-                    int ketoffset = 0;
-                    int len = code - previous;
-                    unsigned char* bralink = NULL;
-                    
-                    /* If the maximum repeat count is unlimited, find the end of the bracket
-                     by scanning through from the start, and compute the offset back to it
-                     from the current code pointer. There may be an OP_OPT setting following
-                     the final KET, so we can't find the end just by going back from the code
-                     pointer. */
-                    
-                    if (repeat_max == -1) {
-                        const unsigned char* ket = previous;
-                        advanceToEndOfBracket(ket);
-                        ketoffset = code - ket;
-                    }
-                    
-                    /* The case of a zero minimum is special because of the need to stick
-                     OP_BRAZERO in front of it, and because the group appears once in the
-                     data, whereas in other cases it appears the minimum number of times. For
-                     this reason, it is simplest to treat this case separately, as otherwise
-                     the code gets far too messy. There are several special subcases when the
-                     minimum is zero. */
-                    
-                    if (repeatMin == 0) {
-                        /* If the maximum is also zero, we just omit the group from the output
-                         altogether. */
-                        
-                        if (repeat_max == 0) {
-                            code = previous;
-                            goto END_REPEAT;
-                        }
-                        
-                        /* If the maximum is 1 or unlimited, we just have to stick in the
-                         BRAZERO and do no more at this point. However, we do need to adjust
-                         any OP_RECURSE calls inside the group that refer to the group itself or
-                         any internal group, because the offset is from the start of the whole
-                         regex. Temporarily terminate the pattern while doing this. */
-                        
-                        if (repeat_max <= 1) {
-                            *code = OP_END;
-                            memmove(previous+1, previous, len);
-                            code++;
-                            *previous++ = OP_BRAZERO + repeatType;
-                        }
-                        
-                        /* If the maximum is greater than 1 and limited, we have to replicate
-                         in a nested fashion, sticking OP_BRAZERO before each set of brackets.
-                         The first one has to be handled carefully because it's the original
-                         copy, which has to be moved up. The remainder can be handled by code
-                         that is common with the non-zero minimum case below. We have to
-                         adjust the value of repeat_max, since one less copy is required. */
-                        
-                        else {
-                            *code = OP_END;
-                            memmove(previous + 2 + LINK_SIZE, previous, len);
-                            code += 2 + LINK_SIZE;
-                            *previous++ = OP_BRAZERO + repeatType;
-                            *previous++ = OP_BRA;
-                            
-                            /* We chain together the bracket offset fields that have to be
-                             filled in later when the ends of the brackets are reached. */
-                            
-                            int offset = (!bralink) ? 0 : previous - bralink;
-                            bralink = previous;
-                            putLinkValueAllowZeroAndAdvance(previous, offset);
-                        }
-                        
-                        repeat_max--;
-                    }
-                    
-                    /* If the minimum is greater than zero, replicate the group as many
-                     times as necessary, and adjust the maximum to the number of subsequent
-                     copies that we need. If we set a first char from the group, and didn't
-                     set a required char, copy the latter from the former. */
-                    
-                    else {
-                        if (repeatMin > 1) {
-                            if (didGroupSetFirstByte && reqByte < 0)
-                                reqByte = firstByte;
-                            for (int i = 1; i < repeatMin; i++) {
-                                memcpy(code, previous, len);
-                                code += len;
-                            }
-                        }
-                        if (repeat_max > 0)
-                            repeat_max -= repeatMin;
-                    }
-                    
-                    /* This code is common to both the zero and non-zero minimum cases. If
-                     the maximum is limited, it replicates the group in a nested fashion,
-                     remembering the bracket starts on a stack. In the case of a zero minimum,
-                     the first one was set up above. In all cases the repeat_max now specifies
-                     the number of additional copies needed. */
-                    
-                    if (repeat_max >= 0) {
-                        for (int i = repeat_max - 1; i >= 0; i--) {
-                            *code++ = OP_BRAZERO + repeatType;
-                            
-                            /* All but the final copy start a new nesting, maintaining the
-                             chain of brackets outstanding. */
-                            
-                            if (i != 0) {
-                                *code++ = OP_BRA;
-                                int offset = (!bralink) ? 0 : code - bralink;
-                                bralink = code;
-                                putLinkValueAllowZeroAndAdvance(code, offset);
-                            }
-                            
-                            memcpy(code, previous, len);
-                            code += len;
-                        }
-                        
-                        /* Now chain through the pending brackets, and fill in their length
-                         fields (which are holding the chain links pro tem). */
-                        
-                        while (bralink) {
-                            int offset = code - bralink + 1;
-                            unsigned char* bra = code - offset;
-                            int oldlinkoffset = getLinkValueAllowZero(bra + 1);
-                            bralink = (!oldlinkoffset) ? 0 : bralink - oldlinkoffset;
-                            *code++ = OP_KET;
-                            putLinkValueAndAdvance(code, offset);
-                            putLinkValue(bra + 1, offset);
-                        }
-                    }
-                    
-                    /* If the maximum is unlimited, set a repeater in the final copy. We
-                     can't just offset backwards from the current code point, because we
-                     don't know if there's been an options resetting after the ket. The
-                     correct offset was computed above. */
-                    
-                    else
-                        code[-ketoffset] = OP_KETRMAX + repeatType;
-                }
-                
-                // A quantifier after an assertion is mostly meaningless, but it
-                // can nullify the assertion if it has a 0 minimum.
-                else if (*previous == OP_ASSERT || *previous == OP_ASSERT_NOT) {
-                    if (repeatMin == 0) {
-                        code = previous;
-                        goto END_REPEAT;
-                    }
-                }
-                
-                /* Else there's some kind of shambles */
-                
-                else {
-                    *errorCodePtr = ERR11;
-                    goto FAILED;
-                }
-                
-                /* In all case we no longer have a previous item. We also set the
-                 "follows varying string" flag for subsequently encountered reqbytes if
-                 it isn't already set and we have just passed a varying length item. */
-                
-            END_REPEAT:
-                previous = NULL;
-                cd.reqVaryOpt |= reqvary;
-                break;
-                
-            /* Start of nested bracket sub-expression, or comment or lookahead or
-             lookbehind or option setting or condition. First deal with special things
-             that can come after a bracket; all are introduced by ?, and the appearance
-             of any of them means that this is not a referencing group. They were
-             checked for validity in the first pass over the string, so we don't have to
-             check for syntax errors here.  */
-                
-            case '(':
-                skipBytes = 0;
-                
-                if (*(++ptr) == '?') {
-                    switch (*(++ptr)) {
-                        case ':':                 /* Non-extracting bracket */
-                            bravalue = OP_BRA;
-                            ptr++;
-                            break;
-                            
-                        case '=':                 /* Positive lookahead */
-                            bravalue = OP_ASSERT;
-                            ptr++;
-                            break;
-                            
-                        case '!':                 /* Negative lookahead */
-                            bravalue = OP_ASSERT_NOT;
-                            ptr++;
-                            break;
-                            
-                        /* Character after (? not specially recognized */
-                            
-                        default:
-                            *errorCodePtr = ERR12;
-                            goto FAILED;
-                        }
-                }
-                
-                /* Else we have a referencing group; adjust the opcode. If the bracket
-                 number is greater than EXTRACT_BASIC_MAX, we set the opcode one higher, and
-                 arrange for the true number to follow later, in an OP_BRANUMBER item. */
-                
-                else {
-                    if (++(*brackets) > EXTRACT_BASIC_MAX) {
-                        bravalue = OP_BRA + EXTRACT_BASIC_MAX + 1;
-                        code[1 + LINK_SIZE] = OP_BRANUMBER;
-                        put2ByteValue(code + 2 + LINK_SIZE, *brackets);
-                        skipBytes = 3;
-                    }
-                    else
-                        bravalue = OP_BRA + *brackets;
-                }
-                
-                /* Process nested bracketed re. We copy code into a non-variable
-                 in order to be able to pass its address because some compilers
-                 complain otherwise. Pass in a new setting for the ims options
-                 if they have changed. */
-                
-                previous = code;
-                *code = bravalue;
-                tempcode = code;
-                tempreqvary = cd.reqVaryOpt;     /* Save value before bracket */
-                
-                if (!compileBracket(
-                                   options,
-                                   brackets,                     /* Extracting bracket count */
-                                   &tempcode,                    /* Where to put code (updated) */
-                                   &ptr,                         /* Input pointer (updated) */
-                                   patternEnd,
-                                   errorCodePtr,                 /* Where to put an error message */
-                                   skipBytes,                    /* Skip over OP_BRANUMBER */
-                                   &subFirstByte,                /* For possible first char */
-                                   &subReqByte,                  /* For possible last char */
-                                   cd))                          /* Tables block */
-                    goto FAILED;
-                
-                /* At the end of compiling, code is still pointing to the start of the
-                 group, while tempcode has been updated to point past the end of the group
-                 and any option resetting that may follow it. The pattern pointer (ptr)
-                 is on the bracket. */
-                
-                /* Handle updating of the required and first characters. Update for normal
-                 brackets of all kinds, and conditions with two branches (see code above).
-                 If the bracket is followed by a quantifier with zero repeat, we have to
-                 back off. Hence the definition of zeroReqByte and zeroFirstByte outside the
-                 main loop so that they can be accessed for the back off. */
-                
-                zeroReqByte = reqByte;
-                zeroFirstByte = firstByte;
-                didGroupSetFirstByte = false;
-                
-                if (bravalue >= OP_BRA) {
-                    /* If we have not yet set a firstByte in this branch, take it from the
-                     subpattern, remembering that it was set here so that a repeat of more
-                     than one can replicate it as reqByte if necessary. If the subpattern has
-                     no firstByte, set "none" for the whole branch. In both cases, a zero
-                     repeat forces firstByte to "none". */
-                    
-                    if (firstByte == REQ_UNSET) {
-                        if (subFirstByte >= 0) {
-                            firstByte = subFirstByte;
-                            didGroupSetFirstByte = true;
-                        }
-                        else
-                            firstByte = REQ_NONE;
-                        zeroFirstByte = REQ_NONE;
-                    }
-                    
-                    /* If firstByte was previously set, convert the subpattern's firstByte
-                     into reqByte if there wasn't one, using the vary flag that was in
-                     existence beforehand. */
-                    
-                    else if (subFirstByte >= 0 && subReqByte < 0)
-                        subReqByte = subFirstByte | tempreqvary;
-                    
-                    /* If the subpattern set a required byte (or set a first byte that isn't
-                     really the first byte - see above), set it. */
-                    
-                    if (subReqByte >= 0)
-                        reqByte = subReqByte;
-                }
-                
-                /* For a forward assertion, we take the reqByte, if set. This can be
-                 helpful if the pattern that follows the assertion doesn't set a different
-                 char. For example, it's useful for /(?=abcde).+/. We can't set firstByte
-                 for an assertion, however because it leads to incorrect effect for patterns
-                 such as /(?=a)a.+/ when the "real" "a" would then become a reqByte instead
-                 of a firstByte. This is overcome by a scan at the end if there's no
-                 firstByte, looking for an asserted first char. */
-                
-                else if (bravalue == OP_ASSERT && subReqByte >= 0)
-                    reqByte = subReqByte;
-                
-                /* Now update the main code pointer to the end of the group. */
-                
-                code = tempcode;
-                
-                /* Error if hit end of pattern */
-                
-                if (ptr >= patternEnd || *ptr != ')') {
-                    *errorCodePtr = ERR14;
-                    goto FAILED;
-                }
-                break;
-                
-            /* Check \ for being a real metacharacter; if not, fall through and handle
-             it as a data character at the start of a string. Escape items are checked
-             for validity in the pre-compiling pass. */
-                
-            case '\\':
-                tempptr = ptr;
-                c = checkEscape(&ptr, patternEnd, errorCodePtr, cd.numCapturingBrackets, false);
-                
-                /* Handle metacharacters introduced by \. For ones like \d, the ESC_ values
-                 are arranged to be the negation of the corresponding OP_values. For the
-                 back references, the values are ESC_REF plus the reference number. Only
-                 back references and those types that consume a character may be repeated.
-                 We can test for values between ESC_b and ESC_w for the latter; this may
-                 have to change if any new ones are ever created. */
-                
-                if (c < 0) {
-                    /* For metasequences that actually match a character, we disable the
-                     setting of a first character if it hasn't already been set. */
-                    
-                    if (firstByte == REQ_UNSET && -c > ESC_b && -c <= ESC_w)
-                        firstByte = REQ_NONE;
-                    
-                    /* Set values to reset to if this is followed by a zero repeat. */
-                    
-                    zeroFirstByte = firstByte;
-                    zeroReqByte = reqByte;
-                    
-                    /* Back references are handled specially */
-                    
-                    if (-c >= ESC_REF) {
-                        int number = -c - ESC_REF;
-                        previous = code;
-                        *code++ = OP_REF;
-                        put2ByteValueAndAdvance(code, number);
-                    }
-                    
-                    /* For the rest, we can obtain the OP value by negating the escape
-                     value */
-                    
-                    else {
-                        previous = (-c > ESC_b && -c <= ESC_w) ? code : NULL;
-                        *code++ = -c;
-                    }
-                    continue;
-                }
-                
-                /* Fall through. */
-                
-                /* Handle a literal character. It is guaranteed not to be whitespace or #
-                 when the extended flag is set. If we are in UTF-8 mode, it may be a
-                 multi-byte literal character. */
-                
-                default:
-            NORMAL_CHAR:
-                
-                previous = code;
-                
-                if (c < 128) {
-                    mcLength = 1;
-                    mcbuffer[0] = c;
-                    
-                    if ((options & IgnoreCaseOption) && (c | 0x20) >= 'a' && (c | 0x20) <= 'z') {
-                        *code++ = OP_ASCII_LETTER_IGNORING_CASE;
-                        *code++ = c | 0x20;
-                    } else {
-                        *code++ = OP_ASCII_CHAR;
-                        *code++ = c;
-                    }
-                } else {
-                    mcLength = encodeUTF8(c, mcbuffer);
-                    
-                    *code++ = (options & IgnoreCaseOption) ? OP_CHAR_IGNORING_CASE : OP_CHAR;
-                    for (c = 0; c < mcLength; c++)
-                        *code++ = mcbuffer[c];
-                }
-                
-                /* Set the first and required bytes appropriately. If no previous first
-                 byte, set it from this character, but revert to none on a zero repeat.
-                 Otherwise, leave the firstByte value alone, and don't change it on a zero
-                 repeat. */
-                
-                if (firstByte == REQ_UNSET) {
-                    zeroFirstByte = REQ_NONE;
-                    zeroReqByte = reqByte;
-                    
-                    /* If the character is more than one byte long, we can set firstByte
-                     only if it is not to be matched caselessly. */
-                    
-                    if (mcLength == 1 || reqCaseOpt == 0) {
-                        firstByte = mcbuffer[0] | reqCaseOpt;
-                        if (mcLength != 1)
-                            reqByte = code[-1] | cd.reqVaryOpt;
-                    }
-                    else
-                        firstByte = reqByte = REQ_NONE;
-                }
-                
-                /* firstByte was previously set; we can set reqByte only the length is
-                 1 or the matching is caseful. */
-                
-                else {
-                    zeroFirstByte = firstByte;
-                    zeroReqByte = reqByte;
-                    if (mcLength == 1 || reqCaseOpt == 0)
-                        reqByte = code[-1] | reqCaseOpt | cd.reqVaryOpt;
-                }
-                
-                break;            /* End of literal character handling */
-        }
-    }                   /* end of big loop */
-    
-    /* Control never reaches here by falling through, only by a goto for all the
-     error states. Pass back the position in the pattern so that it can be displayed
-     to the user for diagnosing the error. */
-    
-FAILED:
-    *ptrPtr = ptr;
-    return false;
-}
-
-/*************************************************
-*     Compile sequence of alternatives           *
-*************************************************/
-
-/* On entry, ptr is pointing past the bracket character, but on return
-it points to the closing bracket, or vertical bar, or end of string.
-The code variable is pointing at the byte into which the BRA operator has been
-stored. If the ims options are changed at the start (for a (?ims: group) or
-during any branch, we need to insert an OP_OPT item at the start of every
-following branch to ensure they get set correctly at run time, and also pass
-the new options into every subsequent branch compile.
-
-Argument:
-  options        option bits, including any changes for this subpattern
-  brackets       -> int containing the number of extracting brackets used
-  codePtr        -> the address of the current code pointer
-  ptrPtr         -> the address of the current pattern pointer
-  errorCodePtr   -> pointer to error code variable
-  skipBytes      skip this many bytes at start (for OP_BRANUMBER)
-  firstbyteptr   place to put the first required character, or a negative number
-  reqbyteptr     place to put the last required character, or a negative number
-  cd             points to the data block with tables pointers etc.
-
-Returns:      true on success
-*/
-
-static bool
-compileBracket(int options, int* brackets, unsigned char** codePtr,
-    const UChar** ptrPtr, const UChar* patternEnd, ErrorCode* errorCodePtr, int skipBytes,
-    int* firstbyteptr, int* reqbyteptr, CompileData& cd)
-{
-    const UChar* ptr = *ptrPtr;
-    unsigned char* code = *codePtr;
-    unsigned char* lastBranch = code;
-    unsigned char* start_bracket = code;
-    int firstByte = REQ_UNSET;
-    int reqByte = REQ_UNSET;
-    
-    /* Offset is set zero to mark that this bracket is still open */
-    
-    putLinkValueAllowZero(code + 1, 0);
-    code += 1 + LINK_SIZE + skipBytes;
-    
-    /* Loop for each alternative branch */
-    
-    while (true) {
-        /* Now compile the branch */
-        
-        int branchFirstByte;
-        int branchReqByte;
-        if (!compileBranch(options, brackets, &code, &ptr, patternEnd, errorCodePtr,
-                            &branchFirstByte, &branchReqByte, cd)) {
-            *ptrPtr = ptr;
-            return false;
-        }
-        
-        /* If this is the first branch, the firstByte and reqByte values for the
-         branch become the values for the regex. */
-        
-        if (*lastBranch != OP_ALT) {
-            firstByte = branchFirstByte;
-            reqByte = branchReqByte;
-        }
-        
-        /* If this is not the first branch, the first char and reqByte have to
-         match the values from all the previous branches, except that if the previous
-         value for reqByte didn't have REQ_VARY set, it can still match, and we set
-         REQ_VARY for the regex. */
-        
-        else {
-            /* If we previously had a firstByte, but it doesn't match the new branch,
-             we have to abandon the firstByte for the regex, but if there was previously
-             no reqByte, it takes on the value of the old firstByte. */
-            
-            if (firstByte >= 0 && firstByte != branchFirstByte) {
-                if (reqByte < 0)
-                    reqByte = firstByte;
-                firstByte = REQ_NONE;
-            }
-            
-            /* If we (now or from before) have no firstByte, a firstByte from the
-             branch becomes a reqByte if there isn't a branch reqByte. */
-            
-            if (firstByte < 0 && branchFirstByte >= 0 && branchReqByte < 0)
-                branchReqByte = branchFirstByte;
-            
-            /* Now ensure that the reqbytes match */
-            
-            if ((reqByte & ~REQ_VARY) != (branchReqByte & ~REQ_VARY))
-                reqByte = REQ_NONE;
-            else
-                reqByte |= branchReqByte;   /* To "or" REQ_VARY */
-        }
-        
-        /* Reached end of expression, either ')' or end of pattern. Go back through
-         the alternative branches and reverse the chain of offsets, with the field in
-         the BRA item now becoming an offset to the first alternative. If there are
-         no alternatives, it points to the end of the group. The length in the
-         terminating ket is always the length of the whole bracketed item. If any of
-         the ims options were changed inside the group, compile a resetting op-code
-         following, except at the very end of the pattern. Return leaving the pointer
-         at the terminating char. */
-        
-        if (ptr >= patternEnd || *ptr != '|') {
-            int length = code - lastBranch;
-            do {
-                int prevLength = getLinkValueAllowZero(lastBranch + 1);
-                putLinkValue(lastBranch + 1, length);
-                length = prevLength;
-                lastBranch -= length;
-            } while (length > 0);
-            
-            /* Fill in the ket */
-            
-            *code = OP_KET;
-            putLinkValue(code + 1, code - start_bracket);
-            code += 1 + LINK_SIZE;
-            
-            /* Set values to pass back */
-            
-            *codePtr = code;
-            *ptrPtr = ptr;
-            *firstbyteptr = firstByte;
-            *reqbyteptr = reqByte;
-            return true;
-        }
-        
-        /* Another branch follows; insert an "or" node. Its length field points back
-         to the previous branch while the bracket remains open. At the end the chain
-         is reversed. It's done like this so that the start of the bracket has a
-         zero offset until it is closed, making it possible to detect recursion. */
-        
-        *code = OP_ALT;
-        putLinkValue(code + 1, code - lastBranch);
-        lastBranch = code;
-        code += 1 + LINK_SIZE;
-        ptr++;
-    }
-    ASSERT_NOT_REACHED();
-}
-
-/*************************************************
-*          Check for anchored expression         *
-*************************************************/
-
-/* Try to find out if this is an anchored regular expression. Consider each
-alternative branch. If they all start OP_CIRC, or with a bracket
-all of whose alternatives start OP_CIRC (recurse ad lib), then
-it's anchored.
-
-Arguments:
-  code          points to start of expression (the bracket)
-  captureMap    a bitmap of which brackets we are inside while testing; this
-                 handles up to substring 31; all brackets after that share
-                 the zero bit
-  backrefMap    the back reference bitmap
-*/
-
-static bool branchIsAnchored(const unsigned char* code)
-{
-    const unsigned char* scode = firstSignificantOpcode(code);
-    int op = *scode;
-
-    /* Brackets */
-    if (op >= OP_BRA || op == OP_ASSERT)
-        return bracketIsAnchored(scode);
-
-    /* Check for explicit anchoring */    
-    return op == OP_CIRC;
-}
-
-static bool bracketIsAnchored(const unsigned char* code)
-{
-    do {
-        if (!branchIsAnchored(code + 1 + LINK_SIZE))
-            return false;
-        code += getLinkValue(code + 1);
-    } while (*code == OP_ALT);   /* Loop for each alternative */
-    return true;
-}
-
-/*************************************************
-*         Check for starting with ^ or .*        *
-*************************************************/
-
-/* This is called to find out if every branch starts with ^ or .* so that
-"first char" processing can be done to speed things up in multiline
-matching and for non-DOTALL patterns that start with .* (which must start at
-the beginning or after \n)
-
-Except when the .* appears inside capturing parentheses, and there is a
-subsequent back reference to those parentheses. By keeping a bitmap of the
-first 31 back references, we can catch some of the more common cases more
-precisely; all the greater back references share a single bit.
-
-Arguments:
-  code          points to start of expression (the bracket)
-  captureMap    a bitmap of which brackets we are inside while testing; this
-                 handles up to substring 31; all brackets after that share
-                 the zero bit
-  backrefMap    the back reference bitmap
-*/
-
-static bool branchNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap)
-{
-    const unsigned char* scode = firstSignificantOpcode(code);
-    int op = *scode;
-    
-    /* Capturing brackets */
-    if (op > OP_BRA) {
-        int captureNum = op - OP_BRA;
-        if (captureNum > EXTRACT_BASIC_MAX)
-            captureNum = get2ByteValue(scode + 2 + LINK_SIZE);
-        int bracketMask = (captureNum < 32) ? (1 << captureNum) : 1;
-        return bracketNeedsLineStart(scode, captureMap | bracketMask, backrefMap);
-    }
-    
-    /* Other brackets */
-    if (op == OP_BRA || op == OP_ASSERT)
-        return bracketNeedsLineStart(scode, captureMap, backrefMap);
-    
-    /* .* means "start at start or after \n" if it isn't in brackets that
-     may be referenced. */
-    
-    if (op == OP_TYPESTAR || op == OP_TYPEMINSTAR)
-        return scode[1] == OP_NOT_NEWLINE && !(captureMap & backrefMap);
-
-    /* Explicit ^ */
-    return op == OP_CIRC || op == OP_BOL;
-}
-
-static bool bracketNeedsLineStart(const unsigned char* code, unsigned captureMap, unsigned backrefMap)
-{
-    do {
-        if (!branchNeedsLineStart(code + 1 + LINK_SIZE, captureMap, backrefMap))
-            return false;
-        code += getLinkValue(code + 1);
-    } while (*code == OP_ALT);  /* Loop for each alternative */
-    return true;
-}
-
-/*************************************************
-*       Check for asserted fixed first char      *
-*************************************************/
-
-/* During compilation, the "first char" settings from forward assertions are
-discarded, because they can cause conflicts with actual literals that follow.
-However, if we end up without a first char setting for an unanchored pattern,
-it is worth scanning the regex to see if there is an initial asserted first
-char. If all branches start with the same asserted char, or with a bracket all
-of whose alternatives start with the same asserted char (recurse ad lib), then
-we return that char, otherwise -1.
-
-Arguments:
-  code       points to start of expression (the bracket)
-  options    pointer to the options (used to check casing changes)
-  inassert   true if in an assertion
-
-Returns:     -1 or the fixed first char
-*/
-
-static int branchFindFirstAssertedCharacter(const unsigned char* code, bool inassert)
-{
-    const unsigned char* scode = firstSignificantOpcodeSkippingAssertions(code);
-    int op = *scode;
-    
-    if (op >= OP_BRA)
-        op = OP_BRA;
-    
-    switch (op) {
-        default:
-            return -1;
-            
-        case OP_BRA:
-        case OP_ASSERT:
-            return bracketFindFirstAssertedCharacter(scode, op == OP_ASSERT);
-
-        case OP_EXACT:
-            scode += 2;
-            /* Fall through */
-
-        case OP_CHAR:
-        case OP_CHAR_IGNORING_CASE:
-        case OP_ASCII_CHAR:
-        case OP_ASCII_LETTER_IGNORING_CASE:
-        case OP_PLUS:
-        case OP_MINPLUS:
-            if (!inassert)
-                return -1;
-            return scode[1];
-    }
-}
-
-static int bracketFindFirstAssertedCharacter(const unsigned char* code, bool inassert)
-{
-    int c = -1;
-    do {
-        int d = branchFindFirstAssertedCharacter(code + 1 + LINK_SIZE, inassert);
-        if (d < 0)
-            return -1;
-        if (c < 0)
-            c = d;
-        else if (c != d)
-            return -1;
-        code += getLinkValue(code + 1);
-    } while (*code == OP_ALT);
-    return c;
-}
-
-static inline int multiplyWithOverflowCheck(int a, int b)
-{
-    if (!a || !b)
-        return 0;
-    if (a > MAX_PATTERN_SIZE / b)
-        return -1;
-    return a * b;
-}
-
-static int calculateCompiledPatternLength(const UChar* pattern, int patternLength, JSRegExpIgnoreCaseOption ignoreCase,
-    CompileData& cd, ErrorCode& errorcode)
-{
-    /* Make a pass over the pattern to compute the
-     amount of store required to hold the compiled code. This does not have to be
-     perfect as long as errors are overestimates. */
-
-    if (patternLength > MAX_PATTERN_SIZE) {
-        errorcode = ERR16;
-        return -1;
-    }
-
-    int length = 1 + LINK_SIZE;      /* For initial BRA plus length */
-    int branch_extra = 0;
-    int lastitemlength = 0;
-    unsigned brastackptr = 0;
-    int brastack[BRASTACK_SIZE];
-    unsigned char bralenstack[BRASTACK_SIZE];
-    int bracount = 0;
-    
-    const UChar* ptr = (const UChar*)(pattern - 1);
-    const UChar* patternEnd = (const UChar*)(pattern + patternLength);
-    
-    while (++ptr < patternEnd) {
-        int minRepeats = 0, maxRepeats = 0;
-        int c = *ptr;
-
-        switch (c) {
-            /* A backslashed item may be an escaped data character or it may be a
-             character type. */
-
-            case '\\':
-                c = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, false);
-                if (errorcode != 0)
-                    return -1;
-                
-                lastitemlength = 1;     /* Default length of last item for repeats */
-                
-                if (c >= 0) {            /* Data character */
-                    length += 2;          /* For a one-byte character */
-                    
-                    if (c > 127) {
-                        int i;
-                        for (i = 0; i < jsc_pcre_utf8_table1_size; i++)
-                            if (c <= jsc_pcre_utf8_table1[i]) break;
-                        length += i;
-                        lastitemlength += i;
-                    }
-                    
-                    continue;
-                }
-                
-                /* Other escapes need one byte */
-                
-                length++;
-                
-                /* A back reference needs an additional 2 bytes, plus either one or 5
-                 bytes for a repeat. We also need to keep the value of the highest
-                 back reference. */
-                
-                if (c <= -ESC_REF) {
-                    int refnum = -c - ESC_REF;
-                    cd.backrefMap |= (refnum < 32) ? (1 << refnum) : 1;
-                    if (refnum > cd.topBackref)
-                        cd.topBackref = refnum;
-                    length += 2;   /* For single back reference */
-                    if (safelyCheckNextChar(ptr, patternEnd, '{') && isCountedRepeat(ptr + 2, patternEnd)) {
-                        ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
-                        if (errorcode)
-                            return -1;
-                        if ((minRepeats == 0 && (maxRepeats == 1 || maxRepeats == -1)) ||
-                            (minRepeats == 1 && maxRepeats == -1))
-                            length++;
-                        else
-                            length += 5;
-                        if (safelyCheckNextChar(ptr, patternEnd, '?'))
-                            ptr++;
-                    }
-                }
-                continue;
-                
-            case '^':     /* Single-byte metacharacters */
-            case '.':
-            case '$':
-                length++;
-                lastitemlength = 1;
-                continue;
-                
-            case '*':            /* These repeats won't be after brackets; */
-            case '+':            /* those are handled separately */
-            case '?':
-                length++;
-                goto POSSESSIVE;
-                
-            /* This covers the cases of braced repeats after a single char, metachar,
-             class, or back reference. */
-
-            case '{':
-                if (!isCountedRepeat(ptr + 1, patternEnd))
-                    goto NORMAL_CHAR;
-                ptr = readRepeatCounts(ptr + 1, &minRepeats, &maxRepeats, &errorcode);
-                if (errorcode != 0)
-                    return -1;
-                
-                /* These special cases just insert one extra opcode */
-                
-                if ((minRepeats == 0 && (maxRepeats == 1 || maxRepeats == -1)) ||
-                    (minRepeats == 1 && maxRepeats == -1))
-                    length++;
-                
-                /* These cases might insert additional copies of a preceding character. */
-                
-                else {
-                    if (minRepeats != 1) {
-                        length -= lastitemlength;   /* Uncount the original char or metachar */
-                        if (minRepeats > 0)
-                            length += 3 + lastitemlength;
-                    }
-                    length += lastitemlength + ((maxRepeats > 0) ? 3 : 1);
-                }
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '?'))
-                    ptr++;      /* Needs no extra length */
-
-            POSSESSIVE:                     /* Test for possessive quantifier */
-                if (safelyCheckNextChar(ptr, patternEnd, '+')) {
-                    ptr++;
-                    length += 2 + 2 * LINK_SIZE;   /* Allow for atomic brackets */
-                }
-                continue;
-                
-            /* An alternation contains an offset to the next branch or ket. If any ims
-             options changed in the previous branch(es), and/or if we are in a
-             lookbehind assertion, extra space will be needed at the start of the
-             branch. This is handled by branch_extra. */
-                
-            case '|':
-                if (brastackptr == 0)
-                    cd.needOuterBracket = true;
-                length += 1 + LINK_SIZE + branch_extra;
-                continue;
-                
-            /* A character class uses 33 characters provided that all the character
-             values are less than 256. Otherwise, it uses a bit map for low valued
-             characters, and individual items for others. Don't worry about character
-             types that aren't allowed in classes - they'll get picked up during the
-             compile. A character class that contains only one single-byte character
-             uses 2 or 3 bytes, depending on whether it is negated or not. Notice this
-             where we can. (In UTF-8 mode we can do this only for chars < 128.) */
-                
-            case '[': {
-                int class_optcount;
-                if (*(++ptr) == '^') {
-                    class_optcount = 10;  /* Greater than one */
-                    ptr++;
-                }
-                else
-                    class_optcount = 0;
-                
-                bool class_utf8 = false;
-                
-                for (; ptr < patternEnd && *ptr != ']'; ++ptr) {
-                    /* Check for escapes */
-                    
-                    if (*ptr == '\\') {
-                        c = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, true);
-                        if (errorcode != 0)
-                            return -1;
-                        
-                        /* Handle escapes that turn into characters */
-                        
-                        if (c >= 0)
-                            goto NON_SPECIAL_CHARACTER;
-                        
-                        /* Escapes that are meta-things. The normal ones just affect the
-                         bit map, but Unicode properties require an XCLASS extended item. */
-                        
-                        else
-                            class_optcount = 10;         /* \d, \s etc; make sure > 1 */
-                    }
-                    
-                    /* Anything else increments the possible optimization count. We have to
-                     detect ranges here so that we can compute the number of extra ranges for
-                     caseless wide characters when UCP support is available. If there are wide
-                     characters, we are going to have to use an XCLASS, even for single
-                     characters. */
-                    
-                    else {
-                        c = *ptr;
-                        
-                        /* Come here from handling \ above when it escapes to a char value */
-                        
-                    NON_SPECIAL_CHARACTER:
-                        class_optcount++;
-                        
-                        int d = -1;
-                        if (safelyCheckNextChar(ptr, patternEnd, '-')) {
-                            const UChar* hyptr = ptr++;
-                            if (safelyCheckNextChar(ptr, patternEnd, '\\')) {
-                                ptr++;
-                                d = checkEscape(&ptr, patternEnd, &errorcode, cd.numCapturingBrackets, true);
-                                if (errorcode != 0)
-                                    return -1;
-                            }
-                            else if ((ptr + 1 < patternEnd) && ptr[1] != ']')
-                                d = *++ptr;
-                            if (d < 0)
-                                ptr = hyptr;      /* go back to hyphen as data */
-                        }
-                        
-                        /* If d >= 0 we have a range. In UTF-8 mode, if the end is > 255, or >
-                         127 for caseless matching, we will need to use an XCLASS. */
-                        
-                        if (d >= 0) {
-                            class_optcount = 10;     /* Ensure > 1 */
-                            if (d < c) {
-                                errorcode = ERR8;
-                                return -1;
-                            }
-                            
-                            if ((d > 255 || (ignoreCase && d > 127))) {
-                                unsigned char buffer[6];
-                                if (!class_utf8)         /* Allow for XCLASS overhead */
-                                {
-                                    class_utf8 = true;
-                                    length += LINK_SIZE + 2;
-                                }
-                                
-                                /* If we have UCP support, find out how many extra ranges are
-                                 needed to map the other case of characters within this range. We
-                                 have to mimic the range optimization here, because extending the
-                                 range upwards might push d over a boundary that makes it use
-                                 another byte in the UTF-8 representation. */
-                                
-                                if (ignoreCase) {
-                                    int occ, ocd;
-                                    int cc = c;
-                                    int origd = d;
-                                    while (getOthercaseRange(&cc, origd, &occ, &ocd)) {
-                                        if (occ >= c && ocd <= d)
-                                            continue;   /* Skip embedded */
-                                        
-                                        if (occ < c  && ocd >= c - 1)  /* Extend the basic range */
-                                        {                            /* if there is overlap,   */
-                                            c = occ;                     /* noting that if occ < c */
-                                            continue;                    /* we can't have ocd > d  */
-                                        }                            /* because a subrange is  */
-                                        if (ocd > d && occ <= d + 1)   /* always shorter than    */
-                                        {                            /* the basic range.       */
-                                            d = ocd;
-                                            continue;
-                                        }
-                                        
-                                        /* An extra item is needed */
-                                        
-                                        length += 1 + encodeUTF8(occ, buffer) +
-                                        ((occ == ocd) ? 0 : encodeUTF8(ocd, buffer));
-                                    }
-                                }
-                                
-                                /* The length of the (possibly extended) range */
-                                
-                                length += 1 + encodeUTF8(c, buffer) + encodeUTF8(d, buffer);
-                            }
-                            
-                        }
-                        
-                        /* We have a single character. There is nothing to be done unless we
-                         are in UTF-8 mode. If the char is > 255, or 127 when caseless, we must
-                         allow for an XCL_SINGLE item, doubled for caselessness if there is UCP
-                         support. */
-                        
-                        else {
-                            if ((c > 255 || (ignoreCase && c > 127))) {
-                                unsigned char buffer[6];
-                                class_optcount = 10;     /* Ensure > 1 */
-                                if (!class_utf8)         /* Allow for XCLASS overhead */
-                                {
-                                    class_utf8 = true;
-                                    length += LINK_SIZE + 2;
-                                }
-                                length += (ignoreCase ? 2 : 1) * (1 + encodeUTF8(c, buffer));
-                            }
-                        }
-                    }
-                }
-                
-                if (ptr >= patternEnd) {   /* Missing terminating ']' */
-                    errorcode = ERR6;
-                    return -1;
-                }
-                
-                /* We can optimize when there was only one optimizable character.
-                 Note that this does not detect the case of a negated single character.
-                 In that case we do an incorrect length computation, but it's not a serious
-                 problem because the computed length is too large rather than too small. */
-
-                if (class_optcount == 1)
-                    goto NORMAL_CHAR;
-
-                /* Here, we handle repeats for the class opcodes. */
-                {
-                    length += 33;
-                    
-                    /* A repeat needs either 1 or 5 bytes. If it is a possessive quantifier,
-                     we also need extra for wrapping the whole thing in a sub-pattern. */
-                    
-                    if (safelyCheckNextChar(ptr, patternEnd, '{') && isCountedRepeat(ptr + 2, patternEnd)) {
-                        ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
-                        if (errorcode != 0)
-                            return -1;
-                        if ((minRepeats == 0 && (maxRepeats == 1 || maxRepeats == -1)) ||
-                            (minRepeats == 1 && maxRepeats == -1))
-                            length++;
-                        else
-                            length += 5;
-                        if (safelyCheckNextChar(ptr, patternEnd, '+')) {
-                            ptr++;
-                            length += 2 + 2 * LINK_SIZE;
-                        } else if (safelyCheckNextChar(ptr, patternEnd, '?'))
-                            ptr++;
-                    }
-                }
-                continue;
-            }
-
-            /* Brackets may be genuine groups or special things */
-                
-            case '(': {
-                int branch_newextra = 0;
-                int bracket_length = 1 + LINK_SIZE;
-                bool capturing = false;
-                
-                /* Handle special forms of bracket, which all start (? */
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '?')) {
-                    switch (c = (ptr + 2 < patternEnd ? ptr[2] : 0)) {
-                        /* Non-referencing groups and lookaheads just move the pointer on, and
-                         then behave like a non-special bracket, except that they don't increment
-                         the count of extracting brackets. Ditto for the "once only" bracket,
-                         which is in Perl from version 5.005. */
-                            
-                        case ':':
-                        case '=':
-                        case '!':
-                            ptr += 2;
-                            break;
-                            
-                        /* Else loop checking valid options until ) is met. Anything else is an
-                         error. If we are without any brackets, i.e. at top level, the settings
-                         act as if specified in the options, so massage the options immediately.
-                         This is for backward compatibility with Perl 5.004. */
-                            
-                        default:
-                            errorcode = ERR12;
-                            return -1;
-                    }
-                } else
-                    capturing = 1;
-                
-                /* Capturing brackets must be counted so we can process escapes in a
-                 Perlish way. If the number exceeds EXTRACT_BASIC_MAX we are going to need
-                 an additional 3 bytes of memory per capturing bracket. */
-                
-                if (capturing) {
-                    bracount++;
-                    if (bracount > EXTRACT_BASIC_MAX)
-                        bracket_length += 3;
-                }
-                
-                /* Save length for computing whole length at end if there's a repeat that
-                 requires duplication of the group. Also save the current value of
-                 branch_extra, and start the new group with the new value. If non-zero, this
-                 will either be 2 for a (?imsx: group, or 3 for a lookbehind assertion. */
-                
-                if (brastackptr >= sizeof(brastack)/sizeof(int)) {
-                    errorcode = ERR17;
-                    return -1;
-                }
-                
-                bralenstack[brastackptr] = branch_extra;
-                branch_extra = branch_newextra;
-                
-                brastack[brastackptr++] = length;
-                length += bracket_length;
-                continue;
-            }
-
-            /* Handle ket. Look for subsequent maxRepeats/minRepeats; for certain sets of values we
-             have to replicate this bracket up to that many times. If brastackptr is
-             0 this is an unmatched bracket which will generate an error, but take care
-             not to try to access brastack[-1] when computing the length and restoring
-             the branch_extra value. */
-
-            case ')': {
-                int duplength;
-                length += 1 + LINK_SIZE;
-                if (brastackptr > 0) {
-                    duplength = length - brastack[--brastackptr];
-                    branch_extra = bralenstack[brastackptr];
-                }
-                else
-                    duplength = 0;
-                
-                /* Leave ptr at the final char; for readRepeatCounts this happens
-                 automatically; for the others we need an increment. */
-                
-                if ((ptr + 1 < patternEnd) && (c = ptr[1]) == '{' && isCountedRepeat(ptr + 2, patternEnd)) {
-                    ptr = readRepeatCounts(ptr + 2, &minRepeats, &maxRepeats, &errorcode);
-                    if (errorcode)
-                        return -1;
-                } else if (c == '*') {
-                    minRepeats = 0;
-                    maxRepeats = -1;
-                    ptr++;
-                } else if (c == '+') {
-                    minRepeats = 1;
-                    maxRepeats = -1;
-                    ptr++;
-                } else if (c == '?') {
-                    minRepeats = 0;
-                    maxRepeats = 1;
-                    ptr++;
-                } else {
-                    minRepeats = 1;
-                    maxRepeats = 1;
-                }
-                
-                /* If the minimum is zero, we have to allow for an OP_BRAZERO before the
-                 group, and if the maximum is greater than zero, we have to replicate
-                 maxval-1 times; each replication acquires an OP_BRAZERO plus a nesting
-                 bracket set. */
-                
-                int repeatsLength;
-                if (minRepeats == 0) {
-                    length++;
-                    if (maxRepeats > 0) {
-                        repeatsLength = multiplyWithOverflowCheck(maxRepeats - 1, duplength + 3 + 2 * LINK_SIZE);
-                        if (repeatsLength < 0) {
-                            errorcode = ERR16;
-                            return -1;
-                        }
-                        length += repeatsLength;
-                        if (length > MAX_PATTERN_SIZE) {
-                            errorcode = ERR16;
-                            return -1;
-                        }
-                    }
-                }
-                
-                /* When the minimum is greater than zero, we have to replicate up to
-                 minval-1 times, with no additions required in the copies. Then, if there
-                 is a limited maximum we have to replicate up to maxval-1 times allowing
-                 for a BRAZERO item before each optional copy and nesting brackets for all
-                 but one of the optional copies. */
-                
-                else {
-                    repeatsLength = multiplyWithOverflowCheck(minRepeats - 1, duplength);
-                    if (repeatsLength < 0) {
-                        errorcode = ERR16;
-                        return -1;
-                    }
-                    length += repeatsLength;
-                    if (maxRepeats > minRepeats) { /* Need this test as maxRepeats=-1 means no limit */
-                        repeatsLength = multiplyWithOverflowCheck(maxRepeats - minRepeats, duplength + 3 + 2 * LINK_SIZE);
-                        if (repeatsLength < 0) {
-                            errorcode = ERR16;
-                            return -1;
-                        }
-                        length += repeatsLength - (2 + 2 * LINK_SIZE);
-                    }
-                    if (length > MAX_PATTERN_SIZE) {
-                        errorcode = ERR16;
-                        return -1;
-                    }
-                }
-                
-                /* Allow space for once brackets for "possessive quantifier" */
-                
-                if (safelyCheckNextChar(ptr, patternEnd, '+')) {
-                    ptr++;
-                    length += 2 + 2 * LINK_SIZE;
-                }
-                continue;
-            }
-
-            /* Non-special character. It won't be space or # in extended mode, so it is
-             always a genuine character. If we are in a \Q...\E sequence, check for the
-             end; if not, we have a literal. */
-                
-            default:
-            NORMAL_CHAR:
-                length += 2;          /* For a one-byte character */
-                lastitemlength = 1;   /* Default length of last item for repeats */
-
-                if (c > 127) {
-                    int i;
-                    for (i = 0; i < jsc_pcre_utf8_table1_size; i++)
-                        if (c <= jsc_pcre_utf8_table1[i])
-                            break;
-                    length += i;
-                    lastitemlength += i;
-                }
-                
-                continue;
-        }
-    }
-    
-    length += 2 + LINK_SIZE;    /* For final KET and END */
-
-    cd.numCapturingBrackets = bracount;
-    return length;
-}
-
-/*************************************************
-*        Compile a Regular Expression            *
-*************************************************/
-
-/* This function takes a string and returns a pointer to a block of store
-holding a compiled version of the expression. The original API for this
-function had no error code return variable; it is retained for backwards
-compatibility. The new function is given a new name.
-
-Arguments:
-  pattern       the regular expression
-  options       various option bits
-  errorCodePtr  pointer to error code variable (pcre_compile2() only)
-                  can be NULL if you don't want a code value
-  errorPtr      pointer to pointer to error text
-  erroroffset   ptr offset in pattern where error was detected
-  tables        pointer to character tables or NULL
-
-Returns:        pointer to compiled data block, or NULL on error,
-                with errorPtr and erroroffset set
-*/
-
-static inline JSRegExp* returnError(ErrorCode errorcode, const char** errorPtr)
-{
-    *errorPtr = errorText(errorcode);
-    return 0;
-}
-
-JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
-                JSRegExpIgnoreCaseOption ignoreCase, JSRegExpMultilineOption multiline,
-                unsigned* numSubpatterns, const char** errorPtr)
-{
-    /* We can't pass back an error message if errorPtr is NULL; I guess the best we
-     can do is just return NULL, but we can set a code value if there is a code pointer. */
-    if (!errorPtr)
-        return 0;
-    *errorPtr = NULL;
-    
-    CompileData cd;
-    
-    ErrorCode errorcode = ERR0;
-    /* Call this once just to count the brackets. */
-    calculateCompiledPatternLength(pattern, patternLength, ignoreCase, cd, errorcode);
-    /* Call it again to compute the length. */
-    int length = calculateCompiledPatternLength(pattern, patternLength, ignoreCase, cd, errorcode);
-    if (errorcode)
-        return returnError(errorcode, errorPtr);
-    
-    if (length > MAX_PATTERN_SIZE)
-        return returnError(ERR16, errorPtr);
-    
-    size_t size = length + sizeof(JSRegExp);
-#if REGEXP_HISTOGRAM
-    size_t stringOffset = (size + sizeof(UChar) - 1) / sizeof(UChar) * sizeof(UChar);
-    size = stringOffset + patternLength * sizeof(UChar);
-#endif
-    JSRegExp* re = reinterpret_cast<JSRegExp*>(new char[size]);
-    
-    if (!re)
-        return returnError(ERR13, errorPtr);
-    
-    re->options = (ignoreCase ? IgnoreCaseOption : 0) | (multiline ? MatchAcrossMultipleLinesOption : 0);
-    
-    /* The starting points of the name/number translation table and of the code are
-     passed around in the compile data block. */
-    
-    const unsigned char* codeStart = (const unsigned char*)(re + 1);
-    
-    /* Set up a starting, non-extracting bracket, then compile the expression. On
-     error, errorcode will be set non-zero, so we don't need to look at the result
-     of the function here. */
-    
-    const UChar* ptr = (const UChar*)pattern;
-    const UChar* patternEnd = pattern + patternLength;
-    unsigned char* code = const_cast<unsigned char*>(codeStart);
-    int firstByte, reqByte;
-    int bracketCount = 0;
-    if (!cd.needOuterBracket)
-        compileBranch(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, &firstByte, &reqByte, cd);
-    else {
-        *code = OP_BRA;
-        compileBracket(re->options, &bracketCount, &code, &ptr, patternEnd, &errorcode, 0, &firstByte, &reqByte, cd);
-    }
-    re->topBracket = bracketCount;
-    re->topBackref = cd.topBackref;
-    
-    /* If not reached end of pattern on success, there's an excess bracket. */
-    
-    if (errorcode == 0 && ptr < patternEnd)
-        errorcode = ERR10;
-    
-    /* Fill in the terminating state and check for disastrous overflow, but
-     if debugging, leave the test till after things are printed out. */
-    
-    *code++ = OP_END;
-
-    ASSERT(code - codeStart <= length);
-    if (code - codeStart > length)
-        errorcode = ERR7;
-    
-    /* Give an error if there's back reference to a non-existent capturing
-     subpattern. */
-    
-    if (re->topBackref > re->topBracket)
-        errorcode = ERR15;
-    
-    /* Failed to compile, or error while post-processing */
-    
-    if (errorcode != ERR0) {
-        delete [] reinterpret_cast<char*>(re);
-        return returnError(errorcode, errorPtr);
-    }
-    
-    /* If the anchored option was not passed, set the flag if we can determine that
-     the pattern is anchored by virtue of ^ characters or \A or anything else (such
-     as starting with .* when DOTALL is set).
-     
-     Otherwise, if we know what the first character has to be, save it, because that
-     speeds up unanchored matches no end. If not, see if we can set the
-     UseMultiLineFirstByteOptimizationOption flag. This is helpful for multiline matches when all branches
-     start with ^. and also when all branches start with .* for non-DOTALL matches.
-     */
-    
-    if (cd.needOuterBracket ? bracketIsAnchored(codeStart) : branchIsAnchored(codeStart))
-        re->options |= IsAnchoredOption;
-    else {
-        if (firstByte < 0) {
-            firstByte = (cd.needOuterBracket
-                    ? bracketFindFirstAssertedCharacter(codeStart, false)
-                    : branchFindFirstAssertedCharacter(codeStart, false))
-                | ((re->options & IgnoreCaseOption) ? REQ_IGNORE_CASE : 0);
-        }
-        if (firstByte >= 0) {
-            int ch = firstByte & 255;
-            if (ch < 127) {
-                re->firstByte = ((firstByte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? ch : firstByte;
-                re->options |= UseFirstByteOptimizationOption;
-            }
-        } else {
-            if (cd.needOuterBracket ? bracketNeedsLineStart(codeStart, 0, cd.backrefMap) : branchNeedsLineStart(codeStart, 0, cd.backrefMap))
-                re->options |= UseMultiLineFirstByteOptimizationOption;
-        }
-    }
-    
-    /* For an anchored pattern, we use the "required byte" only if it follows a
-     variable length item in the regex. Remove the caseless flag for non-caseable
-     bytes. */
-    
-    if (reqByte >= 0 && (!(re->options & IsAnchoredOption) || (reqByte & REQ_VARY))) {
-        int ch = reqByte & 255;
-        if (ch < 127) {
-            re->reqByte = ((reqByte & REQ_IGNORE_CASE) && flipCase(ch) == ch) ? (reqByte & ~REQ_IGNORE_CASE) : reqByte;
-            re->options |= UseRequiredByteOptimizationOption;
-        }
-    }
-    
-#if REGEXP_HISTOGRAM
-    re->stringOffset = stringOffset;
-    re->stringLength = patternLength;
-    memcpy(reinterpret_cast<char*>(re) + stringOffset, pattern, patternLength * 2);
-#endif
-
-    if (numSubpatterns)
-        *numSubpatterns = re->topBracket;
-    return re;
-}
-
-void jsRegExpFree(JSRegExp* re)
-{
-    delete [] reinterpret_cast<char*>(re);
-}
diff --git a/pcre/pcre_exec.cpp b/pcre/pcre_exec.cpp
deleted file mode 100644 (file)
index 50973d0..0000000
+++ /dev/null
@@ -1,2177 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-    Copyright (C) 2007 Eric Seidel <eric@webkit.org>
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-/* This module contains jsRegExpExecute(), the externally visible function
-that does pattern matching using an NFA algorithm, following the rules from
-the JavaScript specification. There are also some supporting functions. */
-
-#include "config.h"
-#include "pcre_internal.h"
-
-#include <limits.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/Vector.h>
-
-#if REGEXP_HISTOGRAM
-#include <wtf/DateMath.h>
-#include <runtime/UString.h>
-#endif
-
-using namespace WTF;
-
-#if COMPILER(GCC)
-#define USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-//#define USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-#endif
-
-/* Avoid warnings on Windows. */
-#undef min
-#undef max
-
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-typedef int ReturnLocation;
-#else
-typedef void* ReturnLocation;
-#endif
-
-#if !REGEXP_HISTOGRAM
-
-class HistogramTimeLogger {
-public:
-    HistogramTimeLogger(const JSRegExp*) { }
-};
-
-#else
-
-using namespace JSC;
-
-class Histogram {
-public:
-    ~Histogram();
-    void add(const JSRegExp*, double);
-
-private:
-    typedef HashMap<RefPtr<UString::Rep>, double> Map;
-    Map times;
-};
-
-class HistogramTimeLogger {
-public:
-    HistogramTimeLogger(const JSRegExp*);
-    ~HistogramTimeLogger();
-
-private:
-    const JSRegExp* m_re;
-    double m_startTime;
-};
-
-#endif
-
-/* Structure for building a chain of data for holding the values of
-the subject pointer at the start of each bracket, used to detect when
-an empty string has been matched by a bracket to break infinite loops. */ 
-struct BracketChainNode {
-    BracketChainNode* previousBracket;
-    const UChar* bracketStart;
-};
-
-struct MatchFrame : FastAllocBase {
-    ReturnLocation returnLocation;
-    struct MatchFrame* previousFrame;
-    
-    /* Function arguments that may change */
-    struct {
-        const UChar* subjectPtr;
-        const unsigned char* instructionPtr;
-        int offsetTop;
-        BracketChainNode* bracketChain;
-    } args;
-    
-    
-    /* PCRE uses "fake" recursion built off of gotos, thus
-     stack-based local variables are not safe to use.  Instead we have to
-     store local variables on the current MatchFrame. */
-    struct {
-        const unsigned char* data;
-        const unsigned char* startOfRepeatingBracket;
-        const UChar* subjectPtrAtStartOfInstruction; // Several instrutions stash away a subjectPtr here for later compare
-        const unsigned char* instructionPtrAtStartOfOnce;
-        
-        int repeatOthercase;
-        
-        int ctype;
-        int fc;
-        int fi;
-        int length;
-        int max;
-        int number;
-        int offset;
-        int saveOffset1;
-        int saveOffset2;
-        int saveOffset3;
-        
-        BracketChainNode bracketChainNode;
-    } locals;
-};
-
-/* Structure for passing "static" information around between the functions
-doing traditional NFA matching, so that they are thread-safe. */
-
-struct MatchData {
-  int*   offsetVector;         /* Offset vector */
-  int    offsetEnd;            /* One past the end */
-  int    offsetMax;            /* The maximum usable for return data */
-  bool   offsetOverflow;       /* Set if too many extractions */
-  const UChar*  startSubject;         /* Start of the subject string */
-  const UChar*  endSubject;           /* End of the subject string */
-  const UChar*  endMatchPtr;         /* Subject position at end match */
-  int    endOffsetTop;        /* Highwater mark at end of match */
-  bool   multiline;
-  bool   ignoreCase;
-};
-
-/* The maximum remaining length of subject we are prepared to search for a
-reqByte match. */
-
-#define REQ_BYTE_MAX 1000
-
-/* The below limit restricts the number of "recursive" match calls in order to
-avoid spending exponential time on complex regular expressions. */
-
-static const unsigned matchLimit = 1000000;
-
-#ifdef DEBUG
-/*************************************************
-*        Debugging function to print chars       *
-*************************************************/
-
-/* Print a sequence of chars in printable format, stopping at the end of the
-subject if the requested.
-
-Arguments:
-  p           points to characters
-  length      number to print
-  isSubject  true if printing from within md.startSubject
-  md          pointer to matching data block, if isSubject is true
-*/
-
-static void pchars(const UChar* p, int length, bool isSubject, const MatchData& md)
-{
-    if (isSubject && length > md.endSubject - p)
-        length = md.endSubject - p;
-    while (length-- > 0) {
-        int c;
-        if (isASCIIPrintable(c = *(p++)))
-            printf("%c", c);
-        else if (c < 256)
-            printf("\\x%02x", c);
-        else
-            printf("\\x{%x}", c);
-    }
-}
-#endif
-
-/*************************************************
-*          Match a back-reference                *
-*************************************************/
-
-/* If a back reference hasn't been set, the length that is passed is greater
-than the number of characters left in the string, so the match fails.
-
-Arguments:
-  offset      index into the offset vector
-  subjectPtr        points into the subject
-  length      length to be matched
-  md          points to match data block
-
-Returns:      true if matched
-*/
-
-static bool matchRef(int offset, const UChar* subjectPtr, int length, const MatchData& md)
-{
-    const UChar* p = md.startSubject + md.offsetVector[offset];
-    
-#ifdef DEBUG
-    if (subjectPtr >= md.endSubject)
-        printf("matching subject <null>");
-    else {
-        printf("matching subject ");
-        pchars(subjectPtr, length, true, md);
-    }
-    printf(" against backref ");
-    pchars(p, length, false, md);
-    printf("\n");
-#endif
-    
-    /* Always fail if not enough characters left */
-    
-    if (length > md.endSubject - subjectPtr)
-        return false;
-    
-    /* Separate the caselesss case for speed */
-    
-    if (md.ignoreCase) {
-        while (length-- > 0) {
-            UChar c = *p++;
-            int othercase = jsc_pcre_ucp_othercase(c);
-            UChar d = *subjectPtr++;
-            if (c != d && othercase != d)
-                return false;
-        }
-    }
-    else {
-        while (length-- > 0)
-            if (*p++ != *subjectPtr++)
-                return false;
-    }
-    
-    return true;
-}
-
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-
-/* Use numbered labels and switch statement at the bottom of the match function. */
-
-#define RMATCH_WHERE(num) num
-#define RRETURN_LABEL RRETURN_SWITCH
-
-#else
-
-/* Use GCC's computed goto extension. */
-
-/* For one test case this is more than 40% faster than the switch statement.
-We could avoid the use of the num argument entirely by using local labels,
-but using it for the GCC case as well as the non-GCC case allows us to share
-a bit more code and notice if we use conflicting numbers.*/
-
-#define RMATCH_WHERE(num) &&RRETURN_##num
-#define RRETURN_LABEL *stack.currentFrame->returnLocation
-
-#endif
-
-#define RECURSIVE_MATCH_COMMON(num) \
-    goto RECURSE;\
-    RRETURN_##num: \
-    stack.popCurrentFrame();
-
-#define RECURSIVE_MATCH(num, ra, rb) \
-    do { \
-        stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
-        RECURSIVE_MATCH_COMMON(num) \
-    } while (0)
-
-#define RECURSIVE_MATCH_NEW_GROUP(num, ra, rb) \
-    do { \
-        stack.pushNewFrame((ra), (rb), RMATCH_WHERE(num)); \
-        startNewGroup(stack.currentFrame); \
-        RECURSIVE_MATCH_COMMON(num) \
-    } while (0)
-
-#define RRETURN goto RRETURN_LABEL
-
-#define RRETURN_NO_MATCH do { isMatch = false; RRETURN; } while (0)
-
-/*************************************************
-*         Match from current position            *
-*************************************************/
-
-/* On entry instructionPtr points to the first opcode, and subjectPtr to the first character
-in the subject string, while substringStart holds the value of subjectPtr at the start of the
-last bracketed group - used for breaking infinite loops matching zero-length
-strings. This function is called recursively in many circumstances. Whenever it
-returns a negative (error) response, the outer match() call must also return the
-same response.
-
-Arguments:
-   subjectPtr        pointer in subject
-   instructionPtr       position in code
-   offsetTop  current top pointer
-   md          pointer to "static" info for the match
-
-Returns:       1 if matched          )  these values are >= 0
-               0 if failed to match  )
-               a negative error value if aborted by an error condition
-                 (e.g. stopped by repeated call or recursion limit)
-*/
-
-static const unsigned numFramesOnStack = 16;
-
-struct MatchStack {
-    MatchStack()
-        : framesEnd(frames + numFramesOnStack)
-        , currentFrame(frames)
-        , size(1) // match() creates accesses the first frame w/o calling pushNewFrame
-    {
-        ASSERT((sizeof(frames) / sizeof(frames[0])) == numFramesOnStack);
-    }
-    
-    MatchFrame frames[numFramesOnStack];
-    MatchFrame* framesEnd;
-    MatchFrame* currentFrame;
-    unsigned size;
-    
-    inline bool canUseStackBufferForNextFrame()
-    {
-        return size < numFramesOnStack;
-    }
-    
-    inline MatchFrame* allocateNextFrame()
-    {
-        if (canUseStackBufferForNextFrame())
-            return currentFrame + 1;
-        return new MatchFrame;
-    }
-    
-    inline void pushNewFrame(const unsigned char* instructionPtr, BracketChainNode* bracketChain, ReturnLocation returnLocation)
-    {
-        MatchFrame* newframe = allocateNextFrame();
-        newframe->previousFrame = currentFrame;
-
-        newframe->args.subjectPtr = currentFrame->args.subjectPtr;
-        newframe->args.offsetTop = currentFrame->args.offsetTop;
-        newframe->args.instructionPtr = instructionPtr;
-        newframe->args.bracketChain = bracketChain;
-        newframe->returnLocation = returnLocation;
-        size++;
-
-        currentFrame = newframe;
-    }
-    
-    inline void popCurrentFrame()
-    {
-        MatchFrame* oldFrame = currentFrame;
-        currentFrame = currentFrame->previousFrame;
-        if (size > numFramesOnStack)
-            delete oldFrame;
-        size--;
-    }
-
-    void popAllFrames()
-    {
-        while (size)
-            popCurrentFrame();
-    }
-};
-
-static int matchError(int errorCode, MatchStack& stack)
-{
-    stack.popAllFrames();
-    return errorCode;
-}
-
-/* Get the next UTF-8 character, not advancing the pointer, incrementing length
- if there are extra bytes. This is called when we know we are in UTF-8 mode. */
-
-static inline void getUTF8CharAndIncrementLength(int& c, const unsigned char* subjectPtr, int& len)
-{
-    c = *subjectPtr;
-    if ((c & 0xc0) == 0xc0) {
-        int gcaa = jsc_pcre_utf8_table4[c & 0x3f];  /* Number of additional bytes */
-        int gcss = 6 * gcaa;
-        c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss;
-        for (int gcii = 1; gcii <= gcaa; gcii++) {
-            gcss -= 6;
-            c |= (subjectPtr[gcii] & 0x3f) << gcss;
-        }
-        len += gcaa;
-    }
-}
-
-static inline void startNewGroup(MatchFrame* currentFrame)
-{
-    /* At the start of a bracketed group, add the current subject pointer to the
-     stack of such pointers, to be re-instated at the end of the group when we hit
-     the closing ket. When match() is called in other circumstances, we don't add to
-     this stack. */
-    
-    currentFrame->locals.bracketChainNode.previousBracket = currentFrame->args.bracketChain;
-    currentFrame->locals.bracketChainNode.bracketStart = currentFrame->args.subjectPtr;
-    currentFrame->args.bracketChain = &currentFrame->locals.bracketChainNode;
-}
-
-// FIXME: "minimize" means "not greedy", we should invert the callers to ask for "greedy" to be less confusing
-static inline void repeatInformationFromInstructionOffset(short instructionOffset, bool& minimize, int& minimumRepeats, int& maximumRepeats)
-{
-    // Instruction offsets are based off of OP_CRSTAR, OP_STAR, OP_TYPESTAR, OP_NOTSTAR
-    static const char minimumRepeatsFromInstructionOffset[] = { 0, 0, 1, 1, 0, 0 };
-    static const int maximumRepeatsFromInstructionOffset[] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX, 1, 1 };
-
-    ASSERT(instructionOffset >= 0);
-    ASSERT(instructionOffset <= (OP_CRMINQUERY - OP_CRSTAR));
-
-    minimize = (instructionOffset & 1); // this assumes ordering: Instruction, MinimizeInstruction, Instruction2, MinimizeInstruction2
-    minimumRepeats = minimumRepeatsFromInstructionOffset[instructionOffset];
-    maximumRepeats = maximumRepeatsFromInstructionOffset[instructionOffset];
-}
-
-static int match(const UChar* subjectPtr, const unsigned char* instructionPtr, int offsetTop, MatchData& md)
-{
-    bool isMatch = false;
-    int min;
-    bool minimize = false; /* Initialization not really needed, but some compilers think so. */
-    unsigned remainingMatchCount = matchLimit;
-    int othercase; /* Declare here to avoid errors during jumps */
-    
-    MatchStack stack;
-
-    /* The opcode jump table. */
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-#define EMIT_JUMP_TABLE_ENTRY(opcode) &&LABEL_OP_##opcode,
-    static void* opcodeJumpTable[256] = { FOR_EACH_OPCODE(EMIT_JUMP_TABLE_ENTRY) };
-#undef EMIT_JUMP_TABLE_ENTRY
-#endif
-    
-    /* One-time setup of the opcode jump table. */
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-    for (int i = 255; !opcodeJumpTable[i]; i--)
-        opcodeJumpTable[i] = &&CAPTURING_BRACKET;
-#endif
-    
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-    // Shark shows this as a hot line
-    // Using a static const here makes this line disappear, but makes later access hotter (not sure why)
-    stack.currentFrame->returnLocation = &&RETURN;
-#else
-    stack.currentFrame->returnLocation = 0;
-#endif
-    stack.currentFrame->args.subjectPtr = subjectPtr;
-    stack.currentFrame->args.instructionPtr = instructionPtr;
-    stack.currentFrame->args.offsetTop = offsetTop;
-    stack.currentFrame->args.bracketChain = 0;
-    startNewGroup(stack.currentFrame);
-    
-    /* This is where control jumps back to to effect "recursion" */
-    
-RECURSE:
-    if (!--remainingMatchCount)
-        return matchError(JSRegExpErrorHitLimit, stack);
-
-    /* Now start processing the operations. */
-    
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-    while (true)
-#endif
-    {
-        
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-#define BEGIN_OPCODE(opcode) LABEL_OP_##opcode
-#define NEXT_OPCODE goto *opcodeJumpTable[*stack.currentFrame->args.instructionPtr]
-#else
-#define BEGIN_OPCODE(opcode) case OP_##opcode
-#define NEXT_OPCODE continue
-#endif
-        
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-        NEXT_OPCODE;
-#else
-        switch (*stack.currentFrame->args.instructionPtr)
-#endif
-        {
-            /* Non-capturing bracket: optimized */
-                
-            BEGIN_OPCODE(BRA):
-            NON_CAPTURING_BRACKET:
-                DPRINTF(("start bracket 0\n"));
-                do {
-                    RECURSIVE_MATCH_NEW_GROUP(2, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                    stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                DPRINTF(("bracket 0 failed\n"));
-                RRETURN;
-                
-            /* Skip over large extraction number data if encountered. */
-                
-            BEGIN_OPCODE(BRANUMBER):
-                stack.currentFrame->args.instructionPtr += 3;
-                NEXT_OPCODE;
-                
-            /* End of the pattern. */
-                
-            BEGIN_OPCODE(END):
-                md.endMatchPtr = stack.currentFrame->args.subjectPtr;          /* Record where we ended */
-                md.endOffsetTop = stack.currentFrame->args.offsetTop;   /* and how many extracts were taken */
-                isMatch = true;
-                RRETURN;
-                
-            /* Assertion brackets. Check the alternative branches in turn - the
-             matching won't pass the KET for an assertion. If any one branch matches,
-             the assertion is true. Lookbehind assertions have an OP_REVERSE item at the
-             start of each branch to move the current point backwards, so the code at
-             this level is identical to the lookahead case. */
-                
-            BEGIN_OPCODE(ASSERT):
-                do {
-                    RECURSIVE_MATCH_NEW_GROUP(6, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
-                    if (isMatch)
-                        break;
-                    stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                if (*stack.currentFrame->args.instructionPtr == OP_KET)
-                    RRETURN_NO_MATCH;
-                
-                /* Continue from after the assertion, updating the offsets high water
-                 mark, since extracts may have been taken during the assertion. */
-                
-                advanceToEndOfBracket(stack.currentFrame->args.instructionPtr);
-                stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
-                stack.currentFrame->args.offsetTop = md.endOffsetTop;
-                NEXT_OPCODE;
-                
-            /* Negative assertion: all branches must fail to match */
-                
-            BEGIN_OPCODE(ASSERT_NOT):
-                do {
-                    RECURSIVE_MATCH_NEW_GROUP(7, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, NULL);
-                    if (isMatch)
-                        RRETURN_NO_MATCH;
-                    stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                
-                stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
-                NEXT_OPCODE;
-                
-            /* An alternation is the end of a branch; scan along to find the end of the
-             bracketed group and go to there. */
-                
-            BEGIN_OPCODE(ALT):
-                advanceToEndOfBracket(stack.currentFrame->args.instructionPtr);
-                NEXT_OPCODE;
-                
-            /* BRAZERO and BRAMINZERO occur just before a bracket group, indicating
-             that it may occur zero times. It may repeat infinitely, or not at all -
-             i.e. it could be ()* or ()? in the pattern. Brackets with fixed upper
-             repeat limits are compiled as a number of copies, with the optional ones
-             preceded by BRAZERO or BRAMINZERO. */
-                
-            BEGIN_OPCODE(BRAZERO): {
-                stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
-                RECURSIVE_MATCH_NEW_GROUP(14, stack.currentFrame->locals.startOfRepeatingBracket, stack.currentFrame->args.bracketChain);
-                if (isMatch)
-                    RRETURN;
-                advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
-                stack.currentFrame->args.instructionPtr = stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE;
-                NEXT_OPCODE;
-            }
-                
-            BEGIN_OPCODE(BRAMINZERO): {
-                stack.currentFrame->locals.startOfRepeatingBracket = stack.currentFrame->args.instructionPtr + 1;
-                advanceToEndOfBracket(stack.currentFrame->locals.startOfRepeatingBracket);
-                RECURSIVE_MATCH_NEW_GROUP(15, stack.currentFrame->locals.startOfRepeatingBracket + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                if (isMatch)
-                    RRETURN;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-            }
-                
-            /* End of a group, repeated or non-repeating. If we are at the end of
-             an assertion "group", stop matching and return 1, but record the
-             current high water mark for use by positive assertions. Do this also
-             for the "once" (not-backup up) groups. */
-                
-            BEGIN_OPCODE(KET):
-            BEGIN_OPCODE(KETRMIN):
-            BEGIN_OPCODE(KETRMAX):
-                stack.currentFrame->locals.instructionPtrAtStartOfOnce = stack.currentFrame->args.instructionPtr - getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.bracketChain->bracketStart;
-
-                /* Back up the stack of bracket start pointers. */
-
-                stack.currentFrame->args.bracketChain = stack.currentFrame->args.bracketChain->previousBracket;
-
-                if (*stack.currentFrame->locals.instructionPtrAtStartOfOnce == OP_ASSERT || *stack.currentFrame->locals.instructionPtrAtStartOfOnce == OP_ASSERT_NOT) {
-                    md.endOffsetTop = stack.currentFrame->args.offsetTop;
-                    isMatch = true;
-                    RRETURN;
-                }
-                
-                /* In all other cases except a conditional group we have to check the
-                 group number back at the start and if necessary complete handling an
-                 extraction by setting the offsets and bumping the high water mark. */
-                
-                stack.currentFrame->locals.number = *stack.currentFrame->locals.instructionPtrAtStartOfOnce - OP_BRA;
-                
-                /* For extended extraction brackets (large number), we have to fish out
-                 the number from a dummy opcode at the start. */
-                
-                if (stack.currentFrame->locals.number > EXTRACT_BASIC_MAX)
-                    stack.currentFrame->locals.number = get2ByteValue(stack.currentFrame->locals.instructionPtrAtStartOfOnce + 2 + LINK_SIZE);
-                stack.currentFrame->locals.offset = stack.currentFrame->locals.number << 1;
-                
-#ifdef DEBUG
-                printf("end bracket %d", stack.currentFrame->locals.number);
-                printf("\n");
-#endif
-                
-                /* Test for a numbered group. This includes groups called as a result
-                 of recursion. Note that whole-pattern recursion is coded as a recurse
-                 into group 0, so it won't be picked up here. Instead, we catch it when
-                 the OP_END is reached. */
-                
-                if (stack.currentFrame->locals.number > 0) {
-                    if (stack.currentFrame->locals.offset >= md.offsetMax)
-                        md.offsetOverflow = true;
-                    else {
-                        md.offsetVector[stack.currentFrame->locals.offset] =
-                        md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number];
-                        md.offsetVector[stack.currentFrame->locals.offset+1] = stack.currentFrame->args.subjectPtr - md.startSubject;
-                        if (stack.currentFrame->args.offsetTop <= stack.currentFrame->locals.offset)
-                            stack.currentFrame->args.offsetTop = stack.currentFrame->locals.offset + 2;
-                    }
-                }
-                
-                /* For a non-repeating ket, just continue at this level. This also
-                 happens for a repeating ket if no characters were matched in the group.
-                 This is the forcible breaking of infinite loops as implemented in Perl
-                 5.005. If there is an options reset, it will get obeyed in the normal
-                 course of events. */
-                
-                if (*stack.currentFrame->args.instructionPtr == OP_KET || stack.currentFrame->args.subjectPtr == stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                    stack.currentFrame->args.instructionPtr += 1 + LINK_SIZE;
-                    NEXT_OPCODE;
-                }
-                
-                /* The repeating kets try the rest of the pattern or restart from the
-                 preceding bracket, in the appropriate order. */
-                
-                if (*stack.currentFrame->args.instructionPtr == OP_KETRMIN) {
-                    RECURSIVE_MATCH(16, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                    RECURSIVE_MATCH_NEW_GROUP(17, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                } else { /* OP_KETRMAX */
-                    RECURSIVE_MATCH_NEW_GROUP(18, stack.currentFrame->locals.instructionPtrAtStartOfOnce, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                    RECURSIVE_MATCH(19, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                    if (isMatch)
-                        RRETURN;
-                }
-                RRETURN;
-                
-            /* Start of subject. */
-
-            BEGIN_OPCODE(CIRC):
-                if (stack.currentFrame->args.subjectPtr != md.startSubject)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            /* After internal newline if multiline. */
-
-            BEGIN_OPCODE(BOL):
-                if (stack.currentFrame->args.subjectPtr != md.startSubject && !isNewline(stack.currentFrame->args.subjectPtr[-1]))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            /* End of subject. */
-
-            BEGIN_OPCODE(DOLL):
-                if (stack.currentFrame->args.subjectPtr < md.endSubject)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            /* Before internal newline if multiline. */
-
-            BEGIN_OPCODE(EOL):
-                if (stack.currentFrame->args.subjectPtr < md.endSubject && !isNewline(*stack.currentFrame->args.subjectPtr))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            /* Word boundary assertions */
-                
-            BEGIN_OPCODE(NOT_WORD_BOUNDARY):
-            BEGIN_OPCODE(WORD_BOUNDARY): {
-                bool currentCharIsWordChar = false;
-                bool previousCharIsWordChar = false;
-                
-                if (stack.currentFrame->args.subjectPtr > md.startSubject)
-                    previousCharIsWordChar = isWordChar(stack.currentFrame->args.subjectPtr[-1]);
-                if (stack.currentFrame->args.subjectPtr < md.endSubject)
-                    currentCharIsWordChar = isWordChar(*stack.currentFrame->args.subjectPtr);
-                
-                /* Now see if the situation is what we want */
-                bool wordBoundaryDesired = (*stack.currentFrame->args.instructionPtr++ == OP_WORD_BOUNDARY);
-                if (wordBoundaryDesired ? currentCharIsWordChar == previousCharIsWordChar : currentCharIsWordChar != previousCharIsWordChar)
-                    RRETURN_NO_MATCH;
-                NEXT_OPCODE;
-            }
-                
-            /* Match a single character type; inline for speed */
-                
-            BEGIN_OPCODE(NOT_NEWLINE):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isNewline(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(NOT_DIGIT):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isASCIIDigit(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(DIGIT):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (!isASCIIDigit(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(NOT_WHITESPACE):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isSpaceChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-
-            BEGIN_OPCODE(WHITESPACE):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (!isSpaceChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            BEGIN_OPCODE(NOT_WORDCHAR):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (isWordChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            BEGIN_OPCODE(WORDCHAR):
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (!isWordChar(*stack.currentFrame->args.subjectPtr++))
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr++;
-                NEXT_OPCODE;
-                
-            /* Match a back reference, possibly repeatedly. Look past the end of the
-             item to see if there is repeat information following. The code is similar
-             to that for character classes, but repeated for efficiency. Then obey
-             similar code to character type repeats - written out again for speed.
-             However, if the referenced string is the empty string, always treat
-             it as matched, any number of times (otherwise there could be infinite
-             loops). */
-                
-            BEGIN_OPCODE(REF):
-                stack.currentFrame->locals.offset = get2ByteValue(stack.currentFrame->args.instructionPtr + 1) << 1;               /* Doubled ref number */
-                stack.currentFrame->args.instructionPtr += 3;                                 /* Advance past item */
-                
-                /* If the reference is unset, set the length to be longer than the amount
-                 of subject left; this ensures that every attempt at a match fails. We
-                 can't just fail here, because of the possibility of quantifiers with zero
-                 minima. */
-                
-                if (stack.currentFrame->locals.offset >= stack.currentFrame->args.offsetTop || md.offsetVector[stack.currentFrame->locals.offset] < 0)
-                    stack.currentFrame->locals.length = 0;
-                else
-                    stack.currentFrame->locals.length = md.offsetVector[stack.currentFrame->locals.offset+1] - md.offsetVector[stack.currentFrame->locals.offset];
-                
-                /* Set up for repetition, or handle the non-repeated case */
-                
-                switch (*stack.currentFrame->args.instructionPtr) {
-                    case OP_CRSTAR:
-                    case OP_CRMINSTAR:
-                    case OP_CRPLUS:
-                    case OP_CRMINPLUS:
-                    case OP_CRQUERY:
-                    case OP_CRMINQUERY:
-                        repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
-                        break;
-                        
-                    case OP_CRRANGE:
-                    case OP_CRMINRANGE:
-                        minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
-                        min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                        stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
-                        if (stack.currentFrame->locals.max == 0)
-                            stack.currentFrame->locals.max = INT_MAX;
-                        stack.currentFrame->args.instructionPtr += 5;
-                        break;
-                    
-                    default:               /* No repeat follows */
-                        if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                            RRETURN_NO_MATCH;
-                        stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                        NEXT_OPCODE;
-                }
-                
-                /* If the length of the reference is zero, just continue with the
-                 main loop. */
-                
-                if (stack.currentFrame->locals.length == 0)
-                    NEXT_OPCODE;
-                
-                /* First, ensure the minimum number of matches are present. */
-                
-                for (int i = 1; i <= min; i++) {
-                    if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                        RRETURN_NO_MATCH;
-                    stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                }
-                
-                /* If min = max, continue at the same level without recursion.
-                 They are not both allowed to be zero. */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;
-                
-                /* If minimizing, keep trying and advancing the pointer */
-                
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(20, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || !matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                            RRETURN;
-                        stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* If maximizing, find the longest string and work backwards */
-                
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                    for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                        if (!matchRef(stack.currentFrame->locals.offset, stack.currentFrame->args.subjectPtr, stack.currentFrame->locals.length, md))
-                            break;
-                        stack.currentFrame->args.subjectPtr += stack.currentFrame->locals.length;
-                    }
-                    while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                        RECURSIVE_MATCH(21, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        stack.currentFrame->args.subjectPtr -= stack.currentFrame->locals.length;
-                    }
-                    RRETURN_NO_MATCH;
-                }
-                /* Control never reaches here */
-                
-            /* Match a bit-mapped character class, possibly repeatedly. This op code is
-             used when all the characters in the class have values in the range 0-255,
-             and either the matching is caseful, or the characters are in the range
-             0-127 when UTF-8 processing is enabled. The only difference between
-             OP_CLASS and OP_NCLASS occurs when a data character outside the range is
-             encountered.
-             
-             First, look past the end of the item to see if there is repeat information
-             following. Then obey similar code to character type repeats - written out
-             again for speed. */
-                
-            BEGIN_OPCODE(NCLASS):
-            BEGIN_OPCODE(CLASS):
-                stack.currentFrame->locals.data = stack.currentFrame->args.instructionPtr + 1;                /* Save for matching */
-                stack.currentFrame->args.instructionPtr += 33;                     /* Advance past the item */
-                
-                switch (*stack.currentFrame->args.instructionPtr) {
-                    case OP_CRSTAR:
-                    case OP_CRMINSTAR:
-                    case OP_CRPLUS:
-                    case OP_CRMINPLUS:
-                    case OP_CRQUERY:
-                    case OP_CRMINQUERY:
-                        repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
-                        break;
-                        
-                    case OP_CRRANGE:
-                    case OP_CRMINRANGE:
-                        minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
-                        min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                        stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
-                        if (stack.currentFrame->locals.max == 0)
-                            stack.currentFrame->locals.max = INT_MAX;
-                        stack.currentFrame->args.instructionPtr += 5;
-                        break;
-                        
-                    default:               /* No repeat follows */
-                        min = stack.currentFrame->locals.max = 1;
-                        break;
-                }
-                
-                /* First, ensure the minimum number of matches are present. */
-                
-                for (int i = 1; i <= min; i++) {
-                    if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                        RRETURN_NO_MATCH;
-                    int c = *stack.currentFrame->args.subjectPtr++;
-                    if (c > 255) {
-                        if (stack.currentFrame->locals.data[-1] == OP_CLASS)
-                            RRETURN_NO_MATCH;
-                    } else {
-                        if (!(stack.currentFrame->locals.data[c / 8] & (1 << (c & 7))))
-                            RRETURN_NO_MATCH;
-                    }
-                }
-                
-                /* If max == min we can continue with the main loop without the
-                 need to recurse. */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;      
-                
-                /* If minimizing, keep testing the rest of the expression and advancing
-                 the pointer while it matches the class. */
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(22, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            RRETURN;
-                        int c = *stack.currentFrame->args.subjectPtr++;
-                        if (c > 255) {
-                            if (stack.currentFrame->locals.data[-1] == OP_CLASS)
-                                RRETURN;
-                        } else {
-                            if ((stack.currentFrame->locals.data[c/8] & (1 << (c&7))) == 0)
-                                RRETURN;
-                        }
-                    }
-                    /* Control never reaches here */
-                }
-                /* If maximizing, find the longest possible run, then work backwards. */
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                    
-                    for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                        if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            break;
-                        int c = *stack.currentFrame->args.subjectPtr;
-                        if (c > 255) {
-                            if (stack.currentFrame->locals.data[-1] == OP_CLASS)
-                                break;
-                        } else {
-                            if (!(stack.currentFrame->locals.data[c / 8] & (1 << (c & 7))))
-                                break;
-                        }
-                        ++stack.currentFrame->args.subjectPtr;
-                    }
-                    for (;;) {
-                        RECURSIVE_MATCH(24, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                            break;        /* Stop if tried at original pos */
-                    }
-                    
-                    RRETURN;
-                }
-                /* Control never reaches here */
-                
-            /* Match an extended character class. */
-                
-            BEGIN_OPCODE(XCLASS):
-                stack.currentFrame->locals.data = stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE;                /* Save for matching */
-                stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);                      /* Advance past the item */
-                
-                switch (*stack.currentFrame->args.instructionPtr) {
-                    case OP_CRSTAR:
-                    case OP_CRMINSTAR:
-                    case OP_CRPLUS:
-                    case OP_CRMINPLUS:
-                    case OP_CRQUERY:
-                    case OP_CRMINQUERY:
-                        repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_CRSTAR, minimize, min, stack.currentFrame->locals.max);
-                        break;
-                        
-                    case OP_CRRANGE:
-                    case OP_CRMINRANGE:
-                        minimize = (*stack.currentFrame->args.instructionPtr == OP_CRMINRANGE);
-                        min = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                        stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 3);
-                        if (stack.currentFrame->locals.max == 0)
-                            stack.currentFrame->locals.max = INT_MAX;
-                        stack.currentFrame->args.instructionPtr += 5;
-                        break;
-                        
-                    default:               /* No repeat follows */
-                        min = stack.currentFrame->locals.max = 1;
-                }
-                
-                /* First, ensure the minimum number of matches are present. */
-                
-                for (int i = 1; i <= min; i++) {
-                    if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                        RRETURN_NO_MATCH;
-                    int c = *stack.currentFrame->args.subjectPtr++;
-                    if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data))
-                        RRETURN_NO_MATCH;
-                }
-                
-                /* If max == min we can continue with the main loop without the
-                 need to recurse. */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;
-                
-                /* If minimizing, keep testing the rest of the expression and advancing
-                 the pointer while it matches the class. */
-                
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(26, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            RRETURN;
-                        int c = *stack.currentFrame->args.subjectPtr++;
-                        if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data))
-                            RRETURN;
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* If maximizing, find the longest possible run, then work backwards. */
-                
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                    for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                        if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            break;
-                        int c = *stack.currentFrame->args.subjectPtr;
-                        if (!jsc_pcre_xclass(c, stack.currentFrame->locals.data))
-                            break;
-                        ++stack.currentFrame->args.subjectPtr;
-                    }
-                    for(;;) {
-                        RECURSIVE_MATCH(27, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                            break;        /* Stop if tried at original pos */
-                    }
-                    RRETURN;
-                }
-                
-                /* Control never reaches here */
-                
-            /* Match a single character, casefully */
-                
-            BEGIN_OPCODE(CHAR):
-                stack.currentFrame->locals.length = 1;
-                stack.currentFrame->args.instructionPtr++;
-                getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
-                stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                if (stack.currentFrame->locals.fc != *stack.currentFrame->args.subjectPtr++)
-                    RRETURN_NO_MATCH;
-                NEXT_OPCODE;
-                
-            /* Match a single character, caselessly */
-                
-            BEGIN_OPCODE(CHAR_IGNORING_CASE): {
-                stack.currentFrame->locals.length = 1;
-                stack.currentFrame->args.instructionPtr++;
-                getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
-                stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                int dc = *stack.currentFrame->args.subjectPtr++;
-                if (stack.currentFrame->locals.fc != dc && jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) != dc)
-                    RRETURN_NO_MATCH;
-                NEXT_OPCODE;
-            }
-                
-            /* Match a single ASCII character. */
-                
-            BEGIN_OPCODE(ASCII_CHAR):
-                if (md.endSubject == stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->args.instructionPtr[1])
-                    RRETURN_NO_MATCH;
-                ++stack.currentFrame->args.subjectPtr;
-                stack.currentFrame->args.instructionPtr += 2;
-                NEXT_OPCODE;
-                
-            /* Match one of two cases of an ASCII letter. */
-                
-            BEGIN_OPCODE(ASCII_LETTER_IGNORING_CASE):
-                if (md.endSubject == stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                if ((*stack.currentFrame->args.subjectPtr | 0x20) != stack.currentFrame->args.instructionPtr[1])
-                    RRETURN_NO_MATCH;
-                ++stack.currentFrame->args.subjectPtr;
-                stack.currentFrame->args.instructionPtr += 2;
-                NEXT_OPCODE;
-                
-            /* Match a single character repeatedly; different opcodes share code. */
-                
-            BEGIN_OPCODE(EXACT):
-                min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = false;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATCHAR;
-                
-            BEGIN_OPCODE(UPTO):
-            BEGIN_OPCODE(MINUPTO):
-                min = 0;
-                stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = *stack.currentFrame->args.instructionPtr == OP_MINUPTO;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATCHAR;
-                
-            BEGIN_OPCODE(STAR):
-            BEGIN_OPCODE(MINSTAR):
-            BEGIN_OPCODE(PLUS):
-            BEGIN_OPCODE(MINPLUS):
-            BEGIN_OPCODE(QUERY):
-            BEGIN_OPCODE(MINQUERY):
-                repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_STAR, minimize, min, stack.currentFrame->locals.max);
-                
-                /* Common code for all repeated single-character matches. We can give
-                 up quickly if there are fewer than the minimum number of characters left in
-                 the subject. */
-                
-            REPEATCHAR:
-                
-                stack.currentFrame->locals.length = 1;
-                getUTF8CharAndIncrementLength(stack.currentFrame->locals.fc, stack.currentFrame->args.instructionPtr, stack.currentFrame->locals.length);
-                if (min * (stack.currentFrame->locals.fc > 0xFFFF ? 2 : 1) > md.endSubject - stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->args.instructionPtr += stack.currentFrame->locals.length;
-                
-                if (stack.currentFrame->locals.fc <= 0xFFFF) {
-                    othercase = md.ignoreCase ? jsc_pcre_ucp_othercase(stack.currentFrame->locals.fc) : -1;
-                    
-                    for (int i = 1; i <= min; i++) {
-                        if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
-                            RRETURN_NO_MATCH;
-                        ++stack.currentFrame->args.subjectPtr;
-                    }
-                    
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;
-                    
-                    if (minimize) {
-                        stack.currentFrame->locals.repeatOthercase = othercase;
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(28, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                RRETURN;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.repeatOthercase)
-                                RRETURN;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        /* Control never reaches here */
-                    } else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                break;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc && *stack.currentFrame->args.subjectPtr != othercase)
-                                break;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                            RECURSIVE_MATCH(29, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            --stack.currentFrame->args.subjectPtr;
-                        }
-                        RRETURN_NO_MATCH;
-                    }
-                    /* Control never reaches here */
-                } else {
-                    /* No case on surrogate pairs, so no need to bother with "othercase". */
-                    
-                    for (int i = 1; i <= min; i++) {
-                        if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
-                            RRETURN_NO_MATCH;
-                        stack.currentFrame->args.subjectPtr += 2;
-                    }
-                    
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;
-                    
-                    if (minimize) {
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(30, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                RRETURN;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
-                                RRETURN;
-                            stack.currentFrame->args.subjectPtr += 2;
-                        }
-                        /* Control never reaches here */
-                    } else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr > md.endSubject - 2)
-                                break;
-                            if (*stack.currentFrame->args.subjectPtr != stack.currentFrame->locals.fc)
-                                break;
-                            stack.currentFrame->args.subjectPtr += 2;
-                        }
-                        while (stack.currentFrame->args.subjectPtr >= stack.currentFrame->locals.subjectPtrAtStartOfInstruction) {
-                            RECURSIVE_MATCH(31, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            stack.currentFrame->args.subjectPtr -= 2;
-                        }
-                        RRETURN_NO_MATCH;
-                    }
-                    /* Control never reaches here */
-                }
-                /* Control never reaches here */
-                
-            /* Match a negated single one-byte character. */
-                
-            BEGIN_OPCODE(NOT): {
-                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                    RRETURN_NO_MATCH;
-                int b = stack.currentFrame->args.instructionPtr[1];
-                int c = *stack.currentFrame->args.subjectPtr++;
-                stack.currentFrame->args.instructionPtr += 2;
-                if (md.ignoreCase) {
-                    if (c < 128)
-                        c = toLowerCase(c);
-                    if (toLowerCase(b) == c)
-                        RRETURN_NO_MATCH;
-                } else {
-                    if (b == c)
-                        RRETURN_NO_MATCH;
-                }
-                NEXT_OPCODE;
-            }
-                
-            /* Match a negated single one-byte character repeatedly. This is almost a
-             repeat of the code for a repeated single character, but I haven't found a
-             nice way of commoning these up that doesn't require a test of the
-             positive/negative option for each character match. Maybe that wouldn't add
-             very much to the time taken, but character matching *is* what this is all
-             about... */
-                
-            BEGIN_OPCODE(NOTEXACT):
-                min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = false;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATNOTCHAR;
-                
-            BEGIN_OPCODE(NOTUPTO):
-            BEGIN_OPCODE(NOTMINUPTO):
-                min = 0;
-                stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = *stack.currentFrame->args.instructionPtr == OP_NOTMINUPTO;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATNOTCHAR;
-                
-            BEGIN_OPCODE(NOTSTAR):
-            BEGIN_OPCODE(NOTMINSTAR):
-            BEGIN_OPCODE(NOTPLUS):
-            BEGIN_OPCODE(NOTMINPLUS):
-            BEGIN_OPCODE(NOTQUERY):
-            BEGIN_OPCODE(NOTMINQUERY):
-                repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_NOTSTAR, minimize, min, stack.currentFrame->locals.max);
-                
-            /* Common code for all repeated single-byte matches. We can give up quickly
-             if there are fewer than the minimum number of bytes left in the
-             subject. */
-                
-            REPEATNOTCHAR:
-                if (min > md.endSubject - stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                stack.currentFrame->locals.fc = *stack.currentFrame->args.instructionPtr++;
-                
-                /* The code is duplicated for the caseless and caseful cases, for speed,
-                 since matching characters is likely to be quite common. First, ensure the
-                 minimum number of matches are present. If min = max, continue at the same
-                 level without recursing. Otherwise, if minimizing, keep trying the rest of
-                 the expression and advancing one matching character if failing, up to the
-                 maximum. Alternatively, if maximizing, find the maximum number of
-                 characters and work backwards. */
-                
-                DPRINTF(("negative matching %c{%d,%d}\n", stack.currentFrame->locals.fc, min, stack.currentFrame->locals.max));
-                
-                if (md.ignoreCase) {
-                    if (stack.currentFrame->locals.fc < 128)
-                        stack.currentFrame->locals.fc = toLowerCase(stack.currentFrame->locals.fc);
-                    
-                    for (int i = 1; i <= min; i++) {
-                        int d = *stack.currentFrame->args.subjectPtr++;
-                        if (d < 128)
-                            d = toLowerCase(d);
-                        if (stack.currentFrame->locals.fc == d)
-                            RRETURN_NO_MATCH;
-                    }
-                    
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;      
-                    
-                    if (minimize) {
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(38, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            int d = *stack.currentFrame->args.subjectPtr++;
-                            if (d < 128)
-                                d = toLowerCase(d);
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject || stack.currentFrame->locals.fc == d)
-                                RRETURN;
-                        }
-                        /* Control never reaches here */
-                    }
-                    
-                    /* Maximize case */
-                    
-                    else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                break;
-                            int d = *stack.currentFrame->args.subjectPtr;
-                            if (d < 128)
-                                d = toLowerCase(d);
-                            if (stack.currentFrame->locals.fc == d)
-                                break;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        for (;;) {
-                            RECURSIVE_MATCH(40, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                                break;        /* Stop if tried at original pos */
-                        }
-                        
-                        RRETURN;
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* Caseful comparisons */
-                
-                else {
-                    for (int i = 1; i <= min; i++) {
-                        int d = *stack.currentFrame->args.subjectPtr++;
-                        if (stack.currentFrame->locals.fc == d)
-                            RRETURN_NO_MATCH;
-                    }
-
-                    if (min == stack.currentFrame->locals.max)
-                        NEXT_OPCODE;
-                    
-                    if (minimize) {
-                        for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                            RECURSIVE_MATCH(42, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            int d = *stack.currentFrame->args.subjectPtr++;
-                            if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject || stack.currentFrame->locals.fc == d)
-                                RRETURN;
-                        }
-                        /* Control never reaches here */
-                    }
-                    
-                    /* Maximize case */
-                    
-                    else {
-                        stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;
-                        
-                        for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                            if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                break;
-                            int d = *stack.currentFrame->args.subjectPtr;
-                            if (stack.currentFrame->locals.fc == d)
-                                break;
-                            ++stack.currentFrame->args.subjectPtr;
-                        }
-                        for (;;) {
-                            RECURSIVE_MATCH(44, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                            if (isMatch)
-                                RRETURN;
-                            if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                                break;        /* Stop if tried at original pos */
-                        }
-
-                        RRETURN;
-                    }
-                }
-                /* Control never reaches here */
-                
-            /* Match a single character type repeatedly; several different opcodes
-             share code. This is very similar to the code for single characters, but we
-             repeat it in the interests of efficiency. */
-                
-            BEGIN_OPCODE(TYPEEXACT):
-                min = stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = true;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATTYPE;
-                
-            BEGIN_OPCODE(TYPEUPTO):
-            BEGIN_OPCODE(TYPEMINUPTO):
-                min = 0;
-                stack.currentFrame->locals.max = get2ByteValue(stack.currentFrame->args.instructionPtr + 1);
-                minimize = *stack.currentFrame->args.instructionPtr == OP_TYPEMINUPTO;
-                stack.currentFrame->args.instructionPtr += 3;
-                goto REPEATTYPE;
-                
-            BEGIN_OPCODE(TYPESTAR):
-            BEGIN_OPCODE(TYPEMINSTAR):
-            BEGIN_OPCODE(TYPEPLUS):
-            BEGIN_OPCODE(TYPEMINPLUS):
-            BEGIN_OPCODE(TYPEQUERY):
-            BEGIN_OPCODE(TYPEMINQUERY):
-                repeatInformationFromInstructionOffset(*stack.currentFrame->args.instructionPtr++ - OP_TYPESTAR, minimize, min, stack.currentFrame->locals.max);
-                
-                /* Common code for all repeated single character type matches. Note that
-                 in UTF-8 mode, '.' matches a character of any length, but for the other
-                 character types, the valid characters are all one-byte long. */
-                
-            REPEATTYPE:
-                stack.currentFrame->locals.ctype = *stack.currentFrame->args.instructionPtr++;      /* Code for the character type */
-                
-                /* First, ensure the minimum number of matches are present. Use inline
-                 code for maximizing the speed, and do the type test once at the start
-                 (i.e. keep it out of the loop). Also we can test that there are at least
-                 the minimum number of characters before we start. */
-                
-                if (min > md.endSubject - stack.currentFrame->args.subjectPtr)
-                    RRETURN_NO_MATCH;
-                if (min > 0) {
-                    switch (stack.currentFrame->locals.ctype) {
-                        case OP_NOT_NEWLINE:
-                            for (int i = 1; i <= min; i++) {
-                                if (isNewline(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_DIGIT:
-                            for (int i = 1; i <= min; i++) {
-                                if (isASCIIDigit(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_DIGIT:
-                            for (int i = 1; i <= min; i++) {
-                                if (!isASCIIDigit(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WHITESPACE:
-                            for (int i = 1; i <= min; i++) {
-                                if (isSpaceChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WHITESPACE:
-                            for (int i = 1; i <= min; i++) {
-                                if (!isSpaceChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WORDCHAR:
-                            for (int i = 1; i <= min; i++) {
-                                if (isWordChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WORDCHAR:
-                            for (int i = 1; i <= min; i++) {
-                                if (!isWordChar(*stack.currentFrame->args.subjectPtr))
-                                    RRETURN_NO_MATCH;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        default:
-                            ASSERT_NOT_REACHED();
-                            return matchError(JSRegExpErrorInternal, stack);
-                    }  /* End switch(stack.currentFrame->locals.ctype) */
-                }
-                
-                /* If min = max, continue at the same level without recursing */
-                
-                if (min == stack.currentFrame->locals.max)
-                    NEXT_OPCODE;    
-                
-                /* If minimizing, we have to test the rest of the pattern before each
-                 subsequent match. */
-                
-                if (minimize) {
-                    for (stack.currentFrame->locals.fi = min;; stack.currentFrame->locals.fi++) {
-                        RECURSIVE_MATCH(48, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->locals.fi >= stack.currentFrame->locals.max || stack.currentFrame->args.subjectPtr >= md.endSubject)
-                            RRETURN;
-                        
-                        int c = *stack.currentFrame->args.subjectPtr++;
-                        switch (stack.currentFrame->locals.ctype) {
-                            case OP_NOT_NEWLINE:
-                                if (isNewline(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_NOT_DIGIT:
-                                if (isASCIIDigit(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_DIGIT:
-                                if (!isASCIIDigit(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_NOT_WHITESPACE:
-                                if (isSpaceChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_WHITESPACE:
-                                if (!isSpaceChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_NOT_WORDCHAR:
-                                if (isWordChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            case OP_WORDCHAR:
-                                if (!isWordChar(c))
-                                    RRETURN;
-                                break;
-                                
-                            default:
-                                ASSERT_NOT_REACHED();
-                                return matchError(JSRegExpErrorInternal, stack);
-                        }
-                    }
-                    /* Control never reaches here */
-                }
-                
-                /* If maximizing it is worth using inline code for speed, doing the type
-                 test once at the start (i.e. keep it out of the loop). */
-                
-                else {
-                    stack.currentFrame->locals.subjectPtrAtStartOfInstruction = stack.currentFrame->args.subjectPtr;  /* Remember where we started */
-                    
-                    switch (stack.currentFrame->locals.ctype) {
-                        case OP_NOT_NEWLINE:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject || isNewline(*stack.currentFrame->args.subjectPtr))
-                                    break;
-                                stack.currentFrame->args.subjectPtr++;
-                            }
-                            break;
-                            
-                        case OP_NOT_DIGIT:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (isASCIIDigit(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_DIGIT:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (!isASCIIDigit(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WHITESPACE:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (isSpaceChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WHITESPACE:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (!isSpaceChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_NOT_WORDCHAR:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (isWordChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        case OP_WORDCHAR:
-                            for (int i = min; i < stack.currentFrame->locals.max; i++) {
-                                if (stack.currentFrame->args.subjectPtr >= md.endSubject)
-                                    break;
-                                int c = *stack.currentFrame->args.subjectPtr;
-                                if (!isWordChar(c))
-                                    break;
-                                ++stack.currentFrame->args.subjectPtr;
-                            }
-                            break;
-                            
-                        default:
-                            ASSERT_NOT_REACHED();
-                            return matchError(JSRegExpErrorInternal, stack);
-                    }
-                    
-                    /* stack.currentFrame->args.subjectPtr is now past the end of the maximum run */
-                    
-                    for (;;) {
-                        RECURSIVE_MATCH(52, stack.currentFrame->args.instructionPtr, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        if (stack.currentFrame->args.subjectPtr-- == stack.currentFrame->locals.subjectPtrAtStartOfInstruction)
-                            break;        /* Stop if tried at original pos */
-                    }
-                    
-                    /* Get here if we can't make it match with any permitted repetitions */
-                    
-                    RRETURN;
-                }
-                /* Control never reaches here */
-                
-            BEGIN_OPCODE(CRMINPLUS):
-            BEGIN_OPCODE(CRMINQUERY):
-            BEGIN_OPCODE(CRMINRANGE):
-            BEGIN_OPCODE(CRMINSTAR):
-            BEGIN_OPCODE(CRPLUS):
-            BEGIN_OPCODE(CRQUERY):
-            BEGIN_OPCODE(CRRANGE):
-            BEGIN_OPCODE(CRSTAR):
-                ASSERT_NOT_REACHED();
-                return matchError(JSRegExpErrorInternal, stack);
-                
-#ifdef USE_COMPUTED_GOTO_FOR_MATCH_OPCODE_LOOP
-            CAPTURING_BRACKET:
-#else
-            default:
-#endif
-                /* Opening capturing bracket. If there is space in the offset vector, save
-                 the current subject position in the working slot at the top of the vector. We
-                 mustn't change the current values of the data slot, because they may be set
-                 from a previous iteration of this group, and be referred to by a reference
-                 inside the group.
-                 
-                 If the bracket fails to match, we need to restore this value and also the
-                 values of the final offsets, in case they were set by a previous iteration of
-                 the same bracket.
-                 
-                 If there isn't enough space in the offset vector, treat this as if it were a
-                 non-capturing bracket. Don't worry about setting the flag for the error case
-                 here; that is handled in the code for KET. */
-                
-                ASSERT(*stack.currentFrame->args.instructionPtr > OP_BRA);
-                
-                stack.currentFrame->locals.number = *stack.currentFrame->args.instructionPtr - OP_BRA;
-                
-                /* For extended extraction brackets (large number), we have to fish out the
-                 number from a dummy opcode at the start. */
-                
-                if (stack.currentFrame->locals.number > EXTRACT_BASIC_MAX)
-                    stack.currentFrame->locals.number = get2ByteValue(stack.currentFrame->args.instructionPtr + 2 + LINK_SIZE);
-                stack.currentFrame->locals.offset = stack.currentFrame->locals.number << 1;
-                
-#ifdef DEBUG
-                printf("start bracket %d subject=", stack.currentFrame->locals.number);
-                pchars(stack.currentFrame->args.subjectPtr, 16, true, md);
-                printf("\n");
-#endif
-                
-                if (stack.currentFrame->locals.offset < md.offsetMax) {
-                    stack.currentFrame->locals.saveOffset1 = md.offsetVector[stack.currentFrame->locals.offset];
-                    stack.currentFrame->locals.saveOffset2 = md.offsetVector[stack.currentFrame->locals.offset + 1];
-                    stack.currentFrame->locals.saveOffset3 = md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number];
-                    
-                    DPRINTF(("saving %d %d %d\n", stack.currentFrame->locals.saveOffset1, stack.currentFrame->locals.saveOffset2, stack.currentFrame->locals.saveOffset3));
-                    md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->args.subjectPtr - md.startSubject;
-                    
-                    do {
-                        RECURSIVE_MATCH_NEW_GROUP(1, stack.currentFrame->args.instructionPtr + 1 + LINK_SIZE, stack.currentFrame->args.bracketChain);
-                        if (isMatch)
-                            RRETURN;
-                        stack.currentFrame->args.instructionPtr += getLinkValue(stack.currentFrame->args.instructionPtr + 1);
-                    } while (*stack.currentFrame->args.instructionPtr == OP_ALT);
-                    
-                    DPRINTF(("bracket %d failed\n", stack.currentFrame->locals.number));
-                    
-                    md.offsetVector[stack.currentFrame->locals.offset] = stack.currentFrame->locals.saveOffset1;
-                    md.offsetVector[stack.currentFrame->locals.offset + 1] = stack.currentFrame->locals.saveOffset2;
-                    md.offsetVector[md.offsetEnd - stack.currentFrame->locals.number] = stack.currentFrame->locals.saveOffset3;
-                    
-                    RRETURN;
-                }
-                
-                /* Insufficient room for saving captured contents */
-                
-                goto NON_CAPTURING_BRACKET;
-        }
-        
-        /* Do not stick any code in here without much thought; it is assumed
-         that "continue" in the code above comes out to here to repeat the main
-         loop. */
-        
-    } /* End of main loop */
-    
-    ASSERT_NOT_REACHED();
-    
-#ifndef USE_COMPUTED_GOTO_FOR_MATCH_RECURSION
-    
-RRETURN_SWITCH:
-    switch (stack.currentFrame->returnLocation) {
-        case 0: goto RETURN;
-        case 1: goto RRETURN_1;
-        case 2: goto RRETURN_2;
-        case 6: goto RRETURN_6;
-        case 7: goto RRETURN_7;
-        case 14: goto RRETURN_14;
-        case 15: goto RRETURN_15;
-        case 16: goto RRETURN_16;
-        case 17: goto RRETURN_17;
-        case 18: goto RRETURN_18;
-        case 19: goto RRETURN_19;
-        case 20: goto RRETURN_20;
-        case 21: goto RRETURN_21;
-        case 22: goto RRETURN_22;
-        case 24: goto RRETURN_24;
-        case 26: goto RRETURN_26;
-        case 27: goto RRETURN_27;
-        case 28: goto RRETURN_28;
-        case 29: goto RRETURN_29;
-        case 30: goto RRETURN_30;
-        case 31: goto RRETURN_31;
-        case 38: goto RRETURN_38;
-        case 40: goto RRETURN_40;
-        case 42: goto RRETURN_42;
-        case 44: goto RRETURN_44;
-        case 48: goto RRETURN_48;
-        case 52: goto RRETURN_52;
-    }
-    
-    ASSERT_NOT_REACHED();
-    return matchError(JSRegExpErrorInternal, stack);
-    
-#endif
-    
-RETURN:
-    return isMatch;
-}
-
-
-/*************************************************
-*         Execute a Regular Expression           *
-*************************************************/
-
-/* This function applies a compiled re to a subject string and picks out
-portions of the string if it matches. Two elements in the vector are set for
-each substring: the offsets to the start and end of the substring.
-
-Arguments:
-  re              points to the compiled expression
-  extra_data      points to extra data or is NULL
-  subject         points to the subject string
-  length          length of subject string (may contain binary zeros)
-  start_offset    where to start in the subject string
-  options         option bits
-  offsets         points to a vector of ints to be filled in with offsets
-  offsetCount     the number of elements in the vector
-
-Returns:          > 0 => success; value is the number of elements filled in
-                  = 0 => success, but offsets is not big enough
-                   -1 => failed to match
-                 < -1 => some kind of unexpected problem
-*/
-
-static void tryFirstByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int firstByte, bool firstByteIsCaseless, bool useMultiLineFirstCharOptimization, const UChar* originalSubjectStart)
-{
-    // If firstByte is set, try scanning to the first instance of that byte
-    // no need to try and match against any earlier part of the subject string.
-    if (firstByte >= 0) {
-        UChar firstChar = firstByte;
-        if (firstByteIsCaseless)
-            while (subjectPtr < endSubject) {
-                int c = *subjectPtr;
-                if (c > 127)
-                    break;
-                if (toLowerCase(c) == firstChar)
-                    break;
-                subjectPtr++;
-            }
-        else {
-            while (subjectPtr < endSubject && *subjectPtr != firstChar)
-                subjectPtr++;
-        }
-    } else if (useMultiLineFirstCharOptimization) {
-        /* Or to just after \n for a multiline match if possible */
-        // I'm not sure why this != originalSubjectStart check is necessary -- ecs 11/18/07
-        if (subjectPtr > originalSubjectStart) {
-            while (subjectPtr < endSubject && !isNewline(subjectPtr[-1]))
-                subjectPtr++;
-        }
-    }
-}
-
-static bool tryRequiredByteOptimization(const UChar*& subjectPtr, const UChar* endSubject, int reqByte, int reqByte2, bool reqByteIsCaseless, bool hasFirstByte, const UChar*& reqBytePtr)
-{
-    /* If reqByte is set, we know that that character must appear in the subject
-     for the match to succeed. If the first character is set, reqByte must be
-     later in the subject; otherwise the test starts at the match point. This
-     optimization can save a huge amount of backtracking in patterns with nested
-     unlimited repeats that aren't going to match. Writing separate code for
-     cased/caseless versions makes it go faster, as does using an autoincrement
-     and backing off on a match.
-     
-     HOWEVER: when the subject string is very, very long, searching to its end can
-     take a long time, and give bad performance on quite ordinary patterns. This
-     showed up when somebody was matching /^C/ on a 32-megabyte string... so we
-     don't do this when the string is sufficiently long.
-    */
-
-    if (reqByte >= 0 && endSubject - subjectPtr < REQ_BYTE_MAX) {
-        const UChar* p = subjectPtr + (hasFirstByte ? 1 : 0);
-
-        /* We don't need to repeat the search if we haven't yet reached the
-         place we found it at last time. */
-
-        if (p > reqBytePtr) {
-            if (reqByteIsCaseless) {
-                while (p < endSubject) {
-                    int pp = *p++;
-                    if (pp == reqByte || pp == reqByte2) {
-                        p--;
-                        break;
-                    }
-                }
-            } else {
-                while (p < endSubject) {
-                    if (*p++ == reqByte) {
-                        p--;
-                        break;
-                    }
-                }
-            }
-
-            /* If we can't find the required character, break the matching loop */
-
-            if (p >= endSubject)
-                return true;
-
-            /* If we have found the required character, save the point where we
-             found it, so that we don't search again next time round the loop if
-             the start hasn't passed this character yet. */
-
-            reqBytePtr = p;
-        }
-    }
-    return false;
-}
-
-int jsRegExpExecute(const JSRegExp* re,
-                    const UChar* subject, int length, int start_offset, int* offsets,
-                    int offsetCount)
-{
-    ASSERT(re);
-    ASSERT(subject || !length);
-    ASSERT(offsetCount >= 0);
-    ASSERT(offsets || offsetCount == 0);
-
-    HistogramTimeLogger logger(re);
-
-    MatchData matchBlock;
-    matchBlock.startSubject = subject;
-    matchBlock.endSubject = matchBlock.startSubject + length;
-    const UChar* endSubject = matchBlock.endSubject;
-    
-    matchBlock.multiline = (re->options & MatchAcrossMultipleLinesOption);
-    matchBlock.ignoreCase = (re->options & IgnoreCaseOption);
-    
-    /* If the expression has got more back references than the offsets supplied can
-     hold, we get a temporary chunk of working store to use during the matching.
-     Otherwise, we can use the vector supplied, rounding down its size to a multiple
-     of 3. */
-    
-    int ocount = offsetCount - (offsetCount % 3);
-    
-    // FIXME: This is lame that we have to second-guess our caller here.
-    // The API should change to either fail-hard when we don't have enough offset space
-    // or that we shouldn't ask our callers to pre-allocate in the first place.
-    bool usingTemporaryOffsets = false;
-    if (re->topBackref > 0 && re->topBackref >= ocount/3) {
-        ocount = re->topBackref * 3 + 3;
-        matchBlock.offsetVector = new int[ocount];
-        if (!matchBlock.offsetVector)
-            return JSRegExpErrorNoMemory;
-        usingTemporaryOffsets = true;
-    } else
-        matchBlock.offsetVector = offsets;
-    
-    matchBlock.offsetEnd = ocount;
-    matchBlock.offsetMax = (2*ocount)/3;
-    matchBlock.offsetOverflow = false;
-    
-    /* Compute the minimum number of offsets that we need to reset each time. Doing
-     this makes a huge difference to execution time when there aren't many brackets
-     in the pattern. */
-    
-    int resetCount = 2 + re->topBracket * 2;
-    if (resetCount > offsetCount)
-        resetCount = ocount;
-    
-    /* Reset the working variable associated with each extraction. These should
-     never be used unless previously set, but they get saved and restored, and so we
-     initialize them to avoid reading uninitialized locations. */
-    
-    if (matchBlock.offsetVector) {
-        int* iptr = matchBlock.offsetVector + ocount;
-        int* iend = iptr - resetCount/2 + 1;
-        while (--iptr >= iend)
-            *iptr = -1;
-    }
-    
-    /* Set up the first character to match, if available. The firstByte value is
-     never set for an anchored regular expression, but the anchoring may be forced
-     at run time, so we have to test for anchoring. The first char may be unset for
-     an unanchored pattern, of course. If there's no first char and the pattern was
-     studied, there may be a bitmap of possible first characters. */
-    
-    bool firstByteIsCaseless = false;
-    int firstByte = -1;
-    if (re->options & UseFirstByteOptimizationOption) {
-        firstByte = re->firstByte & 255;
-        if ((firstByteIsCaseless = (re->firstByte & REQ_IGNORE_CASE)))
-            firstByte = toLowerCase(firstByte);
-    }
-    
-    /* For anchored or unanchored matches, there may be a "last known required
-     character" set. */
-    
-    bool reqByteIsCaseless = false;
-    int reqByte = -1;
-    int reqByte2 = -1;
-    if (re->options & UseRequiredByteOptimizationOption) {
-        reqByte = re->reqByte & 255; // FIXME: This optimization could be made to work for UTF16 chars as well...
-        reqByteIsCaseless = (re->reqByte & REQ_IGNORE_CASE);
-        reqByte2 = flipCase(reqByte);
-    }
-    
-    /* Loop for handling unanchored repeated matching attempts; for anchored regexs
-     the loop runs just once. */
-    
-    const UChar* startMatch = subject + start_offset;
-    const UChar* reqBytePtr = startMatch - 1;
-    bool useMultiLineFirstCharOptimization = re->options & UseMultiLineFirstByteOptimizationOption;
-    
-    do {
-        /* Reset the maximum number of extractions we might see. */
-        if (matchBlock.offsetVector) {
-            int* iptr = matchBlock.offsetVector;
-            int* iend = iptr + resetCount;
-            while (iptr < iend)
-                *iptr++ = -1;
-        }
-        
-        tryFirstByteOptimization(startMatch, endSubject, firstByte, firstByteIsCaseless, useMultiLineFirstCharOptimization, matchBlock.startSubject + start_offset);
-        if (tryRequiredByteOptimization(startMatch, endSubject, reqByte, reqByte2, reqByteIsCaseless, firstByte >= 0, reqBytePtr))
-            break;
-                
-        /* When a match occurs, substrings will be set for all internal extractions;
-         we just need to set up the whole thing as substring 0 before returning. If
-         there were too many extractions, set the return code to zero. In the case
-         where we had to get some local store to hold offsets for backreferences, copy
-         those back references that we can. In this case there need not be overflow
-         if certain parts of the pattern were not used. */
-        
-        /* The code starts after the JSRegExp block and the capture name table. */
-        const unsigned char* start_code = (const unsigned char*)(re + 1);
-        
-        int returnCode = match(startMatch, start_code, 2, matchBlock);
-        
-        /* When the result is no match, advance the pointer to the next character
-         and continue. */
-        if (returnCode == 0) {
-            startMatch++;
-            continue;
-        }
-
-        if (returnCode != 1) {
-            ASSERT(returnCode == JSRegExpErrorHitLimit || returnCode == JSRegExpErrorNoMemory);
-            DPRINTF((">>>> error: returning %d\n", returnCode));
-            return returnCode;
-        }
-        
-        /* We have a match! Copy the offset information from temporary store if
-         necessary */
-        
-        if (usingTemporaryOffsets) {
-            if (offsetCount >= 4) {
-                memcpy(offsets + 2, matchBlock.offsetVector + 2, (offsetCount - 2) * sizeof(int));
-                DPRINTF(("Copied offsets from temporary memory\n"));
-            }
-            if (matchBlock.endOffsetTop > offsetCount)
-                matchBlock.offsetOverflow = true;
-            
-            DPRINTF(("Freeing temporary memory\n"));
-            delete [] matchBlock.offsetVector;
-        }
-        
-        returnCode = matchBlock.offsetOverflow ? 0 : matchBlock.endOffsetTop / 2;
-        
-        if (offsetCount < 2)
-            returnCode = 0;
-        else {
-            offsets[0] = startMatch - matchBlock.startSubject;
-            offsets[1] = matchBlock.endMatchPtr - matchBlock.startSubject;
-        }
-        
-        DPRINTF((">>>> returning %d\n", returnCode));
-        return returnCode;
-    } while (!(re->options & IsAnchoredOption) && startMatch <= endSubject);
-    
-    if (usingTemporaryOffsets) {
-        DPRINTF(("Freeing temporary memory\n"));
-        delete [] matchBlock.offsetVector;
-    }
-    
-    DPRINTF((">>>> returning PCRE_ERROR_NOMATCH\n"));
-    return JSRegExpErrorNoMatch;
-}
-
-#if REGEXP_HISTOGRAM
-
-class CompareHistogramEntries {
-public:
-    bool operator()(const pair<UString, double>& a, const pair<UString, double>& b)
-    {
-        if (a.second == b.second)
-            return a.first < b.first;
-        return a.second < b.second;
-    }
-};
-
-Histogram::~Histogram()
-{
-    Vector<pair<UString, double> > values;
-    Map::iterator end = times.end();
-    for (Map::iterator it = times.begin(); it != end; ++it)
-        values.append(*it);
-    sort(values.begin(), values.end(), CompareHistogramEntries());
-    size_t size = values.size();
-    printf("Regular Expressions, sorted by time spent evaluating them:\n");
-    for (size_t i = 0; i < size; ++i)
-        printf("    %f - %s\n", values[size - i - 1].second, values[size - i - 1].first.UTF8String().c_str());
-}
-
-void Histogram::add(const JSRegExp* re, double elapsedTime)
-{
-    UString string(reinterpret_cast<const UChar*>(reinterpret_cast<const char*>(re) + re->stringOffset), re->stringLength);
-    if (re->options & IgnoreCaseOption && re->options & MatchAcrossMultipleLinesOption)
-        string += " (multi-line, ignore case)";
-    else {
-        if (re->options & IgnoreCaseOption)
-            string += " (ignore case)";
-        if (re->options & MatchAcrossMultipleLinesOption)
-            string += " (multi-line)";
-    }
-    pair<Map::iterator, bool> result = times.add(string.rep(), elapsedTime);
-    if (!result.second)
-        result.first->second += elapsedTime;
-}
-
-HistogramTimeLogger::HistogramTimeLogger(const JSRegExp* re)
-    : m_re(re)
-    , m_startTime(currentTimeMS())
-{
-}
-
-HistogramTimeLogger::~HistogramTimeLogger()
-{
-    static Histogram histogram;
-    histogram.add(m_re, currentTimeMS() - m_startTime);
-}
-
-#endif
diff --git a/pcre/pcre_internal.h b/pcre/pcre_internal.h
deleted file mode 100644 (file)
index 0016bb5..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 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:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-/* This header contains definitions that are shared between the different
-modules, but which are not relevant to the exported API. This includes some
-functions whose names all begin with "_pcre_". */
-
-#ifndef PCRE_INTERNAL_H
-#define PCRE_INTERNAL_H
-
-/* Bit definitions for entries in the pcre_ctypes table. */
-
-#define ctype_space   0x01
-#define ctype_xdigit  0x08
-#define ctype_word    0x10   /* alphameric or '_' */
-
-/* Offsets for the bitmap tables in pcre_cbits. Each table contains a set
-of bits for a class map. Some classes are built by combining these tables. */
-
-#define cbit_space     0      /* \s */
-#define cbit_digit    32      /* \d */
-#define cbit_word     64      /* \w */
-#define cbit_length   96      /* Length of the cbits table */
-
-/* Offsets of the various tables from the base tables pointer, and
-total length. */
-
-#define lcc_offset      0
-#define fcc_offset    128
-#define cbits_offset  256
-#define ctypes_offset (cbits_offset + cbit_length)
-#define tables_length (ctypes_offset + 128)
-
-#ifndef DFTABLES
-
-// Change the following to 1 to dump used regular expressions at process exit time.
-#define REGEXP_HISTOGRAM 0
-
-#include "Assertions.h"
-
-#if COMPILER(MSVC)
-#pragma warning(disable: 4232)
-#pragma warning(disable: 4244)
-#endif
-
-#include "pcre.h"
-
-/* The value of LINK_SIZE determines the number of bytes used to store links as
-offsets within the compiled regex. The default is 2, which allows for compiled
-patterns up to 64K long. */
-
-#define LINK_SIZE   3
-
-/* Define DEBUG to get debugging output on stdout. */
-
-#if 0
-#define DEBUG
-#endif
-
-/* Use a macro for debugging printing, 'cause that eliminates the use of #ifdef
-inline, and there are *still* stupid compilers about that don't like indented
-pre-processor statements, or at least there were when I first wrote this. After
-all, it had only been about 10 years then... */
-
-#ifdef DEBUG
-#define DPRINTF(p) printf p
-#else
-#define DPRINTF(p) /*nothing*/
-#endif
-
-/* PCRE keeps offsets in its compiled code as 2-byte quantities (always stored
-in big-endian order) by default. These are used, for example, to link from the
-start of a subpattern to its alternatives and its end. The use of 2 bytes per
-offset limits the size of the compiled regex to around 64K, which is big enough
-for almost everybody. However, I received a request for an even bigger limit.
-For this reason, and also to make the code easier to maintain, the storing and
-loading of offsets from the byte string is now handled by the functions that are
-defined here. */
-
-/* PCRE uses some other 2-byte quantities that do not change when the size of
-offsets changes. There are used for repeat counts and for other things such as
-capturing parenthesis numbers in back references. */
-
-static inline void put2ByteValue(unsigned char* opcodePtr, int value)
-{
-    ASSERT(value >= 0 && value <= 0xFFFF);
-    opcodePtr[0] = value >> 8;
-    opcodePtr[1] = value;
-}
-
-static inline void put3ByteValue(unsigned char* opcodePtr, int value)
-{
-    ASSERT(value >= 0 && value <= 0xFFFFFF);
-    opcodePtr[0] = value >> 16;
-    opcodePtr[1] = value >> 8;
-    opcodePtr[2] = value;
-}
-
-static inline int get2ByteValue(const unsigned char* opcodePtr)
-{
-    return (opcodePtr[0] << 8) | opcodePtr[1];
-}
-
-static inline int get3ByteValue(const unsigned char* opcodePtr)
-{
-    return (opcodePtr[0] << 16) | (opcodePtr[1] << 8) | opcodePtr[2];
-}
-
-static inline void put2ByteValueAndAdvance(unsigned char*& opcodePtr, int value)
-{
-    put2ByteValue(opcodePtr, value);
-    opcodePtr += 2;
-}
-
-static inline void put3ByteValueAndAdvance(unsigned char*& opcodePtr, int value)
-{
-    put3ByteValue(opcodePtr, value);
-    opcodePtr += 3;
-}
-
-static inline void putLinkValueAllowZero(unsigned char* opcodePtr, int value)
-{
-#if LINK_SIZE == 3
-    put3ByteValue(opcodePtr, value);
-#elif LINK_SIZE == 2
-    put2ByteValue(opcodePtr, value);
-#else
-#   error LINK_SIZE not supported.
-#endif
-}
-
-static inline int getLinkValueAllowZero(const unsigned char* opcodePtr)
-{
-#if LINK_SIZE == 3
-    return get3ByteValue(opcodePtr);
-#elif LINK_SIZE == 2
-    return get2ByteValue(opcodePtr);
-#else
-#   error LINK_SIZE not supported.
-#endif
-}
-
-#define MAX_PATTERN_SIZE 1024 * 1024 // Derived by empirical testing of compile time in PCRE and WREC.
-COMPILE_ASSERT(MAX_PATTERN_SIZE < (1 << (8 * LINK_SIZE)), pcre_max_pattern_fits_in_bytecode);
-
-static inline void putLinkValue(unsigned char* opcodePtr, int value)
-{
-    ASSERT(value);
-    putLinkValueAllowZero(opcodePtr, value);
-}
-
-static inline int getLinkValue(const unsigned char* opcodePtr)
-{
-    int value = getLinkValueAllowZero(opcodePtr);
-    ASSERT(value);
-    return value;
-}
-
-static inline void putLinkValueAndAdvance(unsigned char*& opcodePtr, int value)
-{
-    putLinkValue(opcodePtr, value);
-    opcodePtr += LINK_SIZE;
-}
-
-static inline void putLinkValueAllowZeroAndAdvance(unsigned char*& opcodePtr, int value)
-{
-    putLinkValueAllowZero(opcodePtr, value);
-    opcodePtr += LINK_SIZE;
-}
-
-// FIXME: These are really more of a "compiled regexp state" than "regexp options"
-enum RegExpOptions {
-    UseFirstByteOptimizationOption = 0x40000000,  /* firstByte is set */
-    UseRequiredByteOptimizationOption = 0x20000000,  /* reqByte is set */
-    UseMultiLineFirstByteOptimizationOption = 0x10000000,  /* start after \n for multiline */
-    IsAnchoredOption = 0x02000000,  /* can't use partial with this regex */
-    IgnoreCaseOption = 0x00000001,
-    MatchAcrossMultipleLinesOption = 0x00000002
-};
-
-/* Flags added to firstByte or reqByte; a "non-literal" item is either a
-variable-length repeat, or a anything other than literal characters. */
-
-#define REQ_IGNORE_CASE 0x0100    /* indicates should ignore case */
-#define REQ_VARY     0x0200    /* reqByte followed non-literal item */
-
-/* Miscellaneous definitions */
-
-/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
-contain UTF-8 characters with values greater than 255. */
-
-#define XCL_NOT    0x01    /* Flag: this is a negative class */
-#define XCL_MAP    0x02    /* Flag: a 32-byte map is present */
-
-#define XCL_END       0    /* Marks end of individual items */
-#define XCL_SINGLE    1    /* Single item (one multibyte char) follows */
-#define XCL_RANGE     2    /* A range (two multibyte chars) follows */
-
-/* These are escaped items that aren't just an encoding of a particular data
-value such as \n. They must have non-zero values, as check_escape() returns
-their negation. Also, they must appear in the same order as in the opcode
-definitions below, up to ESC_w. The final one must be
-ESC_REF as subsequent values are used for \1, \2, \3, etc. There is are two
-tests in the code for an escape > ESC_b and <= ESC_w to
-detect the types that may be repeated. These are the types that consume
-characters. If any new escapes are put in between that don't consume a
-character, that code will have to change. */
-
-enum { ESC_B = 1, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s, ESC_W, ESC_w, ESC_REF };
-
-/* Opcode table: OP_BRA must be last, as all values >= it are used for brackets
-that extract substrings. Starting from 1 (i.e. after OP_END), the values up to
-OP_EOD must correspond in order to the list of escapes immediately above.
-Note that whenever this list is updated, the two macro definitions that follow
-must also be updated to match. */
-
-#define FOR_EACH_OPCODE(macro) \
-    macro(END) \
-    \
-    macro(NOT_WORD_BOUNDARY) \
-    macro(WORD_BOUNDARY) \
-    macro(NOT_DIGIT) \
-    macro(DIGIT) \
-    macro(NOT_WHITESPACE) \
-    macro(WHITESPACE) \
-    macro(NOT_WORDCHAR) \
-    macro(WORDCHAR) \
-    \
-    macro(NOT_NEWLINE) \
-    \
-    macro(CIRC) \
-    macro(DOLL) \
-    macro(BOL) \
-    macro(EOL) \
-    macro(CHAR) \
-    macro(CHAR_IGNORING_CASE) \
-    macro(ASCII_CHAR) \
-    macro(ASCII_LETTER_IGNORING_CASE) \
-    macro(NOT) \
-    \
-    macro(STAR) \
-    macro(MINSTAR) \
-    macro(PLUS) \
-    macro(MINPLUS) \
-    macro(QUERY) \
-    macro(MINQUERY) \
-    macro(UPTO) \
-    macro(MINUPTO) \
-    macro(EXACT) \
-    \
-    macro(NOTSTAR) \
-    macro(NOTMINSTAR) \
-    macro(NOTPLUS) \
-    macro(NOTMINPLUS) \
-    macro(NOTQUERY) \
-    macro(NOTMINQUERY) \
-    macro(NOTUPTO) \
-    macro(NOTMINUPTO) \
-    macro(NOTEXACT) \
-    \
-    macro(TYPESTAR) \
-    macro(TYPEMINSTAR) \
-    macro(TYPEPLUS) \
-    macro(TYPEMINPLUS) \
-    macro(TYPEQUERY) \
-    macro(TYPEMINQUERY) \
-    macro(TYPEUPTO) \
-    macro(TYPEMINUPTO) \
-    macro(TYPEEXACT) \
-    \
-    macro(CRSTAR) \
-    macro(CRMINSTAR) \
-    macro(CRPLUS) \
-    macro(CRMINPLUS) \
-    macro(CRQUERY) \
-    macro(CRMINQUERY) \
-    macro(CRRANGE) \
-    macro(CRMINRANGE) \
-    \
-    macro(CLASS) \
-    macro(NCLASS) \
-    macro(XCLASS) \
-    \
-    macro(REF) \
-    \
-    macro(ALT) \
-    macro(KET) \
-    macro(KETRMAX) \
-    macro(KETRMIN) \
-    \
-    macro(ASSERT) \
-    macro(ASSERT_NOT) \
-    \
-    macro(BRAZERO) \
-    macro(BRAMINZERO) \
-    macro(BRANUMBER) \
-    macro(BRA)
-
-#define OPCODE_ENUM_VALUE(opcode) OP_##opcode,
-enum { FOR_EACH_OPCODE(OPCODE_ENUM_VALUE) };
-
-/* WARNING WARNING WARNING: There is an implicit assumption in pcre.c and
-study.c that all opcodes are less than 128 in value. This makes handling UTF-8
-character sequences easier. */
-
-/* The highest extraction number before we have to start using additional
-bytes. (Originally PCRE didn't have support for extraction counts higher than
-this number.) The value is limited by the number of opcodes left after OP_BRA,
-i.e. 255 - OP_BRA. We actually set it a bit lower to leave room for additional
-opcodes. */
-
-/* FIXME: Note that OP_BRA + 100 is > 128, so the two comments above
-are in conflict! */
-
-#define EXTRACT_BASIC_MAX  100
-
-/* The code vector runs on as long as necessary after the end. */
-
-struct JSRegExp {
-    unsigned options;
-
-    unsigned short topBracket;
-    unsigned short topBackref;
-    
-    unsigned short firstByte;
-    unsigned short reqByte;
-
-#if REGEXP_HISTOGRAM
-    size_t stringOffset;
-    size_t stringLength;
-#endif
-};
-
-/* Internal shared data tables. These are tables that are used by more than one
- of the exported public functions. They have to be "external" in the C sense,
- but are not part of the PCRE public API. The data for these tables is in the
- pcre_tables.c module. */
-
-#define jsc_pcre_utf8_table1_size 6
-
-extern const int    jsc_pcre_utf8_table1[6];
-extern const int    jsc_pcre_utf8_table2[6];
-extern const int    jsc_pcre_utf8_table3[6];
-extern const unsigned char jsc_pcre_utf8_table4[0x40];
-
-extern const unsigned char jsc_pcre_default_tables[tables_length];
-
-static inline unsigned char toLowerCase(unsigned char c)
-{
-    static const unsigned char* lowerCaseChars = jsc_pcre_default_tables + lcc_offset;
-    return lowerCaseChars[c];
-}
-
-static inline unsigned char flipCase(unsigned char c)
-{
-    static const unsigned char* flippedCaseChars = jsc_pcre_default_tables + fcc_offset;
-    return flippedCaseChars[c];
-}
-
-static inline unsigned char classBitmapForChar(unsigned char c)
-{
-    static const unsigned char* charClassBitmaps = jsc_pcre_default_tables + cbits_offset;
-    return charClassBitmaps[c];
-}
-
-static inline unsigned char charTypeForChar(unsigned char c)
-{
-    const unsigned char* charTypeMap = jsc_pcre_default_tables + ctypes_offset;
-    return charTypeMap[c];
-}
-
-static inline bool isWordChar(UChar c)
-{
-    return c < 128 && (charTypeForChar(c) & ctype_word);
-}
-
-static inline bool isSpaceChar(UChar c)
-{
-    return (c < 128 && (charTypeForChar(c) & ctype_space)) || c == 0x00A0;
-}
-
-static inline bool isNewline(UChar nl)
-{
-    return (nl == 0xA || nl == 0xD || nl == 0x2028 || nl == 0x2029);
-}
-
-static inline bool isBracketStartOpcode(unsigned char opcode)
-{
-    if (opcode >= OP_BRA)
-        return true;
-    switch (opcode) {
-        case OP_ASSERT:
-        case OP_ASSERT_NOT:
-            return true;
-        default:
-            return false;
-    }
-}
-
-static inline void advanceToEndOfBracket(const unsigned char*& opcodePtr)
-{
-    ASSERT(isBracketStartOpcode(*opcodePtr) || *opcodePtr == OP_ALT);
-    do
-        opcodePtr += getLinkValue(opcodePtr + 1);
-    while (*opcodePtr == OP_ALT);
-}
-
-/* Internal shared functions. These are functions that are used in more
-that one of the source files. They have to have external linkage, but
-but are not part of the public API and so not exported from the library. */
-
-extern int jsc_pcre_ucp_othercase(unsigned);
-extern bool jsc_pcre_xclass(int, const unsigned char*);
-
-#endif
-
-#endif
-
-/* End of pcre_internal.h */
diff --git a/pcre/pcre_tables.cpp b/pcre/pcre_tables.cpp
deleted file mode 100644 (file)
index 8696879..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 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:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-/* This module contains some fixed tables that are used by more than one of the
-PCRE code modules. */
-
-#include "config.h"
-#include "pcre_internal.h"
-
-/*************************************************
-*           Tables for UTF-8 support             *
-*************************************************/
-
-/* These are the breakpoints for different numbers of bytes in a UTF-8
-character. */
-
-const int jsc_pcre_utf8_table1[6] =
-  { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
-
-/* These are the indicator bits and the mask for the data bits to set in the
-first byte of a character, indexed by the number of additional bytes. */
-
-const int jsc_pcre_utf8_table2[6] = { 0,    0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
-const int jsc_pcre_utf8_table3[6] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
-
-/* Table of the number of extra characters, indexed by the first character
-masked with 0x3f. The highest number for a valid UTF-8 character is in fact
-0x3d. */
-
-const unsigned char jsc_pcre_utf8_table4[0x40] = {
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-  2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-  3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
-
-#include "chartables.c"
diff --git a/pcre/pcre_ucp_searchfuncs.cpp b/pcre/pcre_ucp_searchfuncs.cpp
deleted file mode 100644 (file)
index 5592865..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 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:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-
-/* This module contains code for searching the table of Unicode character
-properties. */
-
-#include "config.h"
-#include "pcre_internal.h"
-
-#include "ucpinternal.h"       /* Internal table details */
-#include "ucptable.cpp"        /* The table itself */
-
-/*************************************************
-*       Search table and return other case       *
-*************************************************/
-
-/* If the given character is a letter, and there is another case for the
-letter, return the other case. Otherwise, return -1.
-
-Arguments:
-  c           the character value
-
-Returns:      the other case or -1 if none
-*/
-
-int jsc_pcre_ucp_othercase(unsigned c)
-{
-    int bot = 0;
-    int top = sizeof(ucp_table) / sizeof(cnode);
-    int mid;
-    
-    /* The table is searched using a binary chop. You might think that using
-     intermediate variables to hold some of the common expressions would speed
-     things up, but tests with gcc 3.4.4 on Linux showed that, on the contrary, it
-     makes things a lot slower. */
-    
-    for (;;) {
-        if (top <= bot)
-            return -1;
-        mid = (bot + top) >> 1;
-        if (c == (ucp_table[mid].f0 & f0_charmask))
-            break;
-        if (c < (ucp_table[mid].f0 & f0_charmask))
-            top = mid;
-        else {
-            if ((ucp_table[mid].f0 & f0_rangeflag) && (c <= (ucp_table[mid].f0 & f0_charmask) + (ucp_table[mid].f1 & f1_rangemask)))
-                break;
-            bot = mid + 1;
-        }
-    }
-    
-    /* Found an entry in the table. Return -1 for a range entry. Otherwise return
-     the other case if there is one, else -1. */
-    
-    if (ucp_table[mid].f0 & f0_rangeflag)
-        return -1;
-    
-    int offset = ucp_table[mid].f1 & f1_casemask;
-    if (offset & f1_caseneg)
-        offset |= f1_caseneg;
-    return !offset ? -1 : c + offset;
-}
diff --git a/pcre/pcre_xclass.cpp b/pcre/pcre_xclass.cpp
deleted file mode 100644 (file)
index a32edd4..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007, 2008, 2009 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:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-/* This module contains an internal function that is used to match an extended
-class (one that contains characters whose values are > 255). */
-
-#include "config.h"
-#include "pcre_internal.h"
-
-/*************************************************
-*       Match character against an XCLASS        *
-*************************************************/
-
-/* This function is called to match a character against an extended class that
-might contain values > 255.
-
-Arguments:
-  c           the character
-  data        points to the flag byte of the XCLASS data
-
-Returns:      true if character matches, else false
-*/
-
-/* Get the next UTF-8 character, advancing the pointer. This is called when we
- know we are in UTF-8 mode. */
-
-static inline void getUTF8CharAndAdvancePointer(int& c, const unsigned char*& subjectPtr)
-{
-    c = *subjectPtr++;
-    if ((c & 0xc0) == 0xc0) {
-        int gcaa = jsc_pcre_utf8_table4[c & 0x3f];  /* Number of additional bytes */
-        int gcss = 6 * gcaa;
-        c = (c & jsc_pcre_utf8_table3[gcaa]) << gcss;
-        while (gcaa-- > 0) {
-            gcss -= 6;
-            c |= (*subjectPtr++ & 0x3f) << gcss;
-        }
-    }
-}
-
-bool jsc_pcre_xclass(int c, const unsigned char* data)
-{
-    bool negated = (*data & XCL_NOT);
-    
-    /* Character values < 256 are matched against a bitmap, if one is present. If
-     not, we still carry on, because there may be ranges that start below 256 in the
-     additional data. */
-    
-    if (c < 256) {
-        if ((*data & XCL_MAP) != 0 && (data[1 + c/8] & (1 << (c&7))) != 0)
-            return !negated;   /* char found */
-    }
-    
-    /* First skip the bit map if present. Then match against the list of Unicode
-     properties or large chars or ranges that end with a large char. We won't ever
-     encounter XCL_PROP or XCL_NOTPROP when UCP support is not compiled. */
-    
-    if ((*data++ & XCL_MAP) != 0)
-        data += 32;
-    
-    int t;
-    while ((t = *data++) != XCL_END) {
-        if (t == XCL_SINGLE) {
-            int x;
-            getUTF8CharAndAdvancePointer(x, data);
-            if (c == x)
-                return !negated;
-        }
-        else if (t == XCL_RANGE) {
-            int x, y;
-            getUTF8CharAndAdvancePointer(x, data);
-            getUTF8CharAndAdvancePointer(y, data);
-            if (c >= x && c <= y)
-                return !negated;
-        }
-    }
-    
-    return negated;   /* char did not match */
-}
diff --git a/pcre/ucpinternal.h b/pcre/ucpinternal.h
deleted file mode 100644 (file)
index c8bc4aa..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* This is JavaScriptCore's variant of the PCRE library. While this library
-started out as a copy of PCRE, many of the features of PCRE have been
-removed. This library now supports only the regular expression features
-required by the JavaScript language specification, and has only the functions
-needed by JavaScriptCore and the rest of WebKit.
-
-                 Originally written by Philip Hazel
-           Copyright (c) 1997-2006 University of Cambridge
-    Copyright (C) 2002, 2004, 2006, 2007 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:
-
-    * Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-
-    * 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.
-
-    * Neither the name of the University of Cambridge nor the names of its
-      contributors may be used to endorse or promote products derived from
-      this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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.
------------------------------------------------------------------------------
-*/
-
-/*************************************************
-*           Unicode Property Table handler       *
-*************************************************/
-
-/* Internal header file defining the layout of the bits in each pair of 32-bit
-words that form a data item in the table. */
-
-typedef struct cnode {
-  unsigned f0;
-  unsigned f1;
-} cnode;
-
-/* Things for the f0 field */
-
-#define f0_scriptmask   0xff000000  /* Mask for script field */
-#define f0_scriptshift          24  /* Shift for script value */
-#define f0_rangeflag    0x00f00000  /* Flag for a range item */
-#define f0_charmask     0x001fffff  /* Mask for code point value */
-
-/* Things for the f1 field */
-
-#define f1_typemask     0xfc000000  /* Mask for char type field */
-#define f1_typeshift            26  /* Shift for the type field */
-#define f1_rangemask    0x0000ffff  /* Mask for a range offset */
-#define f1_casemask     0x0000ffff  /* Mask for a case offset */
-#define f1_caseneg      0xffff8000  /* Bits for negation */
-
-/* The data consists of a vector of structures of type cnode. The two unsigned
-32-bit integers are used as follows:
-
-(f0) (1) The most significant byte holds the script number. The numbers are
-         defined by the enum in ucp.h.
-
-     (2) The 0x00800000 bit is set if this entry defines a range of characters.
-         It is not set if this entry defines a single character
-
-     (3) The 0x00600000 bits are spare.
-
-     (4) The 0x001fffff bits contain the code point. No Unicode code point will
-         ever be greater than 0x0010ffff, so this should be OK for ever.
-
-(f1) (1) The 0xfc000000 bits contain the character type number. The numbers are
-         defined by an enum in ucp.h.
-
-     (2) The 0x03ff0000 bits are spare.
-
-     (3) The 0x0000ffff bits contain EITHER the unsigned offset to the top of
-         range if this entry defines a range, OR the *signed* offset to the
-         character's "other case" partner if this entry defines a single
-         character. There is no partner if the value is zero.
-
--------------------------------------------------------------------------------
-| script (8) |.|.|.| codepoint (21) || type (6) |.|.| spare (8) | offset (16) |
--------------------------------------------------------------------------------
-              | | |                              | |
-              | | |-> spare                      | |-> spare
-              | |                                |
-              | |-> spare                        |-> spare
-              |
-              |-> range flag
-
-The upper/lower casing information is set only for characters that come in
-pairs. The non-one-to-one mappings in the Unicode data are ignored.
-
-When searching the data, proceed as follows:
-
-(1) Set up for a binary chop search.
-
-(2) If the top is not greater than the bottom, the character is not in the
-    table. Its type must therefore be "Cn" ("Undefined").
-
-(3) Find the middle vector element.
-
-(4) Extract the code point and compare. If equal, we are done.
-
-(5) If the test character is smaller, set the top to the current point, and
-    goto (2).
-
-(6) If the current entry defines a range, compute the last character by adding
-    the offset, and see if the test character is within the range. If it is,
-    we are done.
-
-(7) Otherwise, set the bottom to one element past the current point and goto
-    (2).
-*/
-
-/* End of ucpinternal.h */
diff --git a/pcre/ucptable.cpp b/pcre/ucptable.cpp
deleted file mode 100644 (file)
index 011f7f5..0000000
+++ /dev/null
@@ -1,2968 +0,0 @@
-/* This source module is automatically generated from the Unicode
-property table. See ucpinternal.h for a description of the layout. */
-
-static const cnode ucp_table[] = {
-  { 0x09800000, 0x0000001f },
-  { 0x09000020, 0x74000000 },
-  { 0x09800021, 0x54000002 },
-  { 0x09000024, 0x5c000000 },
-  { 0x09800025, 0x54000002 },
-  { 0x09000028, 0x58000000 },
-  { 0x09000029, 0x48000000 },
-  { 0x0900002a, 0x54000000 },
-  { 0x0900002b, 0x64000000 },
-  { 0x0900002c, 0x54000000 },
-  { 0x0900002d, 0x44000000 },
-  { 0x0980002e, 0x54000001 },
-  { 0x09800030, 0x34000009 },
-  { 0x0980003a, 0x54000001 },
-  { 0x0980003c, 0x64000002 },
-  { 0x0980003f, 0x54000001 },
-  { 0x21000041, 0x24000020 },
-  { 0x21000042, 0x24000020 },
-  { 0x21000043, 0x24000020 },
-  { 0x21000044, 0x24000020 },
-  { 0x21000045, 0x24000020 },
-  { 0x21000046, 0x24000020 },
-  { 0x21000047, 0x24000020 },
-  { 0x21000048, 0x24000020 },
-  { 0x21000049, 0x24000020 },
-  { 0x2100004a, 0x24000020 },
-  { 0x2100004b, 0x24000020 },
-  { 0x2100004c, 0x24000020 },
-  { 0x2100004d, 0x24000020 },
-  { 0x2100004e, 0x24000020 },
-  { 0x2100004f, 0x24000020 },
-  { 0x21000050, 0x24000020 },
-  { 0x21000051, 0x24000020 },
-  { 0x21000052, 0x24000020 },
-  { 0x21000053, 0x24000020 },
-  { 0x21000054, 0x24000020 },
-  { 0x21000055, 0x24000020 },
-  { 0x21000056, 0x24000020 },
-  { 0x21000057, 0x24000020 },
-  { 0x21000058, 0x24000020 },
-  { 0x21000059, 0x24000020 },
-  { 0x2100005a, 0x24000020 },
-  { 0x0900005b, 0x58000000 },
-  { 0x0900005c, 0x54000000 },
-  { 0x0900005d, 0x48000000 },
-  { 0x0900005e, 0x60000000 },
-  { 0x0900005f, 0x40000000 },
-  { 0x09000060, 0x60000000 },
-  { 0x21000061, 0x1400ffe0 },
-  { 0x21000062, 0x1400ffe0 },
-  { 0x21000063, 0x1400ffe0 },
-  { 0x21000064, 0x1400ffe0 },
-  { 0x21000065, 0x1400ffe0 },
-  { 0x21000066, 0x1400ffe0 },
-  { 0x21000067, 0x1400ffe0 },
-  { 0x21000068, 0x1400ffe0 },
-  { 0x21000069, 0x1400ffe0 },
-  { 0x2100006a, 0x1400ffe0 },
-  { 0x2100006b, 0x1400ffe0 },
-  { 0x2100006c, 0x1400ffe0 },
-  { 0x2100006d, 0x1400ffe0 },
-  { 0x2100006e, 0x1400ffe0 },
-  { 0x2100006f, 0x1400ffe0 },
-  { 0x21000070, 0x1400ffe0 },
-  { 0x21000071, 0x1400ffe0 },
-  { 0x21000072, 0x1400ffe0 },
-  { 0x21000073, 0x1400ffe0 },
-  { 0x21000074, 0x1400ffe0 },
-  { 0x21000075, 0x1400ffe0 },
-  { 0x21000076, 0x1400ffe0 },
-  { 0x21000077, 0x1400ffe0 },
-  { 0x21000078, 0x1400ffe0 },
-  { 0x21000079, 0x1400ffe0 },
-  { 0x2100007a, 0x1400ffe0 },
-  { 0x0900007b, 0x58000000 },
-  { 0x0900007c, 0x64000000 },
-  { 0x0900007d, 0x48000000 },
-  { 0x0900007e, 0x64000000 },
-  { 0x0980007f, 0x00000020 },
-  { 0x090000a0, 0x74000000 },
-  { 0x090000a1, 0x54000000 },
-  { 0x098000a2, 0x5c000003 },
-  { 0x098000a6, 0x68000001 },
-  { 0x090000a8, 0x60000000 },
-  { 0x090000a9, 0x68000000 },
-  { 0x210000aa, 0x14000000 },
-  { 0x090000ab, 0x50000000 },
-  { 0x090000ac, 0x64000000 },
-  { 0x090000ad, 0x04000000 },
-  { 0x090000ae, 0x68000000 },
-  { 0x090000af, 0x60000000 },
-  { 0x090000b0, 0x68000000 },
-  { 0x090000b1, 0x64000000 },
-  { 0x098000b2, 0x3c000001 },
-  { 0x090000b4, 0x60000000 },
-  { 0x090000b5, 0x140002e7 },
-  { 0x090000b6, 0x68000000 },
-  { 0x090000b7, 0x54000000 },
-  { 0x090000b8, 0x60000000 },
-  { 0x090000b9, 0x3c000000 },
-  { 0x210000ba, 0x14000000 },
-  { 0x090000bb, 0x4c000000 },
-  { 0x098000bc, 0x3c000002 },
-  { 0x090000bf, 0x54000000 },
-  { 0x210000c0, 0x24000020 },
-  { 0x210000c1, 0x24000020 },
-  { 0x210000c2, 0x24000020 },
-  { 0x210000c3, 0x24000020 },
-  { 0x210000c4, 0x24000020 },
-  { 0x210000c5, 0x24000020 },
-  { 0x210000c6, 0x24000020 },
-  { 0x210000c7, 0x24000020 },
-  { 0x210000c8, 0x24000020 },
-  { 0x210000c9, 0x24000020 },
-  { 0x210000ca, 0x24000020 },
-  { 0x210000cb, 0x24000020 },
-  { 0x210000cc, 0x24000020 },
-  { 0x210000cd, 0x24000020 },
-  { 0x210000ce, 0x24000020 },
-  { 0x210000cf, 0x24000020 },
-  { 0x210000d0, 0x24000020 },
-  { 0x210000d1, 0x24000020 },
-  { 0x210000d2, 0x24000020 },
-  { 0x210000d3, 0x24000020 },
-  { 0x210000d4, 0x24000020 },
-  { 0x210000d5, 0x24000020 },
-  { 0x210000d6, 0x24000020 },
-  { 0x090000d7, 0x64000000 },
-  { 0x210000d8, 0x24000020 },
-  { 0x210000d9, 0x24000020 },
-  { 0x210000da, 0x24000020 },
-  { 0x210000db, 0x24000020 },
-  { 0x210000dc, 0x24000020 },
-  { 0x210000dd, 0x24000020 },
-  { 0x210000de, 0x24000020 },
-  { 0x210000df, 0x14000000 },
-  { 0x210000e0, 0x1400ffe0 },
-  { 0x210000e1, 0x1400ffe0 },
-  { 0x210000e2, 0x1400ffe0 },
-  { 0x210000e3, 0x1400ffe0 },
-  { 0x210000e4, 0x1400ffe0 },
-  { 0x210000e5, 0x1400ffe0 },
-  { 0x210000e6, 0x1400ffe0 },
-  { 0x210000e7, 0x1400ffe0 },
-  { 0x210000e8, 0x1400ffe0 },
-  { 0x210000e9, 0x1400ffe0 },
-  { 0x210000ea, 0x1400ffe0 },
-  { 0x210000eb, 0x1400ffe0 },
-  { 0x210000ec, 0x1400ffe0 },
-  { 0x210000ed, 0x1400ffe0 },
-  { 0x210000ee, 0x1400ffe0 },
-  { 0x210000ef, 0x1400ffe0 },
-  { 0x210000f0, 0x1400ffe0 },
-  { 0x210000f1, 0x1400ffe0 },
-  { 0x210000f2, 0x1400ffe0 },
-  { 0x210000f3, 0x1400ffe0 },
-  { 0x210000f4, 0x1400ffe0 },
-  { 0x210000f5, 0x1400ffe0 },
-  { 0x210000f6, 0x1400ffe0 },
-  { 0x090000f7, 0x64000000 },
-  { 0x210000f8, 0x1400ffe0 },
-  { 0x210000f9, 0x1400ffe0 },
-  { 0x210000fa, 0x1400ffe0 },
-  { 0x210000fb, 0x1400ffe0 },
-  { 0x210000fc, 0x1400ffe0 },
-  { 0x210000fd, 0x1400ffe0 },
-  { 0x210000fe, 0x1400ffe0 },
-  { 0x210000ff, 0x14000079 },
-  { 0x21000100, 0x24000001 },
-  { 0x21000101, 0x1400ffff },
-  { 0x21000102, 0x24000001 },
-  { 0x21000103, 0x1400ffff },
-  { 0x21000104, 0x24000001 },
-  { 0x21000105, 0x1400ffff },
-  { 0x21000106, 0x24000001 },
-  { 0x21000107, 0x1400ffff },
-  { 0x21000108, 0x24000001 },
-  { 0x21000109, 0x1400ffff },
-  { 0x2100010a, 0x24000001 },
-  { 0x2100010b, 0x1400ffff },
-  { 0x2100010c, 0x24000001 },
-  { 0x2100010d, 0x1400ffff },
-  { 0x2100010e, 0x24000001 },
-  { 0x2100010f, 0x1400ffff },
-  { 0x21000110, 0x24000001 },
-  { 0x21000111, 0x1400ffff },
-  { 0x21000112, 0x24000001 },
-  { 0x21000113, 0x1400ffff },
-  { 0x21000114, 0x24000001 },
-  { 0x21000115, 0x1400ffff },
-  { 0x21000116, 0x24000001 },
-  { 0x21000117, 0x1400ffff },
-  { 0x21000118, 0x24000001 },
-  { 0x21000119, 0x1400ffff },
-  { 0x2100011a, 0x24000001 },
-  { 0x2100011b, 0x1400ffff },
-  { 0x2100011c, 0x24000001 },
-  { 0x2100011d, 0x1400ffff },
-  { 0x2100011e, 0x24000001 },
-  { 0x2100011f, 0x1400ffff },
-  { 0x21000120, 0x24000001 },
-  { 0x21000121, 0x1400ffff },
-  { 0x21000122, 0x24000001 },
-  { 0x21000123, 0x1400ffff },
-  { 0x21000124, 0x24000001 },
-  { 0x21000125, 0x1400ffff },
-  { 0x21000126, 0x24000001 },
-  { 0x21000127, 0x1400ffff },
-  { 0x21000128, 0x24000001 },
-  { 0x21000129, 0x1400ffff },
-  { 0x2100012a, 0x24000001 },
-  { 0x2100012b, 0x1400ffff },
-  { 0x2100012c, 0x24000001 },
-  { 0x2100012d, 0x1400ffff },
-  { 0x2100012e, 0x24000001 },
-  { 0x2100012f, 0x1400ffff },
-  { 0x21000130, 0x2400ff39 },
-  { 0x21000131, 0x1400ff18 },
-  { 0x21000132, 0x24000001 },
-  { 0x21000133, 0x1400ffff },
-  { 0x21000134, 0x24000001 },
-  { 0x21000135, 0x1400ffff },
-  { 0x21000136, 0x24000001 },
-  { 0x21000137, 0x1400ffff },
-  { 0x21000138, 0x14000000 },
-  { 0x21000139, 0x24000001 },
-  { 0x2100013a, 0x1400ffff },
-  { 0x2100013b, 0x24000001 },
-  { 0x2100013c, 0x1400ffff },
-  { 0x2100013d, 0x24000001 },
-  { 0x2100013e, 0x1400ffff },
-  { 0x2100013f, 0x24000001 },
-  { 0x21000140, 0x1400ffff },
-  { 0x21000141, 0x24000001 },
-  { 0x21000142, 0x1400ffff },
-  { 0x21000143, 0x24000001 },
-  { 0x21000144, 0x1400ffff },
-  { 0x21000145, 0x24000001 },
-  { 0x21000146, 0x1400ffff },
-  { 0x21000147, 0x24000001 },
-  { 0x21000148, 0x1400ffff },
-  { 0x21000149, 0x14000000 },
-  { 0x2100014a, 0x24000001 },
-  { 0x2100014b, 0x1400ffff },
-  { 0x2100014c, 0x24000001 },
-  { 0x2100014d, 0x1400ffff },
-  { 0x2100014e, 0x24000001 },
-  { 0x2100014f, 0x1400ffff },
-  { 0x21000150, 0x24000001 },
-  { 0x21000151, 0x1400ffff },
-  { 0x21000152, 0x24000001 },
-  { 0x21000153, 0x1400ffff },
-  { 0x21000154, 0x24000001 },
-  { 0x21000155, 0x1400ffff },
-  { 0x21000156, 0x24000001 },
-  { 0x21000157, 0x1400ffff },
-  { 0x21000158, 0x24000001 },
-  { 0x21000159, 0x1400ffff },
-  { 0x2100015a, 0x24000001 },
-  { 0x2100015b, 0x1400ffff },
-  { 0x2100015c, 0x24000001 },
-  { 0x2100015d, 0x1400ffff },
-  { 0x2100015e, 0x24000001 },
-  { 0x2100015f, 0x1400ffff },
-  { 0x21000160, 0x24000001 },
-  { 0x21000161, 0x1400ffff },
-  { 0x21000162, 0x24000001 },
-  { 0x21000163, 0x1400ffff },
-  { 0x21000164, 0x24000001 },
-  { 0x21000165, 0x1400ffff },
-  { 0x21000166, 0x24000001 },
-  { 0x21000167, 0x1400ffff },
-  { 0x21000168, 0x24000001 },
-  { 0x21000169, 0x1400ffff },
-  { 0x2100016a, 0x24000001 },
-  { 0x2100016b, 0x1400ffff },
-  { 0x2100016c, 0x24000001 },
-  { 0x2100016d, 0x1400ffff },
-  { 0x2100016e, 0x24000001 },
-  { 0x2100016f, 0x1400ffff },
-  { 0x21000170, 0x24000001 },
-  { 0x21000171, 0x1400ffff },
-  { 0x21000172, 0x24000001 },
-  { 0x21000173, 0x1400ffff },
-  { 0x21000174, 0x24000001 },
-  { 0x21000175, 0x1400ffff },
-  { 0x21000176, 0x24000001 },
-  { 0x21000177, 0x1400ffff },
-  { 0x21000178, 0x2400ff87 },
-  { 0x21000179, 0x24000001 },
-  { 0x2100017a, 0x1400ffff },
-  { 0x2100017b, 0x24000001 },
-  { 0x2100017c, 0x1400ffff },
-  { 0x2100017d, 0x24000001 },
-  { 0x2100017e, 0x1400ffff },
-  { 0x2100017f, 0x1400fed4 },
-  { 0x21000180, 0x14000000 },
-  { 0x21000181, 0x240000d2 },
-  { 0x21000182, 0x24000001 },
-  { 0x21000183, 0x1400ffff },
-  { 0x21000184, 0x24000001 },
-  { 0x21000185, 0x1400ffff },
-  { 0x21000186, 0x240000ce },
-  { 0x21000187, 0x24000001 },
-  { 0x21000188, 0x1400ffff },
-  { 0x21000189, 0x240000cd },
-  { 0x2100018a, 0x240000cd },
-  { 0x2100018b, 0x24000001 },
-  { 0x2100018c, 0x1400ffff },
-  { 0x2100018d, 0x14000000 },
-  { 0x2100018e, 0x2400004f },
-  { 0x2100018f, 0x240000ca },
-  { 0x21000190, 0x240000cb },
-  { 0x21000191, 0x24000001 },
-  { 0x21000192, 0x1400ffff },
-  { 0x21000193, 0x240000cd },
-  { 0x21000194, 0x240000cf },
-  { 0x21000195, 0x14000061 },
-  { 0x21000196, 0x240000d3 },
-  { 0x21000197, 0x240000d1 },
-  { 0x21000198, 0x24000001 },
-  { 0x21000199, 0x1400ffff },
-  { 0x2100019a, 0x140000a3 },
-  { 0x2100019b, 0x14000000 },
-  { 0x2100019c, 0x240000d3 },
-  { 0x2100019d, 0x240000d5 },
-  { 0x2100019e, 0x14000082 },
-  { 0x2100019f, 0x240000d6 },
-  { 0x210001a0, 0x24000001 },
-  { 0x210001a1, 0x1400ffff },
-  { 0x210001a2, 0x24000001 },
-  { 0x210001a3, 0x1400ffff },
-  { 0x210001a4, 0x24000001 },
-  { 0x210001a5, 0x1400ffff },
-  { 0x210001a6, 0x240000da },
-  { 0x210001a7, 0x24000001 },
-  { 0x210001a8, 0x1400ffff },
-  { 0x210001a9, 0x240000da },
-  { 0x218001aa, 0x14000001 },
-  { 0x210001ac, 0x24000001 },
-  { 0x210001ad, 0x1400ffff },
-  { 0x210001ae, 0x240000da },
-  { 0x210001af, 0x24000001 },
-  { 0x210001b0, 0x1400ffff },
-  { 0x210001b1, 0x240000d9 },
-  { 0x210001b2, 0x240000d9 },
-  { 0x210001b3, 0x24000001 },
-  { 0x210001b4, 0x1400ffff },
-  { 0x210001b5, 0x24000001 },
-  { 0x210001b6, 0x1400ffff },
-  { 0x210001b7, 0x240000db },
-  { 0x210001b8, 0x24000001 },
-  { 0x210001b9, 0x1400ffff },
-  { 0x210001ba, 0x14000000 },
-  { 0x210001bb, 0x1c000000 },
-  { 0x210001bc, 0x24000001 },
-  { 0x210001bd, 0x1400ffff },
-  { 0x210001be, 0x14000000 },
-  { 0x210001bf, 0x14000038 },
-  { 0x218001c0, 0x1c000003 },
-  { 0x210001c4, 0x24000002 },
-  { 0x210001c5, 0x2000ffff },
-  { 0x210001c6, 0x1400fffe },
-  { 0x210001c7, 0x24000002 },
-  { 0x210001c8, 0x2000ffff },
-  { 0x210001c9, 0x1400fffe },
-  { 0x210001ca, 0x24000002 },
-  { 0x210001cb, 0x2000ffff },
-  { 0x210001cc, 0x1400fffe },
-  { 0x210001cd, 0x24000001 },
-  { 0x210001ce, 0x1400ffff },
-  { 0x210001cf, 0x24000001 },
-  { 0x210001d0, 0x1400ffff },
-  { 0x210001d1, 0x24000001 },
-  { 0x210001d2, 0x1400ffff },
-  { 0x210001d3, 0x24000001 },
-  { 0x210001d4, 0x1400ffff },
-  { 0x210001d5, 0x24000001 },
-  { 0x210001d6, 0x1400ffff },
-  { 0x210001d7, 0x24000001 },
-  { 0x210001d8, 0x1400ffff },
-  { 0x210001d9, 0x24000001 },
-  { 0x210001da, 0x1400ffff },
-  { 0x210001db, 0x24000001 },
-  { 0x210001dc, 0x1400ffff },
-  { 0x210001dd, 0x1400ffb1 },
-  { 0x210001de, 0x24000001 },
-  { 0x210001df, 0x1400ffff },
-  { 0x210001e0, 0x24000001 },
-  { 0x210001e1, 0x1400ffff },
-  { 0x210001e2, 0x24000001 },
-  { 0x210001e3, 0x1400ffff },
-  { 0x210001e4, 0x24000001 },
-  { 0x210001e5, 0x1400ffff },
-  { 0x210001e6, 0x24000001 },
-  { 0x210001e7, 0x1400ffff },
-  { 0x210001e8, 0x24000001 },
-  { 0x210001e9, 0x1400ffff },
-  { 0x210001ea, 0x24000001 },
-  { 0x210001eb, 0x1400ffff },
-  { 0x210001ec, 0x24000001 },
-  { 0x210001ed, 0x1400ffff },
-  { 0x210001ee, 0x24000001 },
-  { 0x210001ef, 0x1400ffff },
-  { 0x210001f0, 0x14000000 },
-  { 0x210001f1, 0x24000002 },
-  { 0x210001f2, 0x2000ffff },
-  { 0x210001f3, 0x1400fffe },
-  { 0x210001f4, 0x24000001 },
-  { 0x210001f5, 0x1400ffff },
-  { 0x210001f6, 0x2400ff9f },
-  { 0x210001f7, 0x2400ffc8 },
-  { 0x210001f8, 0x24000001 },
-  { 0x210001f9, 0x1400ffff },
-  { 0x210001fa, 0x24000001 },
-  { 0x210001fb, 0x1400ffff },
-  { 0x210001fc, 0x24000001 },
-  { 0x210001fd, 0x1400ffff },
-  { 0x210001fe, 0x24000001 },
-  { 0x210001ff, 0x1400ffff },
-  { 0x21000200, 0x24000001 },
-  { 0x21000201, 0x1400ffff },
-  { 0x21000202, 0x24000001 },
-  { 0x21000203, 0x1400ffff },
-  { 0x21000204, 0x24000001 },
-  { 0x21000205, 0x1400ffff },
-  { 0x21000206, 0x24000001 },
-  { 0x21000207, 0x1400ffff },
-  { 0x21000208, 0x24000001 },
-  { 0x21000209, 0x1400ffff },
-  { 0x2100020a, 0x24000001 },
-  { 0x2100020b, 0x1400ffff },
-  { 0x2100020c, 0x24000001 },
-  { 0x2100020d, 0x1400ffff },
-  { 0x2100020e, 0x24000001 },
-  { 0x2100020f, 0x1400ffff },
-  { 0x21000210, 0x24000001 },
-  { 0x21000211, 0x1400ffff },
-  { 0x21000212, 0x24000001 },
-  { 0x21000213, 0x1400ffff },
-  { 0x21000214, 0x24000001 },
-  { 0x21000215, 0x1400ffff },
-  { 0x21000216, 0x24000001 },
-  { 0x21000217, 0x1400ffff },
-  { 0x21000218, 0x24000001 },
-  { 0x21000219, 0x1400ffff },
-  { 0x2100021a, 0x24000001 },
-  { 0x2100021b, 0x1400ffff },
-  { 0x2100021c, 0x24000001 },
-  { 0x2100021d, 0x1400ffff },
-  { 0x2100021e, 0x24000001 },
-  { 0x2100021f, 0x1400ffff },
-  { 0x21000220, 0x2400ff7e },
-  { 0x21000221, 0x14000000 },
-  { 0x21000222, 0x24000001 },
-  { 0x21000223, 0x1400ffff },
-  { 0x21000224, 0x24000001 },
-  { 0x21000225, 0x1400ffff },
-  { 0x21000226, 0x24000001 },
-  { 0x21000227, 0x1400ffff },
-  { 0x21000228, 0x24000001 },
-  { 0x21000229, 0x1400ffff },
-  { 0x2100022a, 0x24000001 },
-  { 0x2100022b, 0x1400ffff },
-  { 0x2100022c, 0x24000001 },
-  { 0x2100022d, 0x1400ffff },
-  { 0x2100022e, 0x24000001 },
-  { 0x2100022f, 0x1400ffff },
-  { 0x21000230, 0x24000001 },
-  { 0x21000231, 0x1400ffff },
-  { 0x21000232, 0x24000001 },
-  { 0x21000233, 0x1400ffff },
-  { 0x21800234, 0x14000005 },
-  { 0x2100023a, 0x24000000 },
-  { 0x2100023b, 0x24000001 },
-  { 0x2100023c, 0x1400ffff },
-  { 0x2100023d, 0x2400ff5d },
-  { 0x2100023e, 0x24000000 },
-  { 0x2180023f, 0x14000001 },
-  { 0x21000241, 0x24000053 },
-  { 0x21800250, 0x14000002 },
-  { 0x21000253, 0x1400ff2e },
-  { 0x21000254, 0x1400ff32 },
-  { 0x21000255, 0x14000000 },
-  { 0x21000256, 0x1400ff33 },
-  { 0x21000257, 0x1400ff33 },
-  { 0x21000258, 0x14000000 },
-  { 0x21000259, 0x1400ff36 },
-  { 0x2100025a, 0x14000000 },
-  { 0x2100025b, 0x1400ff35 },
-  { 0x2180025c, 0x14000003 },
-  { 0x21000260, 0x1400ff33 },
-  { 0x21800261, 0x14000001 },
-  { 0x21000263, 0x1400ff31 },
-  { 0x21800264, 0x14000003 },
-  { 0x21000268, 0x1400ff2f },
-  { 0x21000269, 0x1400ff2d },
-  { 0x2180026a, 0x14000004 },
-  { 0x2100026f, 0x1400ff2d },
-  { 0x21800270, 0x14000001 },
-  { 0x21000272, 0x1400ff2b },
-  { 0x21800273, 0x14000001 },
-  { 0x21000275, 0x1400ff2a },
-  { 0x21800276, 0x14000009 },
-  { 0x21000280, 0x1400ff26 },
-  { 0x21800281, 0x14000001 },
-  { 0x21000283, 0x1400ff26 },
-  { 0x21800284, 0x14000003 },
-  { 0x21000288, 0x1400ff26 },
-  { 0x21000289, 0x14000000 },
-  { 0x2100028a, 0x1400ff27 },
-  { 0x2100028b, 0x1400ff27 },
-  { 0x2180028c, 0x14000005 },
-  { 0x21000292, 0x1400ff25 },
-  { 0x21000293, 0x14000000 },
-  { 0x21000294, 0x1400ffad },
-  { 0x21800295, 0x1400001a },
-  { 0x218002b0, 0x18000011 },
-  { 0x098002c2, 0x60000003 },
-  { 0x098002c6, 0x1800000b },
-  { 0x098002d2, 0x6000000d },
-  { 0x218002e0, 0x18000004 },
-  { 0x098002e5, 0x60000008 },
-  { 0x090002ee, 0x18000000 },
-  { 0x098002ef, 0x60000010 },
-  { 0x1b800300, 0x30000044 },
-  { 0x1b000345, 0x30000054 },
-  { 0x1b800346, 0x30000029 },
-  { 0x13800374, 0x60000001 },
-  { 0x1300037a, 0x18000000 },
-  { 0x0900037e, 0x54000000 },
-  { 0x13800384, 0x60000001 },
-  { 0x13000386, 0x24000026 },
-  { 0x09000387, 0x54000000 },
-  { 0x13000388, 0x24000025 },
-  { 0x13000389, 0x24000025 },
-  { 0x1300038a, 0x24000025 },
-  { 0x1300038c, 0x24000040 },
-  { 0x1300038e, 0x2400003f },
-  { 0x1300038f, 0x2400003f },
-  { 0x13000390, 0x14000000 },
-  { 0x13000391, 0x24000020 },
-  { 0x13000392, 0x24000020 },
-  { 0x13000393, 0x24000020 },
-  { 0x13000394, 0x24000020 },
-  { 0x13000395, 0x24000020 },
-  { 0x13000396, 0x24000020 },
-  { 0x13000397, 0x24000020 },
-  { 0x13000398, 0x24000020 },
-  { 0x13000399, 0x24000020 },
-  { 0x1300039a, 0x24000020 },
-  { 0x1300039b, 0x24000020 },
-  { 0x1300039c, 0x24000020 },
-  { 0x1300039d, 0x24000020 },
-  { 0x1300039e, 0x24000020 },
-  { 0x1300039f, 0x24000020 },
-  { 0x130003a0, 0x24000020 },
-  { 0x130003a1, 0x24000020 },
-  { 0x130003a3, 0x24000020 },
-  { 0x130003a4, 0x24000020 },
-  { 0x130003a5, 0x24000020 },
-  { 0x130003a6, 0x24000020 },
-  { 0x130003a7, 0x24000020 },
-  { 0x130003a8, 0x24000020 },
-  { 0x130003a9, 0x24000020 },
-  { 0x130003aa, 0x24000020 },
-  { 0x130003ab, 0x24000020 },
-  { 0x130003ac, 0x1400ffda },
-  { 0x130003ad, 0x1400ffdb },
-  { 0x130003ae, 0x1400ffdb },
-  { 0x130003af, 0x1400ffdb },
-  { 0x130003b0, 0x14000000 },
-  { 0x130003b1, 0x1400ffe0 },
-  { 0x130003b2, 0x1400ffe0 },
-  { 0x130003b3, 0x1400ffe0 },
-  { 0x130003b4, 0x1400ffe0 },
-  { 0x130003b5, 0x1400ffe0 },
-  { 0x130003b6, 0x1400ffe0 },
-  { 0x130003b7, 0x1400ffe0 },
-  { 0x130003b8, 0x1400ffe0 },
-  { 0x130003b9, 0x1400ffe0 },
-  { 0x130003ba, 0x1400ffe0 },
-  { 0x130003bb, 0x1400ffe0 },
-  { 0x130003bc, 0x1400ffe0 },
-  { 0x130003bd, 0x1400ffe0 },
-  { 0x130003be, 0x1400ffe0 },
-  { 0x130003bf, 0x1400ffe0 },
-  { 0x130003c0, 0x1400ffe0 },
-  { 0x130003c1, 0x1400ffe0 },
-  { 0x130003c2, 0x1400ffe1 },
-  { 0x130003c3, 0x1400ffe0 },
-  { 0x130003c4, 0x1400ffe0 },
-  { 0x130003c5, 0x1400ffe0 },
-  { 0x130003c6, 0x1400ffe0 },
-  { 0x130003c7, 0x1400ffe0 },
-  { 0x130003c8, 0x1400ffe0 },
-  { 0x130003c9, 0x1400ffe0 },
-  { 0x130003ca, 0x1400ffe0 },
-  { 0x130003cb, 0x1400ffe0 },
-  { 0x130003cc, 0x1400ffc0 },
-  { 0x130003cd, 0x1400ffc1 },
-  { 0x130003ce, 0x1400ffc1 },
-  { 0x130003d0, 0x1400ffc2 },
-  { 0x130003d1, 0x1400ffc7 },
-  { 0x138003d2, 0x24000002 },
-  { 0x130003d5, 0x1400ffd1 },
-  { 0x130003d6, 0x1400ffca },
-  { 0x130003d7, 0x14000000 },
-  { 0x130003d8, 0x24000001 },
-  { 0x130003d9, 0x1400ffff },
-  { 0x130003da, 0x24000001 },
-  { 0x130003db, 0x1400ffff },
-  { 0x130003dc, 0x24000001 },
-  { 0x130003dd, 0x1400ffff },
-  { 0x130003de, 0x24000001 },
-  { 0x130003df, 0x1400ffff },
-  { 0x130003e0, 0x24000001 },
-  { 0x130003e1, 0x1400ffff },
-  { 0x0a0003e2, 0x24000001 },
-  { 0x0a0003e3, 0x1400ffff },
-  { 0x0a0003e4, 0x24000001 },
-  { 0x0a0003e5, 0x1400ffff },
-  { 0x0a0003e6, 0x24000001 },
-  { 0x0a0003e7, 0x1400ffff },
-  { 0x0a0003e8, 0x24000001 },
-  { 0x0a0003e9, 0x1400ffff },
-  { 0x0a0003ea, 0x24000001 },
-  { 0x0a0003eb, 0x1400ffff },
-  { 0x0a0003ec, 0x24000001 },
-  { 0x0a0003ed, 0x1400ffff },
-  { 0x0a0003ee, 0x24000001 },
-  { 0x0a0003ef, 0x1400ffff },
-  { 0x130003f0, 0x1400ffaa },
-  { 0x130003f1, 0x1400ffb0 },
-  { 0x130003f2, 0x14000007 },
-  { 0x130003f3, 0x14000000 },
-  { 0x130003f4, 0x2400ffc4 },
-  { 0x130003f5, 0x1400ffa0 },
-  { 0x130003f6, 0x64000000 },
-  { 0x130003f7, 0x24000001 },
-  { 0x130003f8, 0x1400ffff },
-  { 0x130003f9, 0x2400fff9 },
-  { 0x130003fa, 0x24000001 },
-  { 0x130003fb, 0x1400ffff },
-  { 0x130003fc, 0x14000000 },
-  { 0x138003fd, 0x24000002 },
-  { 0x0c000400, 0x24000050 },
-  { 0x0c000401, 0x24000050 },
-  { 0x0c000402, 0x24000050 },
-  { 0x0c000403, 0x24000050 },
-  { 0x0c000404, 0x24000050 },
-  { 0x0c000405, 0x24000050 },
-  { 0x0c000406, 0x24000050 },
-  { 0x0c000407, 0x24000050 },
-  { 0x0c000408, 0x24000050 },
-  { 0x0c000409, 0x24000050 },
-  { 0x0c00040a, 0x24000050 },
-  { 0x0c00040b, 0x24000050 },
-  { 0x0c00040c, 0x24000050 },
-  { 0x0c00040d, 0x24000050 },
-  { 0x0c00040e, 0x24000050 },
-  { 0x0c00040f, 0x24000050 },
-  { 0x0c000410, 0x24000020 },
-  { 0x0c000411, 0x24000020 },
-  { 0x0c000412, 0x24000020 },
-  { 0x0c000413, 0x24000020 },
-  { 0x0c000414, 0x24000020 },
-  { 0x0c000415, 0x24000020 },
-  { 0x0c000416, 0x24000020 },
-  { 0x0c000417, 0x24000020 },
-  { 0x0c000418, 0x24000020 },
-  { 0x0c000419, 0x24000020 },
-  { 0x0c00041a, 0x24000020 },
-  { 0x0c00041b, 0x24000020 },
-  { 0x0c00041c, 0x24000020 },
-  { 0x0c00041d, 0x24000020 },
-  { 0x0c00041e, 0x24000020 },
-  { 0x0c00041f, 0x24000020 },
-  { 0x0c000420, 0x24000020 },
-  { 0x0c000421, 0x24000020 },
-  { 0x0c000422, 0x24000020 },
-  { 0x0c000423, 0x24000020 },
-  { 0x0c000424, 0x24000020 },
-  { 0x0c000425, 0x24000020 },
-  { 0x0c000426, 0x24000020 },
-  { 0x0c000427, 0x24000020 },
-  { 0x0c000428, 0x24000020 },
-  { 0x0c000429, 0x24000020 },
-  { 0x0c00042a, 0x24000020 },
-  { 0x0c00042b, 0x24000020 },
-  { 0x0c00042c, 0x24000020 },
-  { 0x0c00042d, 0x24000020 },
-  { 0x0c00042e, 0x24000020 },
-  { 0x0c00042f, 0x24000020 },
-  { 0x0c000430, 0x1400ffe0 },
-  { 0x0c000431, 0x1400ffe0 },
-  { 0x0c000432, 0x1400ffe0 },
-  { 0x0c000433, 0x1400ffe0 },
-  { 0x0c000434, 0x1400ffe0 },
-  { 0x0c000435, 0x1400ffe0 },
-  { 0x0c000436, 0x1400ffe0 },
-  { 0x0c000437, 0x1400ffe0 },
-  { 0x0c000438, 0x1400ffe0 },
-  { 0x0c000439, 0x1400ffe0 },
-  { 0x0c00043a, 0x1400ffe0 },
-  { 0x0c00043b, 0x1400ffe0 },
-  { 0x0c00043c, 0x1400ffe0 },
-  { 0x0c00043d, 0x1400ffe0 },
-  { 0x0c00043e, 0x1400ffe0 },
-  { 0x0c00043f, 0x1400ffe0 },
-  { 0x0c000440, 0x1400ffe0 },
-  { 0x0c000441, 0x1400ffe0 },
-  { 0x0c000442, 0x1400ffe0 },
-  { 0x0c000443, 0x1400ffe0 },
-  { 0x0c000444, 0x1400ffe0 },
-  { 0x0c000445, 0x1400ffe0 },
-  { 0x0c000446, 0x1400ffe0 },
-  { 0x0c000447, 0x1400ffe0 },
-  { 0x0c000448, 0x1400ffe0 },
-  { 0x0c000449, 0x1400ffe0 },
-  { 0x0c00044a, 0x1400ffe0 },
-  { 0x0c00044b, 0x1400ffe0 },
-  { 0x0c00044c, 0x1400ffe0 },
-  { 0x0c00044d, 0x1400ffe0 },
-  { 0x0c00044e, 0x1400ffe0 },
-  { 0x0c00044f, 0x1400ffe0 },
-  { 0x0c000450, 0x1400ffb0 },
-  { 0x0c000451, 0x1400ffb0 },
-  { 0x0c000452, 0x1400ffb0 },
-  { 0x0c000453, 0x1400ffb0 },
-  { 0x0c000454, 0x1400ffb0 },
-  { 0x0c000455, 0x1400ffb0 },
-  { 0x0c000456, 0x1400ffb0 },
-  { 0x0c000457, 0x1400ffb0 },
-  { 0x0c000458, 0x1400ffb0 },
-  { 0x0c000459, 0x1400ffb0 },
-  { 0x0c00045a, 0x1400ffb0 },
-  { 0x0c00045b, 0x1400ffb0 },
-  { 0x0c00045c, 0x1400ffb0 },
-  { 0x0c00045d, 0x1400ffb0 },
-  { 0x0c00045e, 0x1400ffb0 },
-  { 0x0c00045f, 0x1400ffb0 },
-  { 0x0c000460, 0x24000001 },
-  { 0x0c000461, 0x1400ffff },
-  { 0x0c000462, 0x24000001 },
-  { 0x0c000463, 0x1400ffff },
-  { 0x0c000464, 0x24000001 },
-  { 0x0c000465, 0x1400ffff },
-  { 0x0c000466, 0x24000001 },
-  { 0x0c000467, 0x1400ffff },
-  { 0x0c000468, 0x24000001 },
-  { 0x0c000469, 0x1400ffff },
-  { 0x0c00046a, 0x24000001 },
-  { 0x0c00046b, 0x1400ffff },
-  { 0x0c00046c, 0x24000001 },
-  { 0x0c00046d, 0x1400ffff },
-  { 0x0c00046e, 0x24000001 },
-  { 0x0c00046f, 0x1400ffff },
-  { 0x0c000470, 0x24000001 },
-  { 0x0c000471, 0x1400ffff },
-  { 0x0c000472, 0x24000001 },
-  { 0x0c000473, 0x1400ffff },
-  { 0x0c000474, 0x24000001 },
-  { 0x0c000475, 0x1400ffff },
-  { 0x0c000476, 0x24000001 },
-  { 0x0c000477, 0x1400ffff },
-  { 0x0c000478, 0x24000001 },
-  { 0x0c000479, 0x1400ffff },
-  { 0x0c00047a, 0x24000001 },
-  { 0x0c00047b, 0x1400ffff },
-  { 0x0c00047c, 0x24000001 },
-  { 0x0c00047d, 0x1400ffff },
-  { 0x0c00047e, 0x24000001 },
-  { 0x0c00047f, 0x1400ffff },
-  { 0x0c000480, 0x24000001 },
-  { 0x0c000481, 0x1400ffff },
-  { 0x0c000482, 0x68000000 },
-  { 0x0c800483, 0x30000003 },
-  { 0x0c800488, 0x2c000001 },
-  { 0x0c00048a, 0x24000001 },
-  { 0x0c00048b, 0x1400ffff },
-  { 0x0c00048c, 0x24000001 },
-  { 0x0c00048d, 0x1400ffff },
-  { 0x0c00048e, 0x24000001 },
-  { 0x0c00048f, 0x1400ffff },
-  { 0x0c000490, 0x24000001 },
-  { 0x0c000491, 0x1400ffff },
-  { 0x0c000492, 0x24000001 },
-  { 0x0c000493, 0x1400ffff },
-  { 0x0c000494, 0x24000001 },
-  { 0x0c000495, 0x1400ffff },
-  { 0x0c000496, 0x24000001 },
-  { 0x0c000497, 0x1400ffff },
-  { 0x0c000498, 0x24000001 },
-  { 0x0c000499, 0x1400ffff },
-  { 0x0c00049a, 0x24000001 },
-  { 0x0c00049b, 0x1400ffff },
-  { 0x0c00049c, 0x24000001 },
-  { 0x0c00049d, 0x1400ffff },
-  { 0x0c00049e, 0x24000001 },
-  { 0x0c00049f, 0x1400ffff },
-  { 0x0c0004a0, 0x24000001 },
-  { 0x0c0004a1, 0x1400ffff },
-  { 0x0c0004a2, 0x24000001 },
-  { 0x0c0004a3, 0x1400ffff },
-  { 0x0c0004a4, 0x24000001 },
-  { 0x0c0004a5, 0x1400ffff },
-  { 0x0c0004a6, 0x24000001 },
-  { 0x0c0004a7, 0x1400ffff },
-  { 0x0c0004a8, 0x24000001 },
-  { 0x0c0004a9, 0x1400ffff },
-  { 0x0c0004aa, 0x24000001 },
-  { 0x0c0004ab, 0x1400ffff },
-  { 0x0c0004ac, 0x24000001 },
-  { 0x0c0004ad, 0x1400ffff },
-  { 0x0c0004ae, 0x24000001 },
-  { 0x0c0004af, 0x1400ffff },
-  { 0x0c0004b0, 0x24000001 },
-  { 0x0c0004b1, 0x1400ffff },
-  { 0x0c0004b2, 0x24000001 },
-  { 0x0c0004b3, 0x1400ffff },
-  { 0x0c0004b4, 0x24000001 },
-  { 0x0c0004b5, 0x1400ffff },
-  { 0x0c0004b6, 0x24000001 },
-  { 0x0c0004b7, 0x1400ffff },
-  { 0x0c0004b8, 0x24000001 },
-  { 0x0c0004b9, 0x1400ffff },
-  { 0x0c0004ba, 0x24000001 },
-  { 0x0c0004bb, 0x1400ffff },
-  { 0x0c0004bc, 0x24000001 },
-  { 0x0c0004bd, 0x1400ffff },
-  { 0x0c0004be, 0x24000001 },
-  { 0x0c0004bf, 0x1400ffff },
-  { 0x0c0004c0, 0x24000000 },
-  { 0x0c0004c1, 0x24000001 },
-  { 0x0c0004c2, 0x1400ffff },
-  { 0x0c0004c3, 0x24000001 },
-  { 0x0c0004c4, 0x1400ffff },
-  { 0x0c0004c5, 0x24000001 },
-  { 0x0c0004c6, 0x1400ffff },
-  { 0x0c0004c7, 0x24000001 },
-  { 0x0c0004c8, 0x1400ffff },
-  { 0x0c0004c9, 0x24000001 },
-  { 0x0c0004ca, 0x1400ffff },
-  { 0x0c0004cb, 0x24000001 },
-  { 0x0c0004cc, 0x1400ffff },
-  { 0x0c0004cd, 0x24000001 },
-  { 0x0c0004ce, 0x1400ffff },
-  { 0x0c0004d0, 0x24000001 },
-  { 0x0c0004d1, 0x1400ffff },
-  { 0x0c0004d2, 0x24000001 },
-  { 0x0c0004d3, 0x1400ffff },
-  { 0x0c0004d4, 0x24000001 },
-  { 0x0c0004d5, 0x1400ffff },
-  { 0x0c0004d6, 0x24000001 },
-  { 0x0c0004d7, 0x1400ffff },
-  { 0x0c0004d8, 0x24000001 },
-  { 0x0c0004d9, 0x1400ffff },
-  { 0x0c0004da, 0x24000001 },
-  { 0x0c0004db, 0x1400ffff },
-  { 0x0c0004dc, 0x24000001 },
-  { 0x0c0004dd, 0x1400ffff },
-  { 0x0c0004de, 0x24000001 },
-  { 0x0c0004df, 0x1400ffff },
-  { 0x0c0004e0, 0x24000001 },
-  { 0x0c0004e1, 0x1400ffff },
-  { 0x0c0004e2, 0x24000001 },
-  { 0x0c0004e3, 0x1400ffff },
-  { 0x0c0004e4, 0x24000001 },
-  { 0x0c0004e5, 0x1400ffff },
-  { 0x0c0004e6, 0x24000001 },
-  { 0x0c0004e7, 0x1400ffff },
-  { 0x0c0004e8, 0x24000001 },
-  { 0x0c0004e9, 0x1400ffff },
-  { 0x0c0004ea, 0x24000001 },
-  { 0x0c0004eb, 0x1400ffff },
-  { 0x0c0004ec, 0x24000001 },
-  { 0x0c0004ed, 0x1400ffff },
-  { 0x0c0004ee, 0x24000001 },
-  { 0x0c0004ef, 0x1400ffff },
-  { 0x0c0004f0, 0x24000001 },
-  { 0x0c0004f1, 0x1400ffff },
-  { 0x0c0004f2, 0x24000001 },
-  { 0x0c0004f3, 0x1400ffff },
-  { 0x0c0004f4, 0x24000001 },
-  { 0x0c0004f5, 0x1400ffff },
-  { 0x0c0004f6, 0x24000001 },
-  { 0x0c0004f7, 0x1400ffff },
-  { 0x0c0004f8, 0x24000001 },
-  { 0x0c0004f9, 0x1400ffff },
-  { 0x0c000500, 0x24000001 },
-  { 0x0c000501, 0x1400ffff },
-  { 0x0c000502, 0x24000001 },
-  { 0x0c000503, 0x1400ffff },
-  { 0x0c000504, 0x24000001 },
-  { 0x0c000505, 0x1400ffff },
-  { 0x0c000506, 0x24000001 },
-  { 0x0c000507, 0x1400ffff },
-  { 0x0c000508, 0x24000001 },
-  { 0x0c000509, 0x1400ffff },
-  { 0x0c00050a, 0x24000001 },
-  { 0x0c00050b, 0x1400ffff },
-  { 0x0c00050c, 0x24000001 },
-  { 0x0c00050d, 0x1400ffff },
-  { 0x0c00050e, 0x24000001 },
-  { 0x0c00050f, 0x1400ffff },
-  { 0x01000531, 0x24000030 },
-  { 0x01000532, 0x24000030 },
-  { 0x01000533, 0x24000030 },
-  { 0x01000534, 0x24000030 },
-  { 0x01000535, 0x24000030 },
-  { 0x01000536, 0x24000030 },
-  { 0x01000537, 0x24000030 },
-  { 0x01000538, 0x24000030 },
-  { 0x01000539, 0x24000030 },
-  { 0x0100053a, 0x24000030 },
-  { 0x0100053b, 0x24000030 },
-  { 0x0100053c, 0x24000030 },
-  { 0x0100053d, 0x24000030 },
-  { 0x0100053e, 0x24000030 },
-  { 0x0100053f, 0x24000030 },
-  { 0x01000540, 0x24000030 },
-  { 0x01000541, 0x24000030 },
-  { 0x01000542, 0x24000030 },
-  { 0x01000543, 0x24000030 },
-  { 0x01000544, 0x24000030 },
-  { 0x01000545, 0x24000030 },
-  { 0x01000546, 0x24000030 },
-  { 0x01000547, 0x24000030 },
-  { 0x01000548, 0x24000030 },
-  { 0x01000549, 0x24000030 },
-  { 0x0100054a, 0x24000030 },
-  { 0x0100054b, 0x24000030 },
-  { 0x0100054c, 0x24000030 },
-  { 0x0100054d, 0x24000030 },
-  { 0x0100054e, 0x24000030 },
-  { 0x0100054f, 0x24000030 },
-  { 0x01000550, 0x24000030 },
-  { 0x01000551, 0x24000030 },
-  { 0x01000552, 0x24000030 },
-  { 0x01000553, 0x24000030 },
-  { 0x01000554, 0x24000030 },
-  { 0x01000555, 0x24000030 },
-  { 0x01000556, 0x24000030 },
-  { 0x01000559, 0x18000000 },
-  { 0x0180055a, 0x54000005 },
-  { 0x01000561, 0x1400ffd0 },
-  { 0x01000562, 0x1400ffd0 },
-  { 0x01000563, 0x1400ffd0 },
-  { 0x01000564, 0x1400ffd0 },
-  { 0x01000565, 0x1400ffd0 },
-  { 0x01000566, 0x1400ffd0 },
-  { 0x01000567, 0x1400ffd0 },
-  { 0x01000568, 0x1400ffd0 },
-  { 0x01000569, 0x1400ffd0 },
-  { 0x0100056a, 0x1400ffd0 },
-  { 0x0100056b, 0x1400ffd0 },
-  { 0x0100056c, 0x1400ffd0 },
-  { 0x0100056d, 0x1400ffd0 },
-  { 0x0100056e, 0x1400ffd0 },
-  { 0x0100056f, 0x1400ffd0 },
-  { 0x01000570, 0x1400ffd0 },
-  { 0x01000571, 0x1400ffd0 },
-  { 0x01000572, 0x1400ffd0 },
-  { 0x01000573, 0x1400ffd0 },
-  { 0x01000574, 0x1400ffd0 },
-  { 0x01000575, 0x1400ffd0 },
-  { 0x01000576, 0x1400ffd0 },
-  { 0x01000577, 0x1400ffd0 },
-  { 0x01000578, 0x1400ffd0 },
-  { 0x01000579, 0x1400ffd0 },
-  { 0x0100057a, 0x1400ffd0 },
-  { 0x0100057b, 0x1400ffd0 },
-  { 0x0100057c, 0x1400ffd0 },
-  { 0x0100057d, 0x1400ffd0 },
-  { 0x0100057e, 0x1400ffd0 },
-  { 0x0100057f, 0x1400ffd0 },
-  { 0x01000580, 0x1400ffd0 },
-  { 0x01000581, 0x1400ffd0 },
-  { 0x01000582, 0x1400ffd0 },
-  { 0x01000583, 0x1400ffd0 },
-  { 0x01000584, 0x1400ffd0 },
-  { 0x01000585, 0x1400ffd0 },
-  { 0x01000586, 0x1400ffd0 },
-  { 0x01000587, 0x14000000 },
-  { 0x09000589, 0x54000000 },
-  { 0x0100058a, 0x44000000 },
-  { 0x19800591, 0x30000028 },
-  { 0x198005bb, 0x30000002 },
-  { 0x190005be, 0x54000000 },
-  { 0x190005bf, 0x30000000 },
-  { 0x190005c0, 0x54000000 },
-  { 0x198005c1, 0x30000001 },
-  { 0x190005c3, 0x54000000 },
-  { 0x198005c4, 0x30000001 },
-  { 0x190005c6, 0x54000000 },
-  { 0x190005c7, 0x30000000 },
-  { 0x198005d0, 0x1c00001a },
-  { 0x198005f0, 0x1c000002 },
-  { 0x198005f3, 0x54000001 },
-  { 0x09800600, 0x04000003 },
-  { 0x0000060b, 0x5c000000 },
-  { 0x0980060c, 0x54000001 },
-  { 0x0080060e, 0x68000001 },
-  { 0x00800610, 0x30000005 },
-  { 0x0900061b, 0x54000000 },
-  { 0x0080061e, 0x54000001 },
-  { 0x00800621, 0x1c000019 },
-  { 0x09000640, 0x18000000 },
-  { 0x00800641, 0x1c000009 },
-  { 0x1b80064b, 0x30000013 },
-  { 0x09800660, 0x34000009 },
-  { 0x0080066a, 0x54000003 },
-  { 0x0080066e, 0x1c000001 },
-  { 0x1b000670, 0x30000000 },
-  { 0x00800671, 0x1c000062 },
-  { 0x000006d4, 0x54000000 },
-  { 0x000006d5, 0x1c000000 },
-  { 0x008006d6, 0x30000006 },
-  { 0x090006dd, 0x04000000 },
-  { 0x000006de, 0x2c000000 },
-  { 0x008006df, 0x30000005 },
-  { 0x008006e5, 0x18000001 },
-  { 0x008006e7, 0x30000001 },
-  { 0x000006e9, 0x68000000 },
-  { 0x008006ea, 0x30000003 },
-  { 0x008006ee, 0x1c000001 },
-  { 0x008006f0, 0x34000009 },
-  { 0x008006fa, 0x1c000002 },
-  { 0x008006fd, 0x68000001 },
-  { 0x000006ff, 0x1c000000 },
-  { 0x31800700, 0x5400000d },
-  { 0x3100070f, 0x04000000 },
-  { 0x31000710, 0x1c000000 },
-  { 0x31000711, 0x30000000 },
-  { 0x31800712, 0x1c00001d },
-  { 0x31800730, 0x3000001a },
-  { 0x3180074d, 0x1c000020 },
-  { 0x37800780, 0x1c000025 },
-  { 0x378007a6, 0x3000000a },
-  { 0x370007b1, 0x1c000000 },
-  { 0x0e800901, 0x30000001 },
-  { 0x0e000903, 0x28000000 },
-  { 0x0e800904, 0x1c000035 },
-  { 0x0e00093c, 0x30000000 },
-  { 0x0e00093d, 0x1c000000 },
-  { 0x0e80093e, 0x28000002 },
-  { 0x0e800941, 0x30000007 },
-  { 0x0e800949, 0x28000003 },
-  { 0x0e00094d, 0x30000000 },
-  { 0x0e000950, 0x1c000000 },
-  { 0x0e800951, 0x30000003 },
-  { 0x0e800958, 0x1c000009 },
-  { 0x0e800962, 0x30000001 },
-  { 0x09800964, 0x54000001 },
-  { 0x0e800966, 0x34000009 },
-  { 0x09000970, 0x54000000 },
-  { 0x0e00097d, 0x1c000000 },
-  { 0x02000981, 0x30000000 },
-  { 0x02800982, 0x28000001 },
-  { 0x02800985, 0x1c000007 },
-  { 0x0280098f, 0x1c000001 },
-  { 0x02800993, 0x1c000015 },
-  { 0x028009aa, 0x1c000006 },
-  { 0x020009b2, 0x1c000000 },
-  { 0x028009b6, 0x1c000003 },
-  { 0x020009bc, 0x30000000 },
-  { 0x020009bd, 0x1c000000 },
-  { 0x028009be, 0x28000002 },
-  { 0x028009c1, 0x30000003 },
-  { 0x028009c7, 0x28000001 },
-  { 0x028009cb, 0x28000001 },
-  { 0x020009cd, 0x30000000 },
-  { 0x020009ce, 0x1c000000 },
-  { 0x020009d7, 0x28000000 },
-  { 0x028009dc, 0x1c000001 },
-  { 0x028009df, 0x1c000002 },
-  { 0x028009e2, 0x30000001 },
-  { 0x028009e6, 0x34000009 },
-  { 0x028009f0, 0x1c000001 },
-  { 0x028009f2, 0x5c000001 },
-  { 0x028009f4, 0x3c000005 },
-  { 0x020009fa, 0x68000000 },
-  { 0x15800a01, 0x30000001 },
-  { 0x15000a03, 0x28000000 },
-  { 0x15800a05, 0x1c000005 },
-  { 0x15800a0f, 0x1c000001 },
-  { 0x15800a13, 0x1c000015 },
-  { 0x15800a2a, 0x1c000006 },
-  { 0x15800a32, 0x1c000001 },
-  { 0x15800a35, 0x1c000001 },
-  { 0x15800a38, 0x1c000001 },
-  { 0x15000a3c, 0x30000000 },
-  { 0x15800a3e, 0x28000002 },
-  { 0x15800a41, 0x30000001 },
-  { 0x15800a47, 0x30000001 },
-  { 0x15800a4b, 0x30000002 },
-  { 0x15800a59, 0x1c000003 },
-  { 0x15000a5e, 0x1c000000 },
-  { 0x15800a66, 0x34000009 },
-  { 0x15800a70, 0x30000001 },
-  { 0x15800a72, 0x1c000002 },
-  { 0x14800a81, 0x30000001 },
-  { 0x14000a83, 0x28000000 },
-  { 0x14800a85, 0x1c000008 },
-  { 0x14800a8f, 0x1c000002 },
-  { 0x14800a93, 0x1c000015 },
-  { 0x14800aaa, 0x1c000006 },
-  { 0x14800ab2, 0x1c000001 },
-  { 0x14800ab5, 0x1c000004 },
-  { 0x14000abc, 0x30000000 },
-  { 0x14000abd, 0x1c000000 },
-  { 0x14800abe, 0x28000002 },
-  { 0x14800ac1, 0x30000004 },
-  { 0x14800ac7, 0x30000001 },
-  { 0x14000ac9, 0x28000000 },
-  { 0x14800acb, 0x28000001 },
-  { 0x14000acd, 0x30000000 },
-  { 0x14000ad0, 0x1c000000 },
-  { 0x14800ae0, 0x1c000001 },
-  { 0x14800ae2, 0x30000001 },
-  { 0x14800ae6, 0x34000009 },
-  { 0x14000af1, 0x5c000000 },
-  { 0x2b000b01, 0x30000000 },
-  { 0x2b800b02, 0x28000001 },
-  { 0x2b800b05, 0x1c000007 },
-  { 0x2b800b0f, 0x1c000001 },
-  { 0x2b800b13, 0x1c000015 },
-  { 0x2b800b2a, 0x1c000006 },
-  { 0x2b800b32, 0x1c000001 },
-  { 0x2b800b35, 0x1c000004 },
-  { 0x2b000b3c, 0x30000000 },
-  { 0x2b000b3d, 0x1c000000 },
-  { 0x2b000b3e, 0x28000000 },
-  { 0x2b000b3f, 0x30000000 },
-  { 0x2b000b40, 0x28000000 },
-  { 0x2b800b41, 0x30000002 },
-  { 0x2b800b47, 0x28000001 },
-  { 0x2b800b4b, 0x28000001 },
-  { 0x2b000b4d, 0x30000000 },
-  { 0x2b000b56, 0x30000000 },
-  { 0x2b000b57, 0x28000000 },
-  { 0x2b800b5c, 0x1c000001 },
-  { 0x2b800b5f, 0x1c000002 },
-  { 0x2b800b66, 0x34000009 },
-  { 0x2b000b70, 0x68000000 },
-  { 0x2b000b71, 0x1c000000 },
-  { 0x35000b82, 0x30000000 },
-  { 0x35000b83, 0x1c000000 },
-  { 0x35800b85, 0x1c000005 },
-  { 0x35800b8e, 0x1c000002 },
-  { 0x35800b92, 0x1c000003 },
-  { 0x35800b99, 0x1c000001 },
-  { 0x35000b9c, 0x1c000000 },
-  { 0x35800b9e, 0x1c000001 },
-  { 0x35800ba3, 0x1c000001 },
-  { 0x35800ba8, 0x1c000002 },
-  { 0x35800bae, 0x1c00000b },
-  { 0x35800bbe, 0x28000001 },
-  { 0x35000bc0, 0x30000000 },
-  { 0x35800bc1, 0x28000001 },
-  { 0x35800bc6, 0x28000002 },
-  { 0x35800bca, 0x28000002 },
-  { 0x35000bcd, 0x30000000 },
-  { 0x35000bd7, 0x28000000 },
-  { 0x35800be6, 0x34000009 },
-  { 0x35800bf0, 0x3c000002 },
-  { 0x35800bf3, 0x68000005 },
-  { 0x35000bf9, 0x5c000000 },
-  { 0x35000bfa, 0x68000000 },
-  { 0x36800c01, 0x28000002 },
-  { 0x36800c05, 0x1c000007 },
-  { 0x36800c0e, 0x1c000002 },
-  { 0x36800c12, 0x1c000016 },
-  { 0x36800c2a, 0x1c000009 },
-  { 0x36800c35, 0x1c000004 },
-  { 0x36800c3e, 0x30000002 },
-  { 0x36800c41, 0x28000003 },
-  { 0x36800c46, 0x30000002 },
-  { 0x36800c4a, 0x30000003 },
-  { 0x36800c55, 0x30000001 },
-  { 0x36800c60, 0x1c000001 },
-  { 0x36800c66, 0x34000009 },
-  { 0x1c800c82, 0x28000001 },
-  { 0x1c800c85, 0x1c000007 },
-  { 0x1c800c8e, 0x1c000002 },
-  { 0x1c800c92, 0x1c000016 },
-  { 0x1c800caa, 0x1c000009 },
-  { 0x1c800cb5, 0x1c000004 },
-  { 0x1c000cbc, 0x30000000 },
-  { 0x1c000cbd, 0x1c000000 },
-  { 0x1c000cbe, 0x28000000 },
-  { 0x1c000cbf, 0x30000000 },
-  { 0x1c800cc0, 0x28000004 },
-  { 0x1c000cc6, 0x30000000 },
-  { 0x1c800cc7, 0x28000001 },
-  { 0x1c800cca, 0x28000001 },
-  { 0x1c800ccc, 0x30000001 },
-  { 0x1c800cd5, 0x28000001 },
-  { 0x1c000cde, 0x1c000000 },
-  { 0x1c800ce0, 0x1c000001 },
-  { 0x1c800ce6, 0x34000009 },
-  { 0x24800d02, 0x28000001 },
-  { 0x24800d05, 0x1c000007 },
-  { 0x24800d0e, 0x1c000002 },
-  { 0x24800d12, 0x1c000016 },
-  { 0x24800d2a, 0x1c00000f },
-  { 0x24800d3e, 0x28000002 },
-  { 0x24800d41, 0x30000002 },
-  { 0x24800d46, 0x28000002 },
-  { 0x24800d4a, 0x28000002 },
-  { 0x24000d4d, 0x30000000 },
-  { 0x24000d57, 0x28000000 },
-  { 0x24800d60, 0x1c000001 },
-  { 0x24800d66, 0x34000009 },
-  { 0x2f800d82, 0x28000001 },
-  { 0x2f800d85, 0x1c000011 },
-  { 0x2f800d9a, 0x1c000017 },
-  { 0x2f800db3, 0x1c000008 },
-  { 0x2f000dbd, 0x1c000000 },
-  { 0x2f800dc0, 0x1c000006 },
-  { 0x2f000dca, 0x30000000 },
-  { 0x2f800dcf, 0x28000002 },
-  { 0x2f800dd2, 0x30000002 },
-  { 0x2f000dd6, 0x30000000 },
-  { 0x2f800dd8, 0x28000007 },
-  { 0x2f800df2, 0x28000001 },
-  { 0x2f000df4, 0x54000000 },
-  { 0x38800e01, 0x1c00002f },
-  { 0x38000e31, 0x30000000 },
-  { 0x38800e32, 0x1c000001 },
-  { 0x38800e34, 0x30000006 },
-  { 0x09000e3f, 0x5c000000 },
-  { 0x38800e40, 0x1c000005 },
-  { 0x38000e46, 0x18000000 },
-  { 0x38800e47, 0x30000007 },
-  { 0x38000e4f, 0x54000000 },
-  { 0x38800e50, 0x34000009 },
-  { 0x38800e5a, 0x54000001 },
-  { 0x20800e81, 0x1c000001 },
-  { 0x20000e84, 0x1c000000 },
-  { 0x20800e87, 0x1c000001 },
-  { 0x20000e8a, 0x1c000000 },
-  { 0x20000e8d, 0x1c000000 },
-  { 0x20800e94, 0x1c000003 },
-  { 0x20800e99, 0x1c000006 },
-  { 0x20800ea1, 0x1c000002 },
-  { 0x20000ea5, 0x1c000000 },
-  { 0x20000ea7, 0x1c000000 },
-  { 0x20800eaa, 0x1c000001 },
-  { 0x20800ead, 0x1c000003 },
-  { 0x20000eb1, 0x30000000 },
-  { 0x20800eb2, 0x1c000001 },
-  { 0x20800eb4, 0x30000005 },
-  { 0x20800ebb, 0x30000001 },
-  { 0x20000ebd, 0x1c000000 },
-  { 0x20800ec0, 0x1c000004 },
-  { 0x20000ec6, 0x18000000 },
-  { 0x20800ec8, 0x30000005 },
-  { 0x20800ed0, 0x34000009 },
-  { 0x20800edc, 0x1c000001 },
-  { 0x39000f00, 0x1c000000 },
-  { 0x39800f01, 0x68000002 },
-  { 0x39800f04, 0x5400000e },
-  { 0x39800f13, 0x68000004 },
-  { 0x39800f18, 0x30000001 },
-  { 0x39800f1a, 0x68000005 },
-  { 0x39800f20, 0x34000009 },
-  { 0x39800f2a, 0x3c000009 },
-  { 0x39000f34, 0x68000000 },
-  { 0x39000f35, 0x30000000 },
-  { 0x39000f36, 0x68000000 },
-  { 0x39000f37, 0x30000000 },
-  { 0x39000f38, 0x68000000 },
-  { 0x39000f39, 0x30000000 },
-  { 0x39000f3a, 0x58000000 },
-  { 0x39000f3b, 0x48000000 },
-  { 0x39000f3c, 0x58000000 },
-  { 0x39000f3d, 0x48000000 },
-  { 0x39800f3e, 0x28000001 },
-  { 0x39800f40, 0x1c000007 },
-  { 0x39800f49, 0x1c000021 },
-  { 0x39800f71, 0x3000000d },
-  { 0x39000f7f, 0x28000000 },
-  { 0x39800f80, 0x30000004 },
-  { 0x39000f85, 0x54000000 },
-  { 0x39800f86, 0x30000001 },
-  { 0x39800f88, 0x1c000003 },
-  { 0x39800f90, 0x30000007 },
-  { 0x39800f99, 0x30000023 },
-  { 0x39800fbe, 0x68000007 },
-  { 0x39000fc6, 0x30000000 },
-  { 0x39800fc7, 0x68000005 },
-  { 0x39000fcf, 0x68000000 },
-  { 0x39800fd0, 0x54000001 },
-  { 0x26801000, 0x1c000021 },
-  { 0x26801023, 0x1c000004 },
-  { 0x26801029, 0x1c000001 },
-  { 0x2600102c, 0x28000000 },
-  { 0x2680102d, 0x30000003 },
-  { 0x26001031, 0x28000000 },
-  { 0x26001032, 0x30000000 },
-  { 0x26801036, 0x30000001 },
-  { 0x26001038, 0x28000000 },
-  { 0x26001039, 0x30000000 },
-  { 0x26801040, 0x34000009 },
-  { 0x2680104a, 0x54000005 },
-  { 0x26801050, 0x1c000005 },
-  { 0x26801056, 0x28000001 },
-  { 0x26801058, 0x30000001 },
-  { 0x100010a0, 0x24001c60 },
-  { 0x100010a1, 0x24001c60 },
-  { 0x100010a2, 0x24001c60 },
-  { 0x100010a3, 0x24001c60 },
-  { 0x100010a4, 0x24001c60 },
-  { 0x100010a5, 0x24001c60 },
-  { 0x100010a6, 0x24001c60 },
-  { 0x100010a7, 0x24001c60 },
-  { 0x100010a8, 0x24001c60 },
-  { 0x100010a9, 0x24001c60 },
-  { 0x100010aa, 0x24001c60 },
-  { 0x100010ab, 0x24001c60 },
-  { 0x100010ac, 0x24001c60 },
-  { 0x100010ad, 0x24001c60 },
-  { 0x100010ae, 0x24001c60 },
-  { 0x100010af, 0x24001c60 },
-  { 0x100010b0, 0x24001c60 },
-  { 0x100010b1, 0x24001c60 },
-  { 0x100010b2, 0x24001c60 },
-  { 0x100010b3, 0x24001c60 },
-  { 0x100010b4, 0x24001c60 },
-  { 0x100010b5, 0x24001c60 },
-  { 0x100010b6, 0x24001c60 },
-  { 0x100010b7, 0x24001c60 },
-  { 0x100010b8, 0x24001c60 },
-  { 0x100010b9, 0x24001c60 },
-  { 0x100010ba, 0x24001c60 },
-  { 0x100010bb, 0x24001c60 },
-  { 0x100010bc, 0x24001c60 },
-  { 0x100010bd, 0x24001c60 },
-  { 0x100010be, 0x24001c60 },
-  { 0x100010bf, 0x24001c60 },
-  { 0x100010c0, 0x24001c60 },
-  { 0x100010c1, 0x24001c60 },
-  { 0x100010c2, 0x24001c60 },
-  { 0x100010c3, 0x24001c60 },
-  { 0x100010c4, 0x24001c60 },
-  { 0x100010c5, 0x24001c60 },
-  { 0x108010d0, 0x1c00002a },
-  { 0x090010fb, 0x54000000 },
-  { 0x100010fc, 0x18000000 },
-  { 0x17801100, 0x1c000059 },
-  { 0x1780115f, 0x1c000043 },
-  { 0x178011a8, 0x1c000051 },
-  { 0x0f801200, 0x1c000048 },
-  { 0x0f80124a, 0x1c000003 },
-  { 0x0f801250, 0x1c000006 },
-  { 0x0f001258, 0x1c000000 },
-  { 0x0f80125a, 0x1c000003 },
-  { 0x0f801260, 0x1c000028 },
-  { 0x0f80128a, 0x1c000003 },
-  { 0x0f801290, 0x1c000020 },
-  { 0x0f8012b2, 0x1c000003 },
-  { 0x0f8012b8, 0x1c000006 },
-  { 0x0f0012c0, 0x1c000000 },
-  { 0x0f8012c2, 0x1c000003 },
-  { 0x0f8012c8, 0x1c00000e },
-  { 0x0f8012d8, 0x1c000038 },
-  { 0x0f801312, 0x1c000003 },
-  { 0x0f801318, 0x1c000042 },
-  { 0x0f00135f, 0x30000000 },
-  { 0x0f001360, 0x68000000 },
-  { 0x0f801361, 0x54000007 },
-  { 0x0f801369, 0x3c000013 },
-  { 0x0f801380, 0x1c00000f },
-  { 0x0f801390, 0x68000009 },
-  { 0x088013a0, 0x1c000054 },
-  { 0x07801401, 0x1c00026b },
-  { 0x0780166d, 0x54000001 },
-  { 0x0780166f, 0x1c000007 },
-  { 0x28001680, 0x74000000 },
-  { 0x28801681, 0x1c000019 },
-  { 0x2800169b, 0x58000000 },
-  { 0x2800169c, 0x48000000 },
-  { 0x2d8016a0, 0x1c00004a },
-  { 0x098016eb, 0x54000002 },
-  { 0x2d8016ee, 0x38000002 },
-  { 0x32801700, 0x1c00000c },
-  { 0x3280170e, 0x1c000003 },
-  { 0x32801712, 0x30000002 },
-  { 0x18801720, 0x1c000011 },
-  { 0x18801732, 0x30000002 },
-  { 0x09801735, 0x54000001 },
-  { 0x06801740, 0x1c000011 },
-  { 0x06801752, 0x30000001 },
-  { 0x33801760, 0x1c00000c },
-  { 0x3380176e, 0x1c000002 },
-  { 0x33801772, 0x30000001 },
-  { 0x1f801780, 0x1c000033 },
-  { 0x1f8017b4, 0x04000001 },
-  { 0x1f0017b6, 0x28000000 },
-  { 0x1f8017b7, 0x30000006 },
-  { 0x1f8017be, 0x28000007 },
-  { 0x1f0017c6, 0x30000000 },
-  { 0x1f8017c7, 0x28000001 },
-  { 0x1f8017c9, 0x3000000a },
-  { 0x1f8017d4, 0x54000002 },
-  { 0x1f0017d7, 0x18000000 },
-  { 0x1f8017d8, 0x54000002 },
-  { 0x1f0017db, 0x5c000000 },
-  { 0x1f0017dc, 0x1c000000 },
-  { 0x1f0017dd, 0x30000000 },
-  { 0x1f8017e0, 0x34000009 },
-  { 0x1f8017f0, 0x3c000009 },
-  { 0x25801800, 0x54000005 },
-  { 0x25001806, 0x44000000 },
-  { 0x25801807, 0x54000003 },
-  { 0x2580180b, 0x30000002 },
-  { 0x2500180e, 0x74000000 },
-  { 0x25801810, 0x34000009 },
-  { 0x25801820, 0x1c000022 },
-  { 0x25001843, 0x18000000 },
-  { 0x25801844, 0x1c000033 },
-  { 0x25801880, 0x1c000028 },
-  { 0x250018a9, 0x30000000 },
-  { 0x22801900, 0x1c00001c },
-  { 0x22801920, 0x30000002 },
-  { 0x22801923, 0x28000003 },
-  { 0x22801927, 0x30000001 },
-  { 0x22801929, 0x28000002 },
-  { 0x22801930, 0x28000001 },
-  { 0x22001932, 0x30000000 },
-  { 0x22801933, 0x28000005 },
-  { 0x22801939, 0x30000002 },
-  { 0x22001940, 0x68000000 },
-  { 0x22801944, 0x54000001 },
-  { 0x22801946, 0x34000009 },
-  { 0x34801950, 0x1c00001d },
-  { 0x34801970, 0x1c000004 },
-  { 0x27801980, 0x1c000029 },
-  { 0x278019b0, 0x28000010 },
-  { 0x278019c1, 0x1c000006 },
-  { 0x278019c8, 0x28000001 },
-  { 0x278019d0, 0x34000009 },
-  { 0x278019de, 0x54000001 },
-  { 0x1f8019e0, 0x6800001f },
-  { 0x05801a00, 0x1c000016 },
-  { 0x05801a17, 0x30000001 },
-  { 0x05801a19, 0x28000002 },
-  { 0x05801a1e, 0x54000001 },
-  { 0x21801d00, 0x1400002b },
-  { 0x21801d2c, 0x18000035 },
-  { 0x21801d62, 0x14000015 },
-  { 0x0c001d78, 0x18000000 },
-  { 0x21801d79, 0x14000021 },
-  { 0x21801d9b, 0x18000024 },
-  { 0x1b801dc0, 0x30000003 },
-  { 0x21001e00, 0x24000001 },
-  { 0x21001e01, 0x1400ffff },
-  { 0x21001e02, 0x24000001 },
-  { 0x21001e03, 0x1400ffff },
-  { 0x21001e04, 0x24000001 },
-  { 0x21001e05, 0x1400ffff },
-  { 0x21001e06, 0x24000001 },
-  { 0x21001e07, 0x1400ffff },
-  { 0x21001e08, 0x24000001 },
-  { 0x21001e09, 0x1400ffff },
-  { 0x21001e0a, 0x24000001 },
-  { 0x21001e0b, 0x1400ffff },
-  { 0x21001e0c, 0x24000001 },
-  { 0x21001e0d, 0x1400ffff },
-  { 0x21001e0e, 0x24000001 },
-  { 0x21001e0f, 0x1400ffff },
-  { 0x21001e10, 0x24000001 },
-  { 0x21001e11, 0x1400ffff },
-  { 0x21001e12, 0x24000001 },
-  { 0x21001e13, 0x1400ffff },
-  { 0x21001e14, 0x24000001 },
-  { 0x21001e15, 0x1400ffff },
-  { 0x21001e16, 0x24000001 },
-  { 0x21001e17, 0x1400ffff },
-  { 0x21001e18, 0x24000001 },
-  { 0x21001e19, 0x1400ffff },
-  { 0x21001e1a, 0x24000001 },
-  { 0x21001e1b, 0x1400ffff },
-  { 0x21001e1c, 0x24000001 },
-  { 0x21001e1d, 0x1400ffff },
-  { 0x21001e1e, 0x24000001 },
-  { 0x21001e1f, 0x1400ffff },
-  { 0x21001e20, 0x24000001 },
-  { 0x21001e21, 0x1400ffff },
-  { 0x21001e22, 0x24000001 },
-  { 0x21001e23, 0x1400ffff },
-  { 0x21001e24, 0x24000001 },
-  { 0x21001e25, 0x1400ffff },
-  { 0x21001e26, 0x24000001 },
-  { 0x21001e27, 0x1400ffff },
-  { 0x21001e28, 0x24000001 },
-  { 0x21001e29, 0x1400ffff },
-  { 0x21001e2a, 0x24000001 },
-  { 0x21001e2b, 0x1400ffff },
-  { 0x21001e2c, 0x24000001 },
-  { 0x21001e2d, 0x1400ffff },
-  { 0x21001e2e, 0x24000001 },
-  { 0x21001e2f, 0x1400ffff },
-  { 0x21001e30, 0x24000001 },
-  { 0x21001e31, 0x1400ffff },
-  { 0x21001e32, 0x24000001 },
-  { 0x21001e33, 0x1400ffff },
-  { 0x21001e34, 0x24000001 },
-  { 0x21001e35, 0x1400ffff },
-  { 0x21001e36, 0x24000001 },
-  { 0x21001e37, 0x1400ffff },
-  { 0x21001e38, 0x24000001 },
-  { 0x21001e39, 0x1400ffff },
-  { 0x21001e3a, 0x24000001 },
-  { 0x21001e3b, 0x1400ffff },
-  { 0x21001e3c, 0x24000001 },
-  { 0x21001e3d, 0x1400ffff },
-  { 0x21001e3e, 0x24000001 },
-  { 0x21001e3f, 0x1400ffff },
-  { 0x21001e40, 0x24000001 },
-  { 0x21001e41, 0x1400ffff },
-  { 0x21001e42, 0x24000001 },
-  { 0x21001e43, 0x1400ffff },
-  { 0x21001e44, 0x24000001 },
-  { 0x21001e45, 0x1400ffff },
-  { 0x21001e46, 0x24000001 },
-  { 0x21001e47, 0x1400ffff },
-  { 0x21001e48, 0x24000001 },
-  { 0x21001e49, 0x1400ffff },
-  { 0x21001e4a, 0x24000001 },
-  { 0x21001e4b, 0x1400ffff },
-  { 0x21001e4c, 0x24000001 },
-  { 0x21001e4d, 0x1400ffff },
-  { 0x21001e4e, 0x24000001 },
-  { 0x21001e4f, 0x1400ffff },
-  { 0x21001e50, 0x24000001 },
-  { 0x21001e51, 0x1400ffff },
-  { 0x21001e52, 0x24000001 },
-  { 0x21001e53, 0x1400ffff },
-  { 0x21001e54, 0x24000001 },
-  { 0x21001e55, 0x1400ffff },
-  { 0x21001e56, 0x24000001 },
-  { 0x21001e57, 0x1400ffff },
-  { 0x21001e58, 0x24000001 },
-  { 0x21001e59, 0x1400ffff },
-  { 0x21001e5a, 0x24000001 },
-  { 0x21001e5b, 0x1400ffff },
-  { 0x21001e5c, 0x24000001 },
-  { 0x21001e5d, 0x1400ffff },
-  { 0x21001e5e, 0x24000001 },
-  { 0x21001e5f, 0x1400ffff },
-  { 0x21001e60, 0x24000001 },
-  { 0x21001e61, 0x1400ffff },
-  { 0x21001e62, 0x24000001 },
-  { 0x21001e63, 0x1400ffff },
-  { 0x21001e64, 0x24000001 },
-  { 0x21001e65, 0x1400ffff },
-  { 0x21001e66, 0x24000001 },
-  { 0x21001e67, 0x1400ffff },
-  { 0x21001e68, 0x24000001 },
-  { 0x21001e69, 0x1400ffff },
-  { 0x21001e6a, 0x24000001 },
-  { 0x21001e6b, 0x1400ffff },
-  { 0x21001e6c, 0x24000001 },
-  { 0x21001e6d, 0x1400ffff },
-  { 0x21001e6e, 0x24000001 },
-  { 0x21001e6f, 0x1400ffff },
-  { 0x21001e70, 0x24000001 },
-  { 0x21001e71, 0x1400ffff },
-  { 0x21001e72, 0x24000001 },
-  { 0x21001e73, 0x1400ffff },
-  { 0x21001e74, 0x24000001 },
-  { 0x21001e75, 0x1400ffff },
-  { 0x21001e76, 0x24000001 },
-  { 0x21001e77, 0x1400ffff },
-  { 0x21001e78, 0x24000001 },
-  { 0x21001e79, 0x1400ffff },
-  { 0x21001e7a, 0x24000001 },
-  { 0x21001e7b, 0x1400ffff },
-  { 0x21001e7c, 0x24000001 },
-  { 0x21001e7d, 0x1400ffff },
-  { 0x21001e7e, 0x24000001 },
-  { 0x21001e7f, 0x1400ffff },
-  { 0x21001e80, 0x24000001 },
-  { 0x21001e81, 0x1400ffff },
-  { 0x21001e82, 0x24000001 },
-  { 0x21001e83, 0x1400ffff },
-  { 0x21001e84, 0x24000001 },
-  { 0x21001e85, 0x1400ffff },
-  { 0x21001e86, 0x24000001 },
-  { 0x21001e87, 0x1400ffff },
-  { 0x21001e88, 0x24000001 },
-  { 0x21001e89, 0x1400ffff },
-  { 0x21001e8a, 0x24000001 },
-  { 0x21001e8b, 0x1400ffff },
-  { 0x21001e8c, 0x24000001 },
-  { 0x21001e8d, 0x1400ffff },
-  { 0x21001e8e, 0x24000001 },
-  { 0x21001e8f, 0x1400ffff },
-  { 0x21001e90, 0x24000001 },
-  { 0x21001e91, 0x1400ffff },
-  { 0x21001e92, 0x24000001 },
-  { 0x21001e93, 0x1400ffff },
-  { 0x21001e94, 0x24000001 },
-  { 0x21001e95, 0x1400ffff },
-  { 0x21801e96, 0x14000004 },
-  { 0x21001e9b, 0x1400ffc5 },
-  { 0x21001ea0, 0x24000001 },
-  { 0x21001ea1, 0x1400ffff },
-  { 0x21001ea2, 0x24000001 },
-  { 0x21001ea3, 0x1400ffff },
-  { 0x21001ea4, 0x24000001 },
-  { 0x21001ea5, 0x1400ffff },
-  { 0x21001ea6, 0x24000001 },
-  { 0x21001ea7, 0x1400ffff },
-  { 0x21001ea8, 0x24000001 },
-  { 0x21001ea9, 0x1400ffff },
-  { 0x21001eaa, 0x24000001 },
-  { 0x21001eab, 0x1400ffff },
-  { 0x21001eac, 0x24000001 },
-  { 0x21001ead, 0x1400ffff },
-  { 0x21001eae, 0x24000001 },
-  { 0x21001eaf, 0x1400ffff },
-  { 0x21001eb0, 0x24000001 },
-  { 0x21001eb1, 0x1400ffff },
-  { 0x21001eb2, 0x24000001 },
-  { 0x21001eb3, 0x1400ffff },
-  { 0x21001eb4, 0x24000001 },
-  { 0x21001eb5, 0x1400ffff },
-  { 0x21001eb6, 0x24000001 },
-  { 0x21001eb7, 0x1400ffff },
-  { 0x21001eb8, 0x24000001 },
-  { 0x21001eb9, 0x1400ffff },
-  { 0x21001eba, 0x24000001 },
-  { 0x21001ebb, 0x1400ffff },
-  { 0x21001ebc, 0x24000001 },
-  { 0x21001ebd, 0x1400ffff },
-  { 0x21001ebe, 0x24000001 },
-  { 0x21001ebf, 0x1400ffff },
-  { 0x21001ec0, 0x24000001 },
-  { 0x21001ec1, 0x1400ffff },
-  { 0x21001ec2, 0x24000001 },
-  { 0x21001ec3, 0x1400ffff },
-  { 0x21001ec4, 0x24000001 },
-  { 0x21001ec5, 0x1400ffff },
-  { 0x21001ec6, 0x24000001 },
-  { 0x21001ec7, 0x1400ffff },
-  { 0x21001ec8, 0x24000001 },
-  { 0x21001ec9, 0x1400ffff },
-  { 0x21001eca, 0x24000001 },
-  { 0x21001ecb, 0x1400ffff },
-  { 0x21001ecc, 0x24000001 },
-  { 0x21001ecd, 0x1400ffff },
-  { 0x21001ece, 0x24000001 },
-  { 0x21001ecf, 0x1400ffff },
-  { 0x21001ed0, 0x24000001 },
-  { 0x21001ed1, 0x1400ffff },
-  { 0x21001ed2, 0x24000001 },
-  { 0x21001ed3, 0x1400ffff },
-  { 0x21001ed4, 0x24000001 },
-  { 0x21001ed5, 0x1400ffff },
-  { 0x21001ed6, 0x24000001 },
-  { 0x21001ed7, 0x1400ffff },
-  { 0x21001ed8, 0x24000001 },
-  { 0x21001ed9, 0x1400ffff },
-  { 0x21001eda, 0x24000001 },
-  { 0x21001edb, 0x1400ffff },
-  { 0x21001edc, 0x24000001 },
-  { 0x21001edd, 0x1400ffff },
-  { 0x21001ede, 0x24000001 },
-  { 0x21001edf, 0x1400ffff },
-  { 0x21001ee0, 0x24000001 },
-  { 0x21001ee1, 0x1400ffff },
-  { 0x21001ee2, 0x24000001 },
-  { 0x21001ee3, 0x1400ffff },
-  { 0x21001ee4, 0x24000001 },
-  { 0x21001ee5, 0x1400ffff },
-  { 0x21001ee6, 0x24000001 },
-  { 0x21001ee7, 0x1400ffff },
-  { 0x21001ee8, 0x24000001 },
-  { 0x21001ee9, 0x1400ffff },
-  { 0x21001eea, 0x24000001 },
-  { 0x21001eeb, 0x1400ffff },
-  { 0x21001eec, 0x24000001 },
-  { 0x21001eed, 0x1400ffff },
-  { 0x21001eee, 0x24000001 },
-  { 0x21001eef, 0x1400ffff },
-  { 0x21001ef0, 0x24000001 },
-  { 0x21001ef1, 0x1400ffff },
-  { 0x21001ef2, 0x24000001 },
-  { 0x21001ef3, 0x1400ffff },
-  { 0x21001ef4, 0x24000001 },
-  { 0x21001ef5, 0x1400ffff },
-  { 0x21001ef6, 0x24000001 },
-  { 0x21001ef7, 0x1400ffff },
-  { 0x21001ef8, 0x24000001 },
-  { 0x21001ef9, 0x1400ffff },
-  { 0x13001f00, 0x14000008 },
-  { 0x13001f01, 0x14000008 },
-  { 0x13001f02, 0x14000008 },
-  { 0x13001f03, 0x14000008 },
-  { 0x13001f04, 0x14000008 },
-  { 0x13001f05, 0x14000008 },
-  { 0x13001f06, 0x14000008 },
-  { 0x13001f07, 0x14000008 },
-  { 0x13001f08, 0x2400fff8 },
-  { 0x13001f09, 0x2400fff8 },
-  { 0x13001f0a, 0x2400fff8 },
-  { 0x13001f0b, 0x2400fff8 },
-  { 0x13001f0c, 0x2400fff8 },
-  { 0x13001f0d, 0x2400fff8 },
-  { 0x13001f0e, 0x2400fff8 },
-  { 0x13001f0f, 0x2400fff8 },
-  { 0x13001f10, 0x14000008 },
-  { 0x13001f11, 0x14000008 },
-  { 0x13001f12, 0x14000008 },
-  { 0x13001f13, 0x14000008 },
-  { 0x13001f14, 0x14000008 },
-  { 0x13001f15, 0x14000008 },
-  { 0x13001f18, 0x2400fff8 },
-  { 0x13001f19, 0x2400fff8 },
-  { 0x13001f1a, 0x2400fff8 },
-  { 0x13001f1b, 0x2400fff8 },
-  { 0x13001f1c, 0x2400fff8 },
-  { 0x13001f1d, 0x2400fff8 },
-  { 0x13001f20, 0x14000008 },
-  { 0x13001f21, 0x14000008 },
-  { 0x13001f22, 0x14000008 },
-  { 0x13001f23, 0x14000008 },
-  { 0x13001f24, 0x14000008 },
-  { 0x13001f25, 0x14000008 },
-  { 0x13001f26, 0x14000008 },
-  { 0x13001f27, 0x14000008 },
-  { 0x13001f28, 0x2400fff8 },
-  { 0x13001f29, 0x2400fff8 },
-  { 0x13001f2a, 0x2400fff8 },
-  { 0x13001f2b, 0x2400fff8 },
-  { 0x13001f2c, 0x2400fff8 },
-  { 0x13001f2d, 0x2400fff8 },
-  { 0x13001f2e, 0x2400fff8 },
-  { 0x13001f2f, 0x2400fff8 },
-  { 0x13001f30, 0x14000008 },
-  { 0x13001f31, 0x14000008 },
-  { 0x13001f32, 0x14000008 },
-  { 0x13001f33, 0x14000008 },
-  { 0x13001f34, 0x14000008 },
-  { 0x13001f35, 0x14000008 },
-  { 0x13001f36, 0x14000008 },
-  { 0x13001f37, 0x14000008 },
-  { 0x13001f38, 0x2400fff8 },
-  { 0x13001f39, 0x2400fff8 },
-  { 0x13001f3a, 0x2400fff8 },
-  { 0x13001f3b, 0x2400fff8 },
-  { 0x13001f3c, 0x2400fff8 },
-  { 0x13001f3d, 0x2400fff8 },
-  { 0x13001f3e, 0x2400fff8 },
-  { 0x13001f3f, 0x2400fff8 },
-  { 0x13001f40, 0x14000008 },
-  { 0x13001f41, 0x14000008 },
-  { 0x13001f42, 0x14000008 },
-  { 0x13001f43, 0x14000008 },
-  { 0x13001f44, 0x14000008 },
-  { 0x13001f45, 0x14000008 },
-  { 0x13001f48, 0x2400fff8 },
-  { 0x13001f49, 0x2400fff8 },
-  { 0x13001f4a, 0x2400fff8 },
-  { 0x13001f4b, 0x2400fff8 },
-  { 0x13001f4c, 0x2400fff8 },
-  { 0x13001f4d, 0x2400fff8 },
-  { 0x13001f50, 0x14000000 },
-  { 0x13001f51, 0x14000008 },
-  { 0x13001f52, 0x14000000 },
-  { 0x13001f53, 0x14000008 },
-  { 0x13001f54, 0x14000000 },
-  { 0x13001f55, 0x14000008 },
-  { 0x13001f56, 0x14000000 },
-  { 0x13001f57, 0x14000008 },
-  { 0x13001f59, 0x2400fff8 },
-  { 0x13001f5b, 0x2400fff8 },
-  { 0x13001f5d, 0x2400fff8 },
-  { 0x13001f5f, 0x2400fff8 },
-  { 0x13001f60, 0x14000008 },
-  { 0x13001f61, 0x14000008 },
-  { 0x13001f62, 0x14000008 },
-  { 0x13001f63, 0x14000008 },
-  { 0x13001f64, 0x14000008 },
-  { 0x13001f65, 0x14000008 },
-  { 0x13001f66, 0x14000008 },
-  { 0x13001f67, 0x14000008 },
-  { 0x13001f68, 0x2400fff8 },
-  { 0x13001f69, 0x2400fff8 },
-  { 0x13001f6a, 0x2400fff8 },
-  { 0x13001f6b, 0x2400fff8 },
-  { 0x13001f6c, 0x2400fff8 },
-  { 0x13001f6d, 0x2400fff8 },
-  { 0x13001f6e, 0x2400fff8 },
-  { 0x13001f6f, 0x2400fff8 },
-  { 0x13001f70, 0x1400004a },
-  { 0x13001f71, 0x1400004a },
-  { 0x13001f72, 0x14000056 },
-  { 0x13001f73, 0x14000056 },
-  { 0x13001f74, 0x14000056 },
-  { 0x13001f75, 0x14000056 },
-  { 0x13001f76, 0x14000064 },
-  { 0x13001f77, 0x14000064 },
-  { 0x13001f78, 0x14000080 },
-  { 0x13001f79, 0x14000080 },
-  { 0x13001f7a, 0x14000070 },
-  { 0x13001f7b, 0x14000070 },
-  { 0x13001f7c, 0x1400007e },
-  { 0x13001f7d, 0x1400007e },
-  { 0x13001f80, 0x14000008 },
-  { 0x13001f81, 0x14000008 },
-  { 0x13001f82, 0x14000008 },
-  { 0x13001f83, 0x14000008 },
-  { 0x13001f84, 0x14000008 },
-  { 0x13001f85, 0x14000008 },
-  { 0x13001f86, 0x14000008 },
-  { 0x13001f87, 0x14000008 },
-  { 0x13001f88, 0x2000fff8 },
-  { 0x13001f89, 0x2000fff8 },
-  { 0x13001f8a, 0x2000fff8 },
-  { 0x13001f8b, 0x2000fff8 },
-  { 0x13001f8c, 0x2000fff8 },
-  { 0x13001f8d, 0x2000fff8 },
-  { 0x13001f8e, 0x2000fff8 },
-  { 0x13001f8f, 0x2000fff8 },
-  { 0x13001f90, 0x14000008 },
-  { 0x13001f91, 0x14000008 },
-  { 0x13001f92, 0x14000008 },
-  { 0x13001f93, 0x14000008 },
-  { 0x13001f94, 0x14000008 },
-  { 0x13001f95, 0x14000008 },
-  { 0x13001f96, 0x14000008 },
-  { 0x13001f97, 0x14000008 },
-  { 0x13001f98, 0x2000fff8 },
-  { 0x13001f99, 0x2000fff8 },
-  { 0x13001f9a, 0x2000fff8 },
-  { 0x13001f9b, 0x2000fff8 },
-  { 0x13001f9c, 0x2000fff8 },
-  { 0x13001f9d, 0x2000fff8 },
-  { 0x13001f9e, 0x2000fff8 },
-  { 0x13001f9f, 0x2000fff8 },
-  { 0x13001fa0, 0x14000008 },
-  { 0x13001fa1, 0x14000008 },
-  { 0x13001fa2, 0x14000008 },
-  { 0x13001fa3, 0x14000008 },
-  { 0x13001fa4, 0x14000008 },
-  { 0x13001fa5, 0x14000008 },
-  { 0x13001fa6, 0x14000008 },
-  { 0x13001fa7, 0x14000008 },
-  { 0x13001fa8, 0x2000fff8 },
-  { 0x13001fa9, 0x2000fff8 },
-  { 0x13001faa, 0x2000fff8 },
-  { 0x13001fab, 0x2000fff8 },
-  { 0x13001fac, 0x2000fff8 },
-  { 0x13001fad, 0x2000fff8 },
-  { 0x13001fae, 0x2000fff8 },
-  { 0x13001faf, 0x2000fff8 },
-  { 0x13001fb0, 0x14000008 },
-  { 0x13001fb1, 0x14000008 },
-  { 0x13001fb2, 0x14000000 },
-  { 0x13001fb3, 0x14000009 },
-  { 0x13001fb4, 0x14000000 },
-  { 0x13801fb6, 0x14000001 },
-  { 0x13001fb8, 0x2400fff8 },
-  { 0x13001fb9, 0x2400fff8 },
-  { 0x13001fba, 0x2400ffb6 },
-  { 0x13001fbb, 0x2400ffb6 },
-  { 0x13001fbc, 0x2000fff7 },
-  { 0x13001fbd, 0x60000000 },
-  { 0x13001fbe, 0x1400e3db },
-  { 0x13801fbf, 0x60000002 },
-  { 0x13001fc2, 0x14000000 },
-  { 0x13001fc3, 0x14000009 },
-  { 0x13001fc4, 0x14000000 },
-  { 0x13801fc6, 0x14000001 },
-  { 0x13001fc8, 0x2400ffaa },
-  { 0x13001fc9, 0x2400ffaa },
-  { 0x13001fca, 0x2400ffaa },
-  { 0x13001fcb, 0x2400ffaa },
-  { 0x13001fcc, 0x2000fff7 },
-  { 0x13801fcd, 0x60000002 },
-  { 0x13001fd0, 0x14000008 },
-  { 0x13001fd1, 0x14000008 },
-  { 0x13801fd2, 0x14000001 },
-  { 0x13801fd6, 0x14000001 },
-  { 0x13001fd8, 0x2400fff8 },
-  { 0x13001fd9, 0x2400fff8 },
-  { 0x13001fda, 0x2400ff9c },
-  { 0x13001fdb, 0x2400ff9c },
-  { 0x13801fdd, 0x60000002 },
-  { 0x13001fe0, 0x14000008 },
-  { 0x13001fe1, 0x14000008 },
-  { 0x13801fe2, 0x14000002 },
-  { 0x13001fe5, 0x14000007 },
-  { 0x13801fe6, 0x14000001 },
-  { 0x13001fe8, 0x2400fff8 },
-  { 0x13001fe9, 0x2400fff8 },
-  { 0x13001fea, 0x2400ff90 },
-  { 0x13001feb, 0x2400ff90 },
-  { 0x13001fec, 0x2400fff9 },
-  { 0x13801fed, 0x60000002 },
-  { 0x13001ff2, 0x14000000 },
-  { 0x13001ff3, 0x14000009 },
-  { 0x13001ff4, 0x14000000 },
-  { 0x13801ff6, 0x14000001 },
-  { 0x13001ff8, 0x2400ff80 },
-  { 0x13001ff9, 0x2400ff80 },
-  { 0x13001ffa, 0x2400ff82 },
-  { 0x13001ffb, 0x2400ff82 },
-  { 0x13001ffc, 0x2000fff7 },
-  { 0x13801ffd, 0x60000001 },
-  { 0x09802000, 0x7400000a },
-  { 0x0980200b, 0x04000004 },
-  { 0x09802010, 0x44000005 },
-  { 0x09802016, 0x54000001 },
-  { 0x09002018, 0x50000000 },
-  { 0x09002019, 0x4c000000 },
-  { 0x0900201a, 0x58000000 },
-  { 0x0980201b, 0x50000001 },
-  { 0x0900201d, 0x4c000000 },
-  { 0x0900201e, 0x58000000 },
-  { 0x0900201f, 0x50000000 },
-  { 0x09802020, 0x54000007 },
-  { 0x09002028, 0x6c000000 },
-  { 0x09002029, 0x70000000 },
-  { 0x0980202a, 0x04000004 },
-  { 0x0900202f, 0x74000000 },
-  { 0x09802030, 0x54000008 },
-  { 0x09002039, 0x50000000 },
-  { 0x0900203a, 0x4c000000 },
-  { 0x0980203b, 0x54000003 },
-  { 0x0980203f, 0x40000001 },
-  { 0x09802041, 0x54000002 },
-  { 0x09002044, 0x64000000 },
-  { 0x09002045, 0x58000000 },
-  { 0x09002046, 0x48000000 },
-  { 0x09802047, 0x5400000a },
-  { 0x09002052, 0x64000000 },
-  { 0x09002053, 0x54000000 },
-  { 0x09002054, 0x40000000 },
-  { 0x09802055, 0x54000009 },
-  { 0x0900205f, 0x74000000 },
-  { 0x09802060, 0x04000003 },
-  { 0x0980206a, 0x04000005 },
-  { 0x09002070, 0x3c000000 },
-  { 0x21002071, 0x14000000 },
-  { 0x09802074, 0x3c000005 },
-  { 0x0980207a, 0x64000002 },
-  { 0x0900207d, 0x58000000 },
-  { 0x0900207e, 0x48000000 },
-  { 0x2100207f, 0x14000000 },
-  { 0x09802080, 0x3c000009 },
-  { 0x0980208a, 0x64000002 },
-  { 0x0900208d, 0x58000000 },
-  { 0x0900208e, 0x48000000 },
-  { 0x21802090, 0x18000004 },
-  { 0x098020a0, 0x5c000015 },
-  { 0x1b8020d0, 0x3000000c },
-  { 0x1b8020dd, 0x2c000003 },
-  { 0x1b0020e1, 0x30000000 },
-  { 0x1b8020e2, 0x2c000002 },
-  { 0x1b8020e5, 0x30000006 },
-  { 0x09802100, 0x68000001 },
-  { 0x09002102, 0x24000000 },
-  { 0x09802103, 0x68000003 },
-  { 0x09002107, 0x24000000 },
-  { 0x09802108, 0x68000001 },
-  { 0x0900210a, 0x14000000 },
-  { 0x0980210b, 0x24000002 },
-  { 0x0980210e, 0x14000001 },
-  { 0x09802110, 0x24000002 },
-  { 0x09002113, 0x14000000 },
-  { 0x09002114, 0x68000000 },
-  { 0x09002115, 0x24000000 },
-  { 0x09802116, 0x68000002 },
-  { 0x09802119, 0x24000004 },
-  { 0x0980211e, 0x68000005 },
-  { 0x09002124, 0x24000000 },
-  { 0x09002125, 0x68000000 },
-  { 0x13002126, 0x2400e2a3 },
-  { 0x09002127, 0x68000000 },
-  { 0x09002128, 0x24000000 },
-  { 0x09002129, 0x68000000 },
-  { 0x2100212a, 0x2400df41 },
-  { 0x2100212b, 0x2400dfba },
-  { 0x0980212c, 0x24000001 },
-  { 0x0900212e, 0x68000000 },
-  { 0x0900212f, 0x14000000 },
-  { 0x09802130, 0x24000001 },
-  { 0x09002132, 0x68000000 },
-  { 0x09002133, 0x24000000 },
-  { 0x09002134, 0x14000000 },
-  { 0x09802135, 0x1c000003 },
-  { 0x09002139, 0x14000000 },
-  { 0x0980213a, 0x68000001 },
-  { 0x0980213c, 0x14000001 },
-  { 0x0980213e, 0x24000001 },
-  { 0x09802140, 0x64000004 },
-  { 0x09002145, 0x24000000 },
-  { 0x09802146, 0x14000003 },
-  { 0x0900214a, 0x68000000 },
-  { 0x0900214b, 0x64000000 },
-  { 0x0900214c, 0x68000000 },
-  { 0x09802153, 0x3c00000c },
-  { 0x09002160, 0x38000010 },
-  { 0x09002161, 0x38000010 },
-  { 0x09002162, 0x38000010 },
-  { 0x09002163, 0x38000010 },
-  { 0x09002164, 0x38000010 },
-  { 0x09002165, 0x38000010 },
-  { 0x09002166, 0x38000010 },
-  { 0x09002167, 0x38000010 },
-  { 0x09002168, 0x38000010 },
-  { 0x09002169, 0x38000010 },
-  { 0x0900216a, 0x38000010 },
-  { 0x0900216b, 0x38000010 },
-  { 0x0900216c, 0x38000010 },
-  { 0x0900216d, 0x38000010 },
-  { 0x0900216e, 0x38000010 },
-  { 0x0900216f, 0x38000010 },
-  { 0x09002170, 0x3800fff0 },
-  { 0x09002171, 0x3800fff0 },
-  { 0x09002172, 0x3800fff0 },
-  { 0x09002173, 0x3800fff0 },
-  { 0x09002174, 0x3800fff0 },
-  { 0x09002175, 0x3800fff0 },
-  { 0x09002176, 0x3800fff0 },
-  { 0x09002177, 0x3800fff0 },
-  { 0x09002178, 0x3800fff0 },
-  { 0x09002179, 0x3800fff0 },
-  { 0x0900217a, 0x3800fff0 },
-  { 0x0900217b, 0x3800fff0 },
-  { 0x0900217c, 0x3800fff0 },
-  { 0x0900217d, 0x3800fff0 },
-  { 0x0900217e, 0x3800fff0 },
-  { 0x0900217f, 0x3800fff0 },
-  { 0x09802180, 0x38000003 },
-  { 0x09802190, 0x64000004 },
-  { 0x09802195, 0x68000004 },
-  { 0x0980219a, 0x64000001 },
-  { 0x0980219c, 0x68000003 },
-  { 0x090021a0, 0x64000000 },
-  { 0x098021a1, 0x68000001 },
-  { 0x090021a3, 0x64000000 },
-  { 0x098021a4, 0x68000001 },
-  { 0x090021a6, 0x64000000 },
-  { 0x098021a7, 0x68000006 },
-  { 0x090021ae, 0x64000000 },
-  { 0x098021af, 0x6800001e },
-  { 0x098021ce, 0x64000001 },
-  { 0x098021d0, 0x68000001 },
-  { 0x090021d2, 0x64000000 },
-  { 0x090021d3, 0x68000000 },
-  { 0x090021d4, 0x64000000 },
-  { 0x098021d5, 0x6800001e },
-  { 0x098021f4, 0x6400010b },
-  { 0x09802300, 0x68000007 },
-  { 0x09802308, 0x64000003 },
-  { 0x0980230c, 0x68000013 },
-  { 0x09802320, 0x64000001 },
-  { 0x09802322, 0x68000006 },
-  { 0x09002329, 0x58000000 },
-  { 0x0900232a, 0x48000000 },
-  { 0x0980232b, 0x68000050 },
-  { 0x0900237c, 0x64000000 },
-  { 0x0980237d, 0x6800001d },
-  { 0x0980239b, 0x64000018 },
-  { 0x090023b4, 0x58000000 },
-  { 0x090023b5, 0x48000000 },
-  { 0x090023b6, 0x54000000 },
-  { 0x098023b7, 0x68000024 },
-  { 0x09802400, 0x68000026 },
-  { 0x09802440, 0x6800000a },
-  { 0x09802460, 0x3c00003b },
-  { 0x0980249c, 0x68000019 },
-  { 0x090024b6, 0x6800001a },
-  { 0x090024b7, 0x6800001a },
-  { 0x090024b8, 0x6800001a },
-  { 0x090024b9, 0x6800001a },
-  { 0x090024ba, 0x6800001a },
-  { 0x090024bb, 0x6800001a },
-  { 0x090024bc, 0x6800001a },
-  { 0x090024bd, 0x6800001a },
-  { 0x090024be, 0x6800001a },
-  { 0x090024bf, 0x6800001a },
-  { 0x090024c0, 0x6800001a },
-  { 0x090024c1, 0x6800001a },
-  { 0x090024c2, 0x6800001a },
-  { 0x090024c3, 0x6800001a },
-  { 0x090024c4, 0x6800001a },
-  { 0x090024c5, 0x6800001a },
-  { 0x090024c6, 0x6800001a },
-  { 0x090024c7, 0x6800001a },
-  { 0x090024c8, 0x6800001a },
-  { 0x090024c9, 0x6800001a },
-  { 0x090024ca, 0x6800001a },
-  { 0x090024cb, 0x6800001a },
-  { 0x090024cc, 0x6800001a },
-  { 0x090024cd, 0x6800001a },
-  { 0x090024ce, 0x6800001a },
-  { 0x090024cf, 0x6800001a },
-  { 0x090024d0, 0x6800ffe6 },
-  { 0x090024d1, 0x6800ffe6 },
-  { 0x090024d2, 0x6800ffe6 },
-  { 0x090024d3, 0x6800ffe6 },
-  { 0x090024d4, 0x6800ffe6 },
-  { 0x090024d5, 0x6800ffe6 },
-  { 0x090024d6, 0x6800ffe6 },
-  { 0x090024d7, 0x6800ffe6 },
-  { 0x090024d8, 0x6800ffe6 },
-  { 0x090024d9, 0x6800ffe6 },
-  { 0x090024da, 0x6800ffe6 },
-  { 0x090024db, 0x6800ffe6 },
-  { 0x090024dc, 0x6800ffe6 },
-  { 0x090024dd, 0x6800ffe6 },
-  { 0x090024de, 0x6800ffe6 },
-  { 0x090024df, 0x6800ffe6 },
-  { 0x090024e0, 0x6800ffe6 },
-  { 0x090024e1, 0x6800ffe6 },
-  { 0x090024e2, 0x6800ffe6 },
-  { 0x090024e3, 0x6800ffe6 },
-  { 0x090024e4, 0x6800ffe6 },
-  { 0x090024e5, 0x6800ffe6 },
-  { 0x090024e6, 0x6800ffe6 },
-  { 0x090024e7, 0x6800ffe6 },
-  { 0x090024e8, 0x6800ffe6 },
-  { 0x090024e9, 0x6800ffe6 },
-  { 0x098024ea, 0x3c000015 },
-  { 0x09802500, 0x680000b6 },
-  { 0x090025b7, 0x64000000 },
-  { 0x098025b8, 0x68000008 },
-  { 0x090025c1, 0x64000000 },
-  { 0x098025c2, 0x68000035 },
-  { 0x098025f8, 0x64000007 },
-  { 0x09802600, 0x6800006e },
-  { 0x0900266f, 0x64000000 },
-  { 0x09802670, 0x6800002c },
-  { 0x098026a0, 0x68000011 },
-  { 0x09802701, 0x68000003 },
-  { 0x09802706, 0x68000003 },
-  { 0x0980270c, 0x6800001b },
-  { 0x09802729, 0x68000022 },
-  { 0x0900274d, 0x68000000 },
-  { 0x0980274f, 0x68000003 },
-  { 0x09002756, 0x68000000 },
-  { 0x09802758, 0x68000006 },
-  { 0x09802761, 0x68000006 },
-  { 0x09002768, 0x58000000 },
-  { 0x09002769, 0x48000000 },
-  { 0x0900276a, 0x58000000 },
-  { 0x0900276b, 0x48000000 },
-  { 0x0900276c, 0x58000000 },
-  { 0x0900276d, 0x48000000 },
-  { 0x0900276e, 0x58000000 },
-  { 0x0900276f, 0x48000000 },
-  { 0x09002770, 0x58000000 },
-  { 0x09002771, 0x48000000 },
-  { 0x09002772, 0x58000000 },
-  { 0x09002773, 0x48000000 },
-  { 0x09002774, 0x58000000 },
-  { 0x09002775, 0x48000000 },
-  { 0x09802776, 0x3c00001d },
-  { 0x09002794, 0x68000000 },
-  { 0x09802798, 0x68000017 },
-  { 0x098027b1, 0x6800000d },
-  { 0x098027c0, 0x64000004 },
-  { 0x090027c5, 0x58000000 },
-  { 0x090027c6, 0x48000000 },
-  { 0x098027d0, 0x64000015 },
-  { 0x090027e6, 0x58000000 },
-  { 0x090027e7, 0x48000000 },
-  { 0x090027e8, 0x58000000 },
-  { 0x090027e9, 0x48000000 },
-  { 0x090027ea, 0x58000000 },
-  { 0x090027eb, 0x48000000 },
-  { 0x098027f0, 0x6400000f },
-  { 0x04802800, 0x680000ff },
-  { 0x09802900, 0x64000082 },
-  { 0x09002983, 0x58000000 },
-  { 0x09002984, 0x48000000 },
-  { 0x09002985, 0x58000000 },
-  { 0x09002986, 0x48000000 },
-  { 0x09002987, 0x58000000 },
-  { 0x09002988, 0x48000000 },
-  { 0x09002989, 0x58000000 },
-  { 0x0900298a, 0x48000000 },
-  { 0x0900298b, 0x58000000 },
-  { 0x0900298c, 0x48000000 },
-  { 0x0900298d, 0x58000000 },
-  { 0x0900298e, 0x48000000 },
-  { 0x0900298f, 0x58000000 },
-  { 0x09002990, 0x48000000 },
-  { 0x09002991, 0x58000000 },
-  { 0x09002992, 0x48000000 },
-  { 0x09002993, 0x58000000 },
-  { 0x09002994, 0x48000000 },
-  { 0x09002995, 0x58000000 },
-  { 0x09002996, 0x48000000 },
-  { 0x09002997, 0x58000000 },
-  { 0x09002998, 0x48000000 },
-  { 0x09802999, 0x6400003e },
-  { 0x090029d8, 0x58000000 },
-  { 0x090029d9, 0x48000000 },
-  { 0x090029da, 0x58000000 },
-  { 0x090029db, 0x48000000 },
-  { 0x098029dc, 0x6400001f },
-  { 0x090029fc, 0x58000000 },
-  { 0x090029fd, 0x48000000 },
-  { 0x098029fe, 0x64000101 },
-  { 0x09802b00, 0x68000013 },
-  { 0x11002c00, 0x24000030 },
-  { 0x11002c01, 0x24000030 },
-  { 0x11002c02, 0x24000030 },
-  { 0x11002c03, 0x24000030 },
-  { 0x11002c04, 0x24000030 },
-  { 0x11002c05, 0x24000030 },
-  { 0x11002c06, 0x24000030 },
-  { 0x11002c07, 0x24000030 },
-  { 0x11002c08, 0x24000030 },
-  { 0x11002c09, 0x24000030 },
-  { 0x11002c0a, 0x24000030 },
-  { 0x11002c0b, 0x24000030 },
-  { 0x11002c0c, 0x24000030 },
-  { 0x11002c0d, 0x24000030 },
-  { 0x11002c0e, 0x24000030 },
-  { 0x11002c0f, 0x24000030 },
-  { 0x11002c10, 0x24000030 },
-  { 0x11002c11, 0x24000030 },
-  { 0x11002c12, 0x24000030 },
-  { 0x11002c13, 0x24000030 },
-  { 0x11002c14, 0x24000030 },
-  { 0x11002c15, 0x24000030 },
-  { 0x11002c16, 0x24000030 },
-  { 0x11002c17, 0x24000030 },
-  { 0x11002c18, 0x24000030 },
-  { 0x11002c19, 0x24000030 },
-  { 0x11002c1a, 0x24000030 },
-  { 0x11002c1b, 0x24000030 },
-  { 0x11002c1c, 0x24000030 },
-  { 0x11002c1d, 0x24000030 },
-  { 0x11002c1e, 0x24000030 },
-  { 0x11002c1f, 0x24000030 },
-  { 0x11002c20, 0x24000030 },
-  { 0x11002c21, 0x24000030 },
-  { 0x11002c22, 0x24000030 },
-  { 0x11002c23, 0x24000030 },
-  { 0x11002c24, 0x24000030 },
-  { 0x11002c25, 0x24000030 },
-  { 0x11002c26, 0x24000030 },
-  { 0x11002c27, 0x24000030 },
-  { 0x11002c28, 0x24000030 },
-  { 0x11002c29, 0x24000030 },
-  { 0x11002c2a, 0x24000030 },
-  { 0x11002c2b, 0x24000030 },
-  { 0x11002c2c, 0x24000030 },
-  { 0x11002c2d, 0x24000030 },
-  { 0x11002c2e, 0x24000030 },
-  { 0x11002c30, 0x1400ffd0 },
-  { 0x11002c31, 0x1400ffd0 },
-  { 0x11002c32, 0x1400ffd0 },
-  { 0x11002c33, 0x1400ffd0 },
-  { 0x11002c34, 0x1400ffd0 },
-  { 0x11002c35, 0x1400ffd0 },
-  { 0x11002c36, 0x1400ffd0 },
-  { 0x11002c37, 0x1400ffd0 },
-  { 0x11002c38, 0x1400ffd0 },
-  { 0x11002c39, 0x1400ffd0 },
-  { 0x11002c3a, 0x1400ffd0 },
-  { 0x11002c3b, 0x1400ffd0 },
-  { 0x11002c3c, 0x1400ffd0 },
-  { 0x11002c3d, 0x1400ffd0 },
-  { 0x11002c3e, 0x1400ffd0 },
-  { 0x11002c3f, 0x1400ffd0 },
-  { 0x11002c40, 0x1400ffd0 },
-  { 0x11002c41, 0x1400ffd0 },
-  { 0x11002c42, 0x1400ffd0 },
-  { 0x11002c43, 0x1400ffd0 },
-  { 0x11002c44, 0x1400ffd0 },
-  { 0x11002c45, 0x1400ffd0 },
-  { 0x11002c46, 0x1400ffd0 },
-  { 0x11002c47, 0x1400ffd0 },
-  { 0x11002c48, 0x1400ffd0 },
-  { 0x11002c49, 0x1400ffd0 },
-  { 0x11002c4a, 0x1400ffd0 },
-  { 0x11002c4b, 0x1400ffd0 },
-  { 0x11002c4c, 0x1400ffd0 },
-  { 0x11002c4d, 0x1400ffd0 },
-  { 0x11002c4e, 0x1400ffd0 },
-  { 0x11002c4f, 0x1400ffd0 },
-  { 0x11002c50, 0x1400ffd0 },
-  { 0x11002c51, 0x1400ffd0 },
-  { 0x11002c52, 0x1400ffd0 },
-  { 0x11002c53, 0x1400ffd0 },
-  { 0x11002c54, 0x1400ffd0 },
-  { 0x11002c55, 0x1400ffd0 },
-  { 0x11002c56, 0x1400ffd0 },
-  { 0x11002c57, 0x1400ffd0 },
-  { 0x11002c58, 0x1400ffd0 },
-  { 0x11002c59, 0x1400ffd0 },
-  { 0x11002c5a, 0x1400ffd0 },
-  { 0x11002c5b, 0x1400ffd0 },
-  { 0x11002c5c, 0x1400ffd0 },
-  { 0x11002c5d, 0x1400ffd0 },
-  { 0x11002c5e, 0x1400ffd0 },
-  { 0x0a002c80, 0x24000001 },
-  { 0x0a002c81, 0x1400ffff },
-  { 0x0a002c82, 0x24000001 },
-  { 0x0a002c83, 0x1400ffff },
-  { 0x0a002c84, 0x24000001 },
-  { 0x0a002c85, 0x1400ffff },
-  { 0x0a002c86, 0x24000001 },
-  { 0x0a002c87, 0x1400ffff },
-  { 0x0a002c88, 0x24000001 },
-  { 0x0a002c89, 0x1400ffff },
-  { 0x0a002c8a, 0x24000001 },
-  { 0x0a002c8b, 0x1400ffff },
-  { 0x0a002c8c, 0x24000001 },
-  { 0x0a002c8d, 0x1400ffff },
-  { 0x0a002c8e, 0x24000001 },
-  { 0x0a002c8f, 0x1400ffff },
-  { 0x0a002c90, 0x24000001 },
-  { 0x0a002c91, 0x1400ffff },
-  { 0x0a002c92, 0x24000001 },
-  { 0x0a002c93, 0x1400ffff },
-  { 0x0a002c94, 0x24000001 },
-  { 0x0a002c95, 0x1400ffff },
-  { 0x0a002c96, 0x24000001 },
-  { 0x0a002c97, 0x1400ffff },
-  { 0x0a002c98, 0x24000001 },
-  { 0x0a002c99, 0x1400ffff },
-  { 0x0a002c9a, 0x24000001 },
-  { 0x0a002c9b, 0x1400ffff },
-  { 0x0a002c9c, 0x24000001 },
-  { 0x0a002c9d, 0x1400ffff },
-  { 0x0a002c9e, 0x24000001 },
-  { 0x0a002c9f, 0x1400ffff },
-  { 0x0a002ca0, 0x24000001 },
-  { 0x0a002ca1, 0x1400ffff },
-  { 0x0a002ca2, 0x24000001 },
-  { 0x0a002ca3, 0x1400ffff },
-  { 0x0a002ca4, 0x24000001 },
-  { 0x0a002ca5, 0x1400ffff },
-  { 0x0a002ca6, 0x24000001 },
-  { 0x0a002ca7, 0x1400ffff },
-  { 0x0a002ca8, 0x24000001 },
-  { 0x0a002ca9, 0x1400ffff },
-  { 0x0a002caa, 0x24000001 },
-  { 0x0a002cab, 0x1400ffff },
-  { 0x0a002cac, 0x24000001 },
-  { 0x0a002cad, 0x1400ffff },
-  { 0x0a002cae, 0x24000001 },
-  { 0x0a002caf, 0x1400ffff },
-  { 0x0a002cb0, 0x24000001 },
-  { 0x0a002cb1, 0x1400ffff },
-  { 0x0a002cb2, 0x24000001 },
-  { 0x0a002cb3, 0x1400ffff },
-  { 0x0a002cb4, 0x24000001 },
-  { 0x0a002cb5, 0x1400ffff },
-  { 0x0a002cb6, 0x24000001 },
-  { 0x0a002cb7, 0x1400ffff },
-  { 0x0a002cb8, 0x24000001 },
-  { 0x0a002cb9, 0x1400ffff },
-  { 0x0a002cba, 0x24000001 },
-  { 0x0a002cbb, 0x1400ffff },
-  { 0x0a002cbc, 0x24000001 },
-  { 0x0a002cbd, 0x1400ffff },
-  { 0x0a002cbe, 0x24000001 },
-  { 0x0a002cbf, 0x1400ffff },
-  { 0x0a002cc0, 0x24000001 },
-  { 0x0a002cc1, 0x1400ffff },
-  { 0x0a002cc2, 0x24000001 },
-  { 0x0a002cc3, 0x1400ffff },
-  { 0x0a002cc4, 0x24000001 },
-  { 0x0a002cc5, 0x1400ffff },
-  { 0x0a002cc6, 0x24000001 },
-  { 0x0a002cc7, 0x1400ffff },
-  { 0x0a002cc8, 0x24000001 },
-  { 0x0a002cc9, 0x1400ffff },
-  { 0x0a002cca, 0x24000001 },
-  { 0x0a002ccb, 0x1400ffff },
-  { 0x0a002ccc, 0x24000001 },
-  { 0x0a002ccd, 0x1400ffff },
-  { 0x0a002cce, 0x24000001 },
-  { 0x0a002ccf, 0x1400ffff },
-  { 0x0a002cd0, 0x24000001 },
-  { 0x0a002cd1, 0x1400ffff },
-  { 0x0a002cd2, 0x24000001 },
-  { 0x0a002cd3, 0x1400ffff },
-  { 0x0a002cd4, 0x24000001 },
-  { 0x0a002cd5, 0x1400ffff },
-  { 0x0a002cd6, 0x24000001 },
-  { 0x0a002cd7, 0x1400ffff },
-  { 0x0a002cd8, 0x24000001 },
-  { 0x0a002cd9, 0x1400ffff },
-  { 0x0a002cda, 0x24000001 },
-  { 0x0a002cdb, 0x1400ffff },
-  { 0x0a002cdc, 0x24000001 },
-  { 0x0a002cdd, 0x1400ffff },
-  { 0x0a002cde, 0x24000001 },
-  { 0x0a002cdf, 0x1400ffff },
-  { 0x0a002ce0, 0x24000001 },
-  { 0x0a002ce1, 0x1400ffff },
-  { 0x0a002ce2, 0x24000001 },
-  { 0x0a002ce3, 0x1400ffff },
-  { 0x0a002ce4, 0x14000000 },
-  { 0x0a802ce5, 0x68000005 },
-  { 0x0a802cf9, 0x54000003 },
-  { 0x0a002cfd, 0x3c000000 },
-  { 0x0a802cfe, 0x54000001 },
-  { 0x10002d00, 0x1400e3a0 },
-  { 0x10002d01, 0x1400e3a0 },
-  { 0x10002d02, 0x1400e3a0 },
-  { 0x10002d03, 0x1400e3a0 },
-  { 0x10002d04, 0x1400e3a0 },
-  { 0x10002d05, 0x1400e3a0 },
-  { 0x10002d06, 0x1400e3a0 },
-  { 0x10002d07, 0x1400e3a0 },
-  { 0x10002d08, 0x1400e3a0 },
-  { 0x10002d09, 0x1400e3a0 },
-  { 0x10002d0a, 0x1400e3a0 },
-  { 0x10002d0b, 0x1400e3a0 },
-  { 0x10002d0c, 0x1400e3a0 },
-  { 0x10002d0d, 0x1400e3a0 },
-  { 0x10002d0e, 0x1400e3a0 },
-  { 0x10002d0f, 0x1400e3a0 },
-  { 0x10002d10, 0x1400e3a0 },
-  { 0x10002d11, 0x1400e3a0 },
-  { 0x10002d12, 0x1400e3a0 },
-  { 0x10002d13, 0x1400e3a0 },
-  { 0x10002d14, 0x1400e3a0 },
-  { 0x10002d15, 0x1400e3a0 },
-  { 0x10002d16, 0x1400e3a0 },
-  { 0x10002d17, 0x1400e3a0 },
-  { 0x10002d18, 0x1400e3a0 },
-  { 0x10002d19, 0x1400e3a0 },
-  { 0x10002d1a, 0x1400e3a0 },
-  { 0x10002d1b, 0x1400e3a0 },
-  { 0x10002d1c, 0x1400e3a0 },
-  { 0x10002d1d, 0x1400e3a0 },
-  { 0x10002d1e, 0x1400e3a0 },
-  { 0x10002d1f, 0x1400e3a0 },
-  { 0x10002d20, 0x1400e3a0 },
-  { 0x10002d21, 0x1400e3a0 },
-  { 0x10002d22, 0x1400e3a0 },
-  { 0x10002d23, 0x1400e3a0 },
-  { 0x10002d24, 0x1400e3a0 },
-  { 0x10002d25, 0x1400e3a0 },
-  { 0x3a802d30, 0x1c000035 },
-  { 0x3a002d6f, 0x18000000 },
-  { 0x0f802d80, 0x1c000016 },
-  { 0x0f802da0, 0x1c000006 },
-  { 0x0f802da8, 0x1c000006 },
-  { 0x0f802db0, 0x1c000006 },
-  { 0x0f802db8, 0x1c000006 },
-  { 0x0f802dc0, 0x1c000006 },
-  { 0x0f802dc8, 0x1c000006 },
-  { 0x0f802dd0, 0x1c000006 },
-  { 0x0f802dd8, 0x1c000006 },
-  { 0x09802e00, 0x54000001 },
-  { 0x09002e02, 0x50000000 },
-  { 0x09002e03, 0x4c000000 },
-  { 0x09002e04, 0x50000000 },
-  { 0x09002e05, 0x4c000000 },
-  { 0x09802e06, 0x54000002 },
-  { 0x09002e09, 0x50000000 },
-  { 0x09002e0a, 0x4c000000 },
-  { 0x09002e0b, 0x54000000 },
-  { 0x09002e0c, 0x50000000 },
-  { 0x09002e0d, 0x4c000000 },
-  { 0x09802e0e, 0x54000008 },
-  { 0x09002e17, 0x44000000 },
-  { 0x09002e1c, 0x50000000 },
-  { 0x09002e1d, 0x4c000000 },
-  { 0x16802e80, 0x68000019 },
-  { 0x16802e9b, 0x68000058 },
-  { 0x16802f00, 0x680000d5 },
-  { 0x09802ff0, 0x6800000b },
-  { 0x09003000, 0x74000000 },
-  { 0x09803001, 0x54000002 },
-  { 0x09003004, 0x68000000 },
-  { 0x16003005, 0x18000000 },
-  { 0x09003006, 0x1c000000 },
-  { 0x16003007, 0x38000000 },
-  { 0x09003008, 0x58000000 },
-  { 0x09003009, 0x48000000 },
-  { 0x0900300a, 0x58000000 },
-  { 0x0900300b, 0x48000000 },
-  { 0x0900300c, 0x58000000 },
-  { 0x0900300d, 0x48000000 },
-  { 0x0900300e, 0x58000000 },
-  { 0x0900300f, 0x48000000 },
-  { 0x09003010, 0x58000000 },
-  { 0x09003011, 0x48000000 },
-  { 0x09803012, 0x68000001 },
-  { 0x09003014, 0x58000000 },
-  { 0x09003015, 0x48000000 },
-  { 0x09003016, 0x58000000 },
-  { 0x09003017, 0x48000000 },
-  { 0x09003018, 0x58000000 },
-  { 0x09003019, 0x48000000 },
-  { 0x0900301a, 0x58000000 },
-  { 0x0900301b, 0x48000000 },
-  { 0x0900301c, 0x44000000 },
-  { 0x0900301d, 0x58000000 },
-  { 0x0980301e, 0x48000001 },
-  { 0x09003020, 0x68000000 },
-  { 0x16803021, 0x38000008 },
-  { 0x1b80302a, 0x30000005 },
-  { 0x09003030, 0x44000000 },
-  { 0x09803031, 0x18000004 },
-  { 0x09803036, 0x68000001 },
-  { 0x16803038, 0x38000002 },
-  { 0x1600303b, 0x18000000 },
-  { 0x0900303c, 0x1c000000 },
-  { 0x0900303d, 0x54000000 },
-  { 0x0980303e, 0x68000001 },
-  { 0x1a803041, 0x1c000055 },
-  { 0x1b803099, 0x30000001 },
-  { 0x0980309b, 0x60000001 },
-  { 0x1a80309d, 0x18000001 },
-  { 0x1a00309f, 0x1c000000 },
-  { 0x090030a0, 0x44000000 },
-  { 0x1d8030a1, 0x1c000059 },
-  { 0x090030fb, 0x54000000 },
-  { 0x098030fc, 0x18000002 },
-  { 0x1d0030ff, 0x1c000000 },
-  { 0x03803105, 0x1c000027 },
-  { 0x17803131, 0x1c00005d },
-  { 0x09803190, 0x68000001 },
-  { 0x09803192, 0x3c000003 },
-  { 0x09803196, 0x68000009 },
-  { 0x038031a0, 0x1c000017 },
-  { 0x098031c0, 0x6800000f },
-  { 0x1d8031f0, 0x1c00000f },
-  { 0x17803200, 0x6800001e },
-  { 0x09803220, 0x3c000009 },
-  { 0x0980322a, 0x68000019 },
-  { 0x09003250, 0x68000000 },
-  { 0x09803251, 0x3c00000e },
-  { 0x17803260, 0x6800001f },
-  { 0x09803280, 0x3c000009 },
-  { 0x0980328a, 0x68000026 },
-  { 0x098032b1, 0x3c00000e },
-  { 0x098032c0, 0x6800003e },
-  { 0x09803300, 0x680000ff },
-  { 0x16803400, 0x1c0019b5 },
-  { 0x09804dc0, 0x6800003f },
-  { 0x16804e00, 0x1c0051bb },
-  { 0x3c80a000, 0x1c000014 },
-  { 0x3c00a015, 0x18000000 },
-  { 0x3c80a016, 0x1c000476 },
-  { 0x3c80a490, 0x68000036 },
-  { 0x0980a700, 0x60000016 },
-  { 0x3080a800, 0x1c000001 },
-  { 0x3000a802, 0x28000000 },
-  { 0x3080a803, 0x1c000002 },
-  { 0x3000a806, 0x30000000 },
-  { 0x3080a807, 0x1c000003 },
-  { 0x3000a80b, 0x30000000 },
-  { 0x3080a80c, 0x1c000016 },
-  { 0x3080a823, 0x28000001 },
-  { 0x3080a825, 0x30000001 },
-  { 0x3000a827, 0x28000000 },
-  { 0x3080a828, 0x68000003 },
-  { 0x1780ac00, 0x1c002ba3 },
-  { 0x0980d800, 0x1000037f },
-  { 0x0980db80, 0x1000007f },
-  { 0x0980dc00, 0x100003ff },
-  { 0x0980e000, 0x0c0018ff },
-  { 0x1680f900, 0x1c00012d },
-  { 0x1680fa30, 0x1c00003a },
-  { 0x1680fa70, 0x1c000069 },
-  { 0x2180fb00, 0x14000006 },
-  { 0x0180fb13, 0x14000004 },
-  { 0x1900fb1d, 0x1c000000 },
-  { 0x1900fb1e, 0x30000000 },
-  { 0x1980fb1f, 0x1c000009 },
-  { 0x1900fb29, 0x64000000 },
-  { 0x1980fb2a, 0x1c00000c },
-  { 0x1980fb38, 0x1c000004 },
-  { 0x1900fb3e, 0x1c000000 },
-  { 0x1980fb40, 0x1c000001 },
-  { 0x1980fb43, 0x1c000001 },
-  { 0x1980fb46, 0x1c00006b },
-  { 0x0080fbd3, 0x1c00016a },
-  { 0x0900fd3e, 0x58000000 },
-  { 0x0900fd3f, 0x48000000 },
-  { 0x0080fd50, 0x1c00003f },
-  { 0x0080fd92, 0x1c000035 },
-  { 0x0080fdf0, 0x1c00000b },
-  { 0x0000fdfc, 0x5c000000 },
-  { 0x0900fdfd, 0x68000000 },
-  { 0x1b80fe00, 0x3000000f },
-  { 0x0980fe10, 0x54000006 },
-  { 0x0900fe17, 0x58000000 },
-  { 0x0900fe18, 0x48000000 },
-  { 0x0900fe19, 0x54000000 },
-  { 0x1b80fe20, 0x30000003 },
-  { 0x0900fe30, 0x54000000 },
-  { 0x0980fe31, 0x44000001 },
-  { 0x0980fe33, 0x40000001 },
-  { 0x0900fe35, 0x58000000 },
-  { 0x0900fe36, 0x48000000 },
-  { 0x0900fe37, 0x58000000 },
-  { 0x0900fe38, 0x48000000 },
-  { 0x0900fe39, 0x58000000 },
-  { 0x0900fe3a, 0x48000000 },
-  { 0x0900fe3b, 0x58000000 },
-  { 0x0900fe3c, 0x48000000 },
-  { 0x0900fe3d, 0x58000000 },
-  { 0x0900fe3e, 0x48000000 },
-  { 0x0900fe3f, 0x58000000 },
-  { 0x0900fe40, 0x48000000 },
-  { 0x0900fe41, 0x58000000 },
-  { 0x0900fe42, 0x48000000 },
-  { 0x0900fe43, 0x58000000 },
-  { 0x0900fe44, 0x48000000 },
-  { 0x0980fe45, 0x54000001 },
-  { 0x0900fe47, 0x58000000 },
-  { 0x0900fe48, 0x48000000 },
-  { 0x0980fe49, 0x54000003 },
-  { 0x0980fe4d, 0x40000002 },
-  { 0x0980fe50, 0x54000002 },
-  { 0x0980fe54, 0x54000003 },
-  { 0x0900fe58, 0x44000000 },
-  { 0x0900fe59, 0x58000000 },
-  { 0x0900fe5a, 0x48000000 },
-  { 0x0900fe5b, 0x58000000 },
-  { 0x0900fe5c, 0x48000000 },
-  { 0x0900fe5d, 0x58000000 },
-  { 0x0900fe5e, 0x48000000 },
-  { 0x0980fe5f, 0x54000002 },
-  { 0x0900fe62, 0x64000000 },
-  { 0x0900fe63, 0x44000000 },
-  { 0x0980fe64, 0x64000002 },
-  { 0x0900fe68, 0x54000000 },
-  { 0x0900fe69, 0x5c000000 },
-  { 0x0980fe6a, 0x54000001 },
-  { 0x0080fe70, 0x1c000004 },
-  { 0x0080fe76, 0x1c000086 },
-  { 0x0900feff, 0x04000000 },
-  { 0x0980ff01, 0x54000002 },
-  { 0x0900ff04, 0x5c000000 },
-  { 0x0980ff05, 0x54000002 },
-  { 0x0900ff08, 0x58000000 },
-  { 0x0900ff09, 0x48000000 },
-  { 0x0900ff0a, 0x54000000 },
-  { 0x0900ff0b, 0x64000000 },
-  { 0x0900ff0c, 0x54000000 },
-  { 0x0900ff0d, 0x44000000 },
-  { 0x0980ff0e, 0x54000001 },
-  { 0x0980ff10, 0x34000009 },
-  { 0x0980ff1a, 0x54000001 },
-  { 0x0980ff1c, 0x64000002 },
-  { 0x0980ff1f, 0x54000001 },
-  { 0x2100ff21, 0x24000020 },
-  { 0x2100ff22, 0x24000020 },
-  { 0x2100ff23, 0x24000020 },
-  { 0x2100ff24, 0x24000020 },
-  { 0x2100ff25, 0x24000020 },
-  { 0x2100ff26, 0x24000020 },
-  { 0x2100ff27, 0x24000020 },
-  { 0x2100ff28, 0x24000020 },
-  { 0x2100ff29, 0x24000020 },
-  { 0x2100ff2a, 0x24000020 },
-  { 0x2100ff2b, 0x24000020 },
-  { 0x2100ff2c, 0x24000020 },
-  { 0x2100ff2d, 0x24000020 },
-  { 0x2100ff2e, 0x24000020 },
-  { 0x2100ff2f, 0x24000020 },
-  { 0x2100ff30, 0x24000020 },
-  { 0x2100ff31, 0x24000020 },
-  { 0x2100ff32, 0x24000020 },
-  { 0x2100ff33, 0x24000020 },
-  { 0x2100ff34, 0x24000020 },
-  { 0x2100ff35, 0x24000020 },
-  { 0x2100ff36, 0x24000020 },
-  { 0x2100ff37, 0x24000020 },
-  { 0x2100ff38, 0x24000020 },
-  { 0x2100ff39, 0x24000020 },
-  { 0x2100ff3a, 0x24000020 },
-  { 0x0900ff3b, 0x58000000 },
-  { 0x0900ff3c, 0x54000000 },
-  { 0x0900ff3d, 0x48000000 },
-  { 0x0900ff3e, 0x60000000 },
-  { 0x0900ff3f, 0x40000000 },
-  { 0x0900ff40, 0x60000000 },
-  { 0x2100ff41, 0x1400ffe0 },
-  { 0x2100ff42, 0x1400ffe0 },
-  { 0x2100ff43, 0x1400ffe0 },
-  { 0x2100ff44, 0x1400ffe0 },
-  { 0x2100ff45, 0x1400ffe0 },
-  { 0x2100ff46, 0x1400ffe0 },
-  { 0x2100ff47, 0x1400ffe0 },
-  { 0x2100ff48, 0x1400ffe0 },
-  { 0x2100ff49, 0x1400ffe0 },
-  { 0x2100ff4a, 0x1400ffe0 },
-  { 0x2100ff4b, 0x1400ffe0 },
-  { 0x2100ff4c, 0x1400ffe0 },
-  { 0x2100ff4d, 0x1400ffe0 },
-  { 0x2100ff4e, 0x1400ffe0 },
-  { 0x2100ff4f, 0x1400ffe0 },
-  { 0x2100ff50, 0x1400ffe0 },
-  { 0x2100ff51, 0x1400ffe0 },
-  { 0x2100ff52, 0x1400ffe0 },
-  { 0x2100ff53, 0x1400ffe0 },
-  { 0x2100ff54, 0x1400ffe0 },
-  { 0x2100ff55, 0x1400ffe0 },
-  { 0x2100ff56, 0x1400ffe0 },
-  { 0x2100ff57, 0x1400ffe0 },
-  { 0x2100ff58, 0x1400ffe0 },
-  { 0x2100ff59, 0x1400ffe0 },
-  { 0x2100ff5a, 0x1400ffe0 },
-  { 0x0900ff5b, 0x58000000 },
-  { 0x0900ff5c, 0x64000000 },
-  { 0x0900ff5d, 0x48000000 },
-  { 0x0900ff5e, 0x64000000 },
-  { 0x0900ff5f, 0x58000000 },
-  { 0x0900ff60, 0x48000000 },
-  { 0x0900ff61, 0x54000000 },
-  { 0x0900ff62, 0x58000000 },
-  { 0x0900ff63, 0x48000000 },
-  { 0x0980ff64, 0x54000001 },
-  { 0x1d80ff66, 0x1c000009 },
-  { 0x0900ff70, 0x18000000 },
-  { 0x1d80ff71, 0x1c00002c },
-  { 0x0980ff9e, 0x18000001 },
-  { 0x1780ffa0, 0x1c00001e },
-  { 0x1780ffc2, 0x1c000005 },
-  { 0x1780ffca, 0x1c000005 },
-  { 0x1780ffd2, 0x1c000005 },
-  { 0x1780ffda, 0x1c000002 },
-  { 0x0980ffe0, 0x5c000001 },
-  { 0x0900ffe2, 0x64000000 },
-  { 0x0900ffe3, 0x60000000 },
-  { 0x0900ffe4, 0x68000000 },
-  { 0x0980ffe5, 0x5c000001 },
-  { 0x0900ffe8, 0x68000000 },
-  { 0x0980ffe9, 0x64000003 },
-  { 0x0980ffed, 0x68000001 },
-  { 0x0980fff9, 0x04000002 },
-  { 0x0980fffc, 0x68000001 },
-  { 0x23810000, 0x1c00000b },
-  { 0x2381000d, 0x1c000019 },
-  { 0x23810028, 0x1c000012 },
-  { 0x2381003c, 0x1c000001 },
-  { 0x2381003f, 0x1c00000e },
-  { 0x23810050, 0x1c00000d },
-  { 0x23810080, 0x1c00007a },
-  { 0x09810100, 0x54000001 },
-  { 0x09010102, 0x68000000 },
-  { 0x09810107, 0x3c00002c },
-  { 0x09810137, 0x68000008 },
-  { 0x13810140, 0x38000034 },
-  { 0x13810175, 0x3c000003 },
-  { 0x13810179, 0x68000010 },
-  { 0x1301018a, 0x3c000000 },
-  { 0x29810300, 0x1c00001e },
-  { 0x29810320, 0x3c000003 },
-  { 0x12810330, 0x1c000019 },
-  { 0x1201034a, 0x38000000 },
-  { 0x3b810380, 0x1c00001d },
-  { 0x3b01039f, 0x54000000 },
-  { 0x2a8103a0, 0x1c000023 },
-  { 0x2a8103c8, 0x1c000007 },
-  { 0x2a0103d0, 0x68000000 },
-  { 0x2a8103d1, 0x38000004 },
-  { 0x0d010400, 0x24000028 },
-  { 0x0d010401, 0x24000028 },
-  { 0x0d010402, 0x24000028 },
-  { 0x0d010403, 0x24000028 },
-  { 0x0d010404, 0x24000028 },
-  { 0x0d010405, 0x24000028 },
-  { 0x0d010406, 0x24000028 },
-  { 0x0d010407, 0x24000028 },
-  { 0x0d010408, 0x24000028 },
-  { 0x0d010409, 0x24000028 },
-  { 0x0d01040a, 0x24000028 },
-  { 0x0d01040b, 0x24000028 },
-  { 0x0d01040c, 0x24000028 },
-  { 0x0d01040d, 0x24000028 },
-  { 0x0d01040e, 0x24000028 },
-  { 0x0d01040f, 0x24000028 },
-  { 0x0d010410, 0x24000028 },
-  { 0x0d010411, 0x24000028 },
-  { 0x0d010412, 0x24000028 },
-  { 0x0d010413, 0x24000028 },
-  { 0x0d010414, 0x24000028 },
-  { 0x0d010415, 0x24000028 },
-  { 0x0d010416, 0x24000028 },
-  { 0x0d010417, 0x24000028 },
-  { 0x0d010418, 0x24000028 },
-  { 0x0d010419, 0x24000028 },
-  { 0x0d01041a, 0x24000028 },
-  { 0x0d01041b, 0x24000028 },
-  { 0x0d01041c, 0x24000028 },
-  { 0x0d01041d, 0x24000028 },
-  { 0x0d01041e, 0x24000028 },
-  { 0x0d01041f, 0x24000028 },
-  { 0x0d010420, 0x24000028 },
-  { 0x0d010421, 0x24000028 },
-  { 0x0d010422, 0x24000028 },
-  { 0x0d010423, 0x24000028 },
-  { 0x0d010424, 0x24000028 },
-  { 0x0d010425, 0x24000028 },
-  { 0x0d010426, 0x24000028 },
-  { 0x0d010427, 0x24000028 },
-  { 0x0d010428, 0x1400ffd8 },
-  { 0x0d010429, 0x1400ffd8 },
-  { 0x0d01042a, 0x1400ffd8 },
-  { 0x0d01042b, 0x1400ffd8 },
-  { 0x0d01042c, 0x1400ffd8 },
-  { 0x0d01042d, 0x1400ffd8 },
-  { 0x0d01042e, 0x1400ffd8 },
-  { 0x0d01042f, 0x1400ffd8 },
-  { 0x0d010430, 0x1400ffd8 },
-  { 0x0d010431, 0x1400ffd8 },
-  { 0x0d010432, 0x1400ffd8 },
-  { 0x0d010433, 0x1400ffd8 },
-  { 0x0d010434, 0x1400ffd8 },
-  { 0x0d010435, 0x1400ffd8 },
-  { 0x0d010436, 0x1400ffd8 },
-  { 0x0d010437, 0x1400ffd8 },
-  { 0x0d010438, 0x1400ffd8 },
-  { 0x0d010439, 0x1400ffd8 },
-  { 0x0d01043a, 0x1400ffd8 },
-  { 0x0d01043b, 0x1400ffd8 },
-  { 0x0d01043c, 0x1400ffd8 },
-  { 0x0d01043d, 0x1400ffd8 },
-  { 0x0d01043e, 0x1400ffd8 },
-  { 0x0d01043f, 0x1400ffd8 },
-  { 0x0d010440, 0x1400ffd8 },
-  { 0x0d010441, 0x1400ffd8 },
-  { 0x0d010442, 0x1400ffd8 },
-  { 0x0d010443, 0x1400ffd8 },
-  { 0x0d010444, 0x1400ffd8 },
-  { 0x0d010445, 0x1400ffd8 },
-  { 0x0d010446, 0x1400ffd8 },
-  { 0x0d010447, 0x1400ffd8 },
-  { 0x0d010448, 0x1400ffd8 },
-  { 0x0d010449, 0x1400ffd8 },
-  { 0x0d01044a, 0x1400ffd8 },
-  { 0x0d01044b, 0x1400ffd8 },
-  { 0x0d01044c, 0x1400ffd8 },
-  { 0x0d01044d, 0x1400ffd8 },
-  { 0x0d01044e, 0x1400ffd8 },
-  { 0x0d01044f, 0x1400ffd8 },
-  { 0x2e810450, 0x1c00004d },
-  { 0x2c8104a0, 0x34000009 },
-  { 0x0b810800, 0x1c000005 },
-  { 0x0b010808, 0x1c000000 },
-  { 0x0b81080a, 0x1c00002b },
-  { 0x0b810837, 0x1c000001 },
-  { 0x0b01083c, 0x1c000000 },
-  { 0x0b01083f, 0x1c000000 },
-  { 0x1e010a00, 0x1c000000 },
-  { 0x1e810a01, 0x30000002 },
-  { 0x1e810a05, 0x30000001 },
-  { 0x1e810a0c, 0x30000003 },
-  { 0x1e810a10, 0x1c000003 },
-  { 0x1e810a15, 0x1c000002 },
-  { 0x1e810a19, 0x1c00001a },
-  { 0x1e810a38, 0x30000002 },
-  { 0x1e010a3f, 0x30000000 },
-  { 0x1e810a40, 0x3c000007 },
-  { 0x1e810a50, 0x54000008 },
-  { 0x0981d000, 0x680000f5 },
-  { 0x0981d100, 0x68000026 },
-  { 0x0981d12a, 0x6800003a },
-  { 0x0981d165, 0x28000001 },
-  { 0x1b81d167, 0x30000002 },
-  { 0x0981d16a, 0x68000002 },
-  { 0x0981d16d, 0x28000005 },
-  { 0x0981d173, 0x04000007 },
-  { 0x1b81d17b, 0x30000007 },
-  { 0x0981d183, 0x68000001 },
-  { 0x1b81d185, 0x30000006 },
-  { 0x0981d18c, 0x6800001d },
-  { 0x1b81d1aa, 0x30000003 },
-  { 0x0981d1ae, 0x6800002f },
-  { 0x1381d200, 0x68000041 },
-  { 0x1381d242, 0x30000002 },
-  { 0x1301d245, 0x68000000 },
-  { 0x0981d300, 0x68000056 },
-  { 0x0981d400, 0x24000019 },
-  { 0x0981d41a, 0x14000019 },
-  { 0x0981d434, 0x24000019 },
-  { 0x0981d44e, 0x14000006 },
-  { 0x0981d456, 0x14000011 },
-  { 0x0981d468, 0x24000019 },
-  { 0x0981d482, 0x14000019 },
-  { 0x0901d49c, 0x24000000 },
-  { 0x0981d49e, 0x24000001 },
-  { 0x0901d4a2, 0x24000000 },
-  { 0x0981d4a5, 0x24000001 },
-  { 0x0981d4a9, 0x24000003 },
-  { 0x0981d4ae, 0x24000007 },
-  { 0x0981d4b6, 0x14000003 },
-  { 0x0901d4bb, 0x14000000 },
-  { 0x0981d4bd, 0x14000006 },
-  { 0x0981d4c5, 0x1400000a },
-  { 0x0981d4d0, 0x24000019 },
-  { 0x0981d4ea, 0x14000019 },
-  { 0x0981d504, 0x24000001 },
-  { 0x0981d507, 0x24000003 },
-  { 0x0981d50d, 0x24000007 },
-  { 0x0981d516, 0x24000006 },
-  { 0x0981d51e, 0x14000019 },
-  { 0x0981d538, 0x24000001 },
-  { 0x0981d53b, 0x24000003 },
-  { 0x0981d540, 0x24000004 },
-  { 0x0901d546, 0x24000000 },
-  { 0x0981d54a, 0x24000006 },
-  { 0x0981d552, 0x14000019 },
-  { 0x0981d56c, 0x24000019 },
-  { 0x0981d586, 0x14000019 },
-  { 0x0981d5a0, 0x24000019 },
-  { 0x0981d5ba, 0x14000019 },
-  { 0x0981d5d4, 0x24000019 },
-  { 0x0981d5ee, 0x14000019 },
-  { 0x0981d608, 0x24000019 },
-  { 0x0981d622, 0x14000019 },
-  { 0x0981d63c, 0x24000019 },
-  { 0x0981d656, 0x14000019 },
-  { 0x0981d670, 0x24000019 },
-  { 0x0981d68a, 0x1400001b },
-  { 0x0981d6a8, 0x24000018 },
-  { 0x0901d6c1, 0x64000000 },
-  { 0x0981d6c2, 0x14000018 },
-  { 0x0901d6db, 0x64000000 },
-  { 0x0981d6dc, 0x14000005 },
-  { 0x0981d6e2, 0x24000018 },
-  { 0x0901d6fb, 0x64000000 },
-  { 0x0981d6fc, 0x14000018 },
-  { 0x0901d715, 0x64000000 },
-  { 0x0981d716, 0x14000005 },
-  { 0x0981d71c, 0x24000018 },
-  { 0x0901d735, 0x64000000 },
-  { 0x0981d736, 0x14000018 },
-  { 0x0901d74f, 0x64000000 },
-  { 0x0981d750, 0x14000005 },
-  { 0x0981d756, 0x24000018 },
-  { 0x0901d76f, 0x64000000 },
-  { 0x0981d770, 0x14000018 },
-  { 0x0901d789, 0x64000000 },
-  { 0x0981d78a, 0x14000005 },
-  { 0x0981d790, 0x24000018 },
-  { 0x0901d7a9, 0x64000000 },
-  { 0x0981d7aa, 0x14000018 },
-  { 0x0901d7c3, 0x64000000 },
-  { 0x0981d7c4, 0x14000005 },
-  { 0x0981d7ce, 0x34000031 },
-  { 0x16820000, 0x1c00a6d6 },
-  { 0x1682f800, 0x1c00021d },
-  { 0x090e0001, 0x04000000 },
-  { 0x098e0020, 0x0400005f },
-  { 0x1b8e0100, 0x300000ef },
-  { 0x098f0000, 0x0c00fffd },
-  { 0x09900000, 0x0c00fffd },
-};
index f2d04fca91b32a565dd1f141f3de1a51a5a659d0..1ba5ec604376f9797c523bee1798da065f75806d 100644 (file)
 #define CallIdentifier_h
 
 #include <runtime/UString.h>
-#include "FastAllocBase.h"
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
 
 namespace JSC {
 
-    struct CallIdentifier : public FastAllocBase {
+    struct CallIdentifier {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         UString m_name;
         UString m_url;
         unsigned m_lineNumber;
@@ -56,11 +59,11 @@ namespace JSC {
             static unsigned hash(const CallIdentifier& key)
             {
                 unsigned hashCodes[3] = {
-                    key.m_name.rep()->hash(),
-                    key.m_url.rep()->hash(),
+                    key.m_name.impl()->hash(),
+                    key.m_url.impl()->hash(),
                     key.m_lineNumber
                 };
-                return UString::Rep::computeHash(reinterpret_cast<char*>(hashCodes), sizeof(hashCodes));
+                return StringHasher::hashMemory<sizeof(hashCodes)>(hashCodes);
             }
 
             static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; }
@@ -71,7 +74,7 @@ namespace JSC {
 
 #ifndef NDEBUG
         operator const char*() const { return c_str(); }
-        const char* c_str() const { return m_name.UTF8String().data(); }
+        const char* c_str() const { return m_name.utf8().data(); }
 #endif
     };
 
index 126e6f686e54bf4a75ea99df2546211d7ca0b10b..1a84518c1bbb9538c7ffd8d7e5474119eb95b3b3 100644 (file)
@@ -42,7 +42,7 @@ Profile::Profile(const UString& title, unsigned uid)
 {
     // FIXME: When multi-threading is supported this will be a vector and calls
     // into the profiler will need to know which thread it is executing on.
-    m_head = ProfileNode::create(CallIdentifier("Thread_1", UString(), 0), 0, 0);
+    m_head = ProfileNode::create(0, CallIdentifier("Thread_1", UString(), 0), 0, 0);
 }
 
 Profile::~Profile()
@@ -106,7 +106,7 @@ void Profile::debugPrintData() const
     m_head->debugPrintData(0);
 }
 
-typedef pair<UString::Rep*, unsigned> NameCountPair;
+typedef pair<StringImpl*, unsigned> NameCountPair;
 
 static inline bool functionNameCountPairComparator(const NameCountPair& a, const NameCountPair& b)
 {
@@ -127,7 +127,7 @@ void Profile::debugPrintDataSampleStyle() const
 
     std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator);
     for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it)
-        printf("        %-12d%s\n", (*it).second, UString((*it).first).UTF8String().data());
+        printf("        %-12d%s\n", (*it).second, UString((*it).first).utf8().data());
 
     printf("\nSort by top of stack, same collapsed (when >= 5):\n");
 }
index bdfa27b22c967d73417aef214288d5fa85e501a5..5db38bca8d56a5ef01d28a5f942b0fd93027fbe2 100644 (file)
@@ -40,19 +40,19 @@ namespace JSC {
 
 static const char* NonJSExecution = "(idle)";
 
-PassRefPtr<ProfileGenerator> ProfileGenerator::create(const UString& title, ExecState* originatingExec, unsigned uid)
+PassRefPtr<ProfileGenerator> ProfileGenerator::create(ExecState* exec, const UString& title, unsigned uid)
 {
-    return adoptRef(new ProfileGenerator(title, originatingExec, uid));
+    return adoptRef(new ProfileGenerator(exec, title, uid));
 }
 
-ProfileGenerator::ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid)
-    : m_originatingGlobalExec(originatingExec ? originatingExec->lexicalGlobalObject()->globalExec() : 0)
-    , m_profileGroup(originatingExec ? originatingExec->lexicalGlobalObject()->profileGroup() : 0)
+ProfileGenerator::ProfileGenerator(ExecState* exec, const UString& title, unsigned uid)
+    : m_origin(exec ? exec->lexicalGlobalObject() : 0)
+    , m_profileGroup(exec ? exec->lexicalGlobalObject()->profileGroup() : 0)
 {
     m_profile = Profile::create(title, uid);
     m_currentNode = m_head = m_profile->head();
-    if (originatingExec)
-        addParentForConsoleStart(originatingExec);
+    if (exec)
+        addParentForConsoleStart(exec);
 }
 
 void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
@@ -63,7 +63,7 @@ void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
     JSValue function;
 
     exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
-    m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
+    m_currentNode = ProfileNode::create(exec, Profiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get());
     m_head->insertNode(m_currentNode.get());
 }
 
@@ -72,35 +72,35 @@ const UString& ProfileGenerator::title() const
     return m_profile->title();
 }
 
-void ProfileGenerator::willExecute(const CallIdentifier& callIdentifier)
+void ProfileGenerator::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
 {
     if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) {
-        CString name = callIdentifier.m_name.UTF8String();
-        CString url = callIdentifier.m_url.UTF8String();
+        CString name = callIdentifier.m_name.utf8();
+        CString url = callIdentifier.m_url.utf8();
         JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber);
     }
 
-    if (!m_originatingGlobalExec)
+    if (!m_origin)
         return;
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
-    m_currentNode = m_currentNode->willExecute(callIdentifier);
+    ASSERT(m_currentNode);
+    m_currentNode = m_currentNode->willExecute(callerCallFrame, callIdentifier);
 }
 
-void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier)
+void ProfileGenerator::didExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
 {
     if (JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED()) {
-        CString name = callIdentifier.m_name.UTF8String();
-        CString url = callIdentifier.m_url.UTF8String();
+        CString name = callIdentifier.m_name.utf8();
+        CString url = callIdentifier.m_url.utf8();
         JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber);
     }
 
-    if (!m_originatingGlobalExec)
+    if (!m_origin)
         return;
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
+    ASSERT(m_currentNode);
     if (m_currentNode->callIdentifier() != callIdentifier) {
-        RefPtr<ProfileNode> returningNode = ProfileNode::create(callIdentifier, m_head.get(), m_currentNode.get());
+        RefPtr<ProfileNode> returningNode = ProfileNode::create(callerCallFrame, callIdentifier, m_head.get(), m_currentNode.get());
         returningNode->setStartTime(m_currentNode->startTime());
         returningNode->didExecute();
         m_currentNode->insertNode(returningNode.release());
@@ -110,6 +110,17 @@ void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier)
     m_currentNode = m_currentNode->didExecute();
 }
 
+void ProfileGenerator::exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&)
+{
+    // If the current node was called by the handler (==) or any
+    // more nested function (>) the we have exited early from it.
+    ASSERT(m_currentNode);
+    while (m_currentNode->callerCallFrame() >= handlerCallFrame) {
+        didExecute(m_currentNode->callerCallFrame(), m_currentNode->callIdentifier());
+        ASSERT(m_currentNode);
+    }
+}
+
 void ProfileGenerator::stopProfiling()
 {
     m_profile->forEach(&ProfileNode::stopProfiling);
@@ -117,14 +128,14 @@ void ProfileGenerator::stopProfiling()
     removeProfileStart();
     removeProfileEnd();
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
+    ASSERT(m_currentNode);
 
     // Set the current node to the parent, because we are in a call that
     // will not get didExecute call.
     m_currentNode = m_currentNode->parent();
 
    if (double headSelfTime = m_head->selfTime()) {
-        RefPtr<ProfileNode> idleNode = ProfileNode::create(CallIdentifier(NonJSExecution, UString(), 0), m_head.get(), m_head.get());
+        RefPtr<ProfileNode> idleNode = ProfileNode::create(0, CallIdentifier(NonJSExecution, UString(), 0), m_head.get(), m_head.get());
 
         idleNode->setTotalTime(headSelfTime);
         idleNode->setSelfTime(headSelfTime);
index 82149b33d61675d410ddb0ada5d1c142465fd907..8c8b81731535619d14233dff0fdb7d1b22880adf 100644 (file)
@@ -34,6 +34,7 @@
 namespace JSC {
 
     class ExecState;
+    class JSGlobalObject;
     class Profile;
     class ProfileNode;
     class UString;
@@ -41,32 +42,34 @@ namespace JSC {
 
     class ProfileGenerator : public RefCounted<ProfileGenerator>  {
     public:
-        static PassRefPtr<ProfileGenerator> create(const UString& title, ExecState* originatingExec, unsigned uid);
+        static PassRefPtr<ProfileGenerator> create(ExecState*, const UString& title, unsigned uid);
 
         // Members
         const UString& title() const;
         PassRefPtr<Profile> profile() const { return m_profile; }
-        ExecState* originatingGlobalExec() const { return m_originatingGlobalExec; }
+        JSGlobalObject* origin() const { return m_origin; }
         unsigned profileGroup() const { return m_profileGroup; }
 
         // Collecting
-        void willExecute(const CallIdentifier&);
-        void didExecute(const CallIdentifier&);
+        void willExecute(ExecState* callerCallFrame, const CallIdentifier&);
+        void didExecute(ExecState* callerCallFrame, const CallIdentifier&);
+
+        void exceptionUnwind(ExecState* handlerCallFrame, const CallIdentifier&);
 
         // Stopping Profiling
         void stopProfiling();
 
-        typedef void (ProfileGenerator::*ProfileFunction)(const CallIdentifier& callIdentifier);
+        typedef void (ProfileGenerator::*ProfileFunction)(ExecState* callerOrHandlerCallFrame, const CallIdentifier& callIdentifier);
 
     private:
-        ProfileGenerator(const UString& title, ExecState* originatingExec, unsigned uid);
+        ProfileGenerator(ExecState*, const UString& title, unsigned uid);
         void addParentForConsoleStart(ExecState*);
 
         void removeProfileStart();
         void removeProfileEnd();
 
         RefPtr<Profile> m_profile;
-        ExecState* m_originatingGlobalExec;
+        JSGlobalObject* m_origin;
         unsigned m_profileGroup;
         RefPtr<ProfileNode> m_head;
         RefPtr<ProfileNode> m_currentNode;
index f60c72e48649bf344b1ca2ca62247662053853d1..8f20bbeff8a60b512c506fd4bf9e240e17fa062b 100644 (file)
@@ -45,7 +45,7 @@ namespace JSC {
 static double getCount()
 {
 #if OS(WINDOWS)
-    static LARGE_INTEGER frequency = {0};
+    static LARGE_INTEGER frequency;
     if (!frequency.QuadPart)
         QueryPerformanceFrequency(&frequency);
     LARGE_INTEGER counter;
@@ -56,8 +56,9 @@ static double getCount()
 #endif
 }
 
-ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
-    : m_callIdentifier(callIdentifier)
+ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+    : m_callerCallFrame(callerCallFrame)
+    , m_callIdentifier(callIdentifier)
     , m_head(headNode)
     , m_parent(parentNode)
     , m_nextSibling(0)
@@ -72,8 +73,9 @@ ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* head
     startTimer();
 }
 
-ProfileNode::ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy)
-    : m_callIdentifier(nodeToCopy->callIdentifier())
+ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
+    : m_callerCallFrame(callerCallFrame)
+    , m_callIdentifier(nodeToCopy->callIdentifier())
     , m_head(headNode)
     , m_parent(nodeToCopy->parent())
     , m_nextSibling(0)
@@ -87,7 +89,7 @@ ProfileNode::ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy)
 {
 }
 
-ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
+ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
 {
     for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
         if ((*currentChild)->callIdentifier() == callIdentifier) {
@@ -96,7 +98,7 @@ ProfileNode* ProfileNode::willExecute(const CallIdentifier& callIdentifier)
         }
     }
 
-    RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
+    RefPtr<ProfileNode> newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
     if (m_children.size())
         m_children.last()->setNextSibling(newChild.get());
     m_children.append(newChild.release());
@@ -294,11 +296,11 @@ void ProfileNode::debugPrintData(int indentLevel) const
         printf("  ");
 
     printf("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
-        functionName().UTF8String().data(), 
+        functionName().utf8().data(), 
         m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
         m_visibleSelfTime, m_visibleTotalTime, 
         (m_visible ? "True" : "False"),
-        m_nextSibling ? m_nextSibling->functionName().UTF8String().data() : "");
+        m_nextSibling ? m_nextSibling->functionName().utf8().data() : "");
 
     ++indentLevel;
 
@@ -313,13 +315,13 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
     printf("    ");
 
     // Print function names
-    const char* name = functionName().UTF8String().data();
+    const char* name = functionName().utf8().data();
     double sampleCount = m_actualTotalTime * 1000;
     if (indentLevel) {
         for (int i = 0; i < indentLevel; ++i)
             printf("  ");
 
-         countedFunctions.add(functionName().rep());
+         countedFunctions.add(functionName().impl());
 
         printf("%.0f %s\n", sampleCount ? sampleCount : 1, name);
     } else
@@ -339,7 +341,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
         while (indentLevel--)
             printf("  ");
 
-        printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().UTF8String().data());
+        printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
     }
 
     return m_actualTotalTime;
index 2b5a93602f4318623e0f12efd7aeb7363e87b8b6..ffe7b6f9d0e34caf3d3cf282422f342b5c7d1e91 100644 (file)
 #define ProfileNode_h
 
 #include "CallIdentifier.h"
-#include <wtf/Vector.h>
+#include <wtf/HashCountedSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
 
 namespace JSC {
 
+    class ExecState;
     class ProfileNode;
 
     typedef Vector<RefPtr<ProfileNode> >::const_iterator StackIterator;
-    typedef HashCountedSet<UString::Rep*> FunctionCallHashCount;
+    typedef HashCountedSet<StringImpl*> FunctionCallHashCount;
 
     class ProfileNode : public RefCounted<ProfileNode> {
     public:
-        static PassRefPtr<ProfileNode> create(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
+        static PassRefPtr<ProfileNode> create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
         {
-            return adoptRef(new ProfileNode(callIdentifier, headNode, parentNode));
+            return adoptRef(new ProfileNode(callerCallFrame, callIdentifier, headNode, parentNode));
         }
-        static PassRefPtr<ProfileNode> create(ProfileNode* headNode, ProfileNode* node)
+        static PassRefPtr<ProfileNode> create(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* node)
         {
-            return adoptRef(new ProfileNode(headNode, node));
+            return adoptRef(new ProfileNode(callerCallFrame, headNode, node));
         }
 
         bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); }
 
-        ProfileNode* willExecute(const CallIdentifier&);
+        ProfileNode* willExecute(ExecState* callerCallFrame, const CallIdentifier&);
         ProfileNode* didExecute();
 
         void stopProfiling();
 
         // CallIdentifier members
+        ExecState* callerCallFrame() const { return m_callerCallFrame; }
         const CallIdentifier& callIdentifier() const { return m_callIdentifier; }
         const UString& functionName() const { return m_callIdentifier.m_name; }
         const UString& url() const { return m_callIdentifier.m_url; }
@@ -127,8 +130,8 @@ namespace JSC {
 #endif
 
     private:
-        ProfileNode(const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
-        ProfileNode(ProfileNode* headNode, ProfileNode* nodeToCopy);
+        ProfileNode(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode);
+        ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy);
 
         void startTimer();
         void resetChildrensSiblings();
@@ -146,6 +149,7 @@ namespace JSC {
         static inline bool functionNameDescendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() > b->functionName(); }
         static inline bool functionNameAscendingComparator(const RefPtr<ProfileNode>& a, const RefPtr<ProfileNode>& b) { return a->functionName() < b->functionName(); }
 
+        ExecState* m_callerCallFrame;
         CallIdentifier m_callIdentifier;
         ProfileNode* m_head;
         ProfileNode* m_parent;
index fe8727a4bf3b9f29029c5c156fd6b5e95d144db6..bcaaaacbf217b08425f4327ca8bd37bf23a14a26 100644 (file)
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
 #include "CodeBlock.h"
+#include "InternalFunction.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Nodes.h"
 #include "Profile.h"
 #include "ProfileGenerator.h"
 #include "ProfileNode.h"
+#include "UStringConcatenate.h"
 #include <stdio.h>
 
 namespace JSC {
@@ -64,25 +66,25 @@ void Profiler::startProfiling(ExecState* exec, const UString& title)
 
     // Check if we currently have a Profile for this global ExecState and title.
     // If so return early and don't create a new Profile.
-    ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0;
+    JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0;
 
     for (size_t i = 0; i < m_currentProfiles.size(); ++i) {
         ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
-        if (profileGenerator->originatingGlobalExec() == globalExec && profileGenerator->title() == title)
+        if (profileGenerator->origin() == origin && profileGenerator->title() == title)
             return;
     }
 
     s_sharedEnabledProfilerReference = this;
-    RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(title, exec, ++ProfilesUID);
+    RefPtr<ProfileGenerator> profileGenerator = ProfileGenerator::create(exec, title, ++ProfilesUID);
     m_currentProfiles.append(profileGenerator);
 }
 
 PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& title)
 {
-    ExecState* globalExec = exec ? exec->lexicalGlobalObject()->globalExec() : 0;
+    JSGlobalObject* origin = exec ? exec->lexicalGlobalObject() : 0;
     for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
         ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
-        if (profileGenerator->originatingGlobalExec() == globalExec && (title.isNull() || profileGenerator->title() == title)) {
+        if (profileGenerator->origin() == origin && (title.isNull() || profileGenerator->title() == title)) {
             profileGenerator->stopProfiling();
             RefPtr<Profile> returnProfile = profileGenerator->profile();
 
@@ -97,42 +99,62 @@ PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& titl
     return 0;
 }
 
-static inline void dispatchFunctionToProfiles(const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
+void Profiler::stopProfiling(JSGlobalObject* origin)
+{
+    for (ptrdiff_t i = m_currentProfiles.size() - 1; i >= 0; --i) {
+        ProfileGenerator* profileGenerator = m_currentProfiles[i].get();
+        if (profileGenerator->origin() == origin) {
+            profileGenerator->stopProfiling();
+            m_currentProfiles.remove(i);
+            if (!m_currentProfiles.size())
+                s_sharedEnabledProfilerReference = 0;
+        }
+    }
+}
+
+static inline void dispatchFunctionToProfiles(ExecState* callerOrHandlerCallFrame, const Vector<RefPtr<ProfileGenerator> >& profiles, ProfileGenerator::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentProfileTargetGroup)
 {
     for (size_t i = 0; i < profiles.size(); ++i) {
-        if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->originatingGlobalExec())
-            (profiles[i].get()->*function)(callIdentifier);
+        if (profiles[i]->profileGroup() == currentProfileTargetGroup || !profiles[i]->origin())
+            (profiles[i].get()->*function)(callerOrHandlerCallFrame, callIdentifier);
     }
 }
 
-void Profiler::willExecute(ExecState* exec, JSValue function)
+void Profiler::willExecute(ExecState* callerCallFrame, JSValue function)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+void Profiler::willExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    CallIdentifier callIdentifier = createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber);
+    CallIdentifier callIdentifier = createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber);
+
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, callerCallFrame->lexicalGlobalObject()->profileGroup());
+}
+
+void Profiler::didExecute(ExecState* callerCallFrame, JSValue function)
+{
+    ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, function, "", 0), callerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::didExecute(ExecState* exec, JSValue function)
+void Profiler::didExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(callerCallFrame, m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(callerCallFrame, JSValue(), sourceURL, startingLineNumber), callerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
-void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber)
+void Profiler::exceptionUnwind(ExecState* handlerCallFrame)
 {
     ASSERT(!m_currentProfiles.isEmpty());
 
-    dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup());
+    dispatchFunctionToProfiles(handlerCallFrame, m_currentProfiles, &ProfileGenerator::exceptionUnwind, createCallIdentifier(handlerCallFrame, JSValue(), "", 0), handlerCallFrame->lexicalGlobalObject()->profileGroup());
 }
 
 CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber)
@@ -141,14 +163,16 @@ CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionV
         return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber);
     if (!functionValue.isObject())
         return CallIdentifier("(unknown)", defaultSourceURL, defaultLineNumber);
-    if (asObject(functionValue)->inherits(&JSFunction::info)) {
+    if (asObject(functionValue)->inherits(&JSFunction::s_info)) {
         JSFunction* function = asFunction(functionValue);
         if (!function->executable()->isHostFunction())
             return createCallIdentifierFromFunctionImp(exec, function);
     }
-    if (asObject(functionValue)->inherits(&InternalFunction::info))
+    if (asObject(functionValue)->inherits(&JSFunction::s_info))
+        return CallIdentifier(static_cast<JSFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
+    if (asObject(functionValue)->inherits(&InternalFunction::s_info))
         return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber);
-    return CallIdentifier(makeString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
+    return CallIdentifier(makeUString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber);
 }
 
 CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)
index 4b8b4a019f0d0c0570c74e3b4b07b73e429f0a4b..86366c1c4f9198d3df116229e55c0c9935fdea1d 100644 (file)
@@ -38,13 +38,15 @@ namespace JSC {
 
     class ExecState;
     class JSGlobalData;
+    class JSGlobalObject;
     class JSObject;
     class JSValue;
     class ProfileGenerator;
     class UString;
     struct CallIdentifier;    
 
-    class Profiler : public FastAllocBase {
+    class Profiler {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         static Profiler** enabledProfilerReference()
         {
@@ -56,11 +58,14 @@ namespace JSC {
 
         void startProfiling(ExecState*, const UString& title);
         PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
+        void stopProfiling(JSGlobalObject*);
 
-        void willExecute(ExecState*, JSValue function);
-        void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
-        void didExecute(ExecState*, JSValue function);
-        void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber);
+        void willExecute(ExecState* callerCallFrame, JSValue function);
+        void willExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber);
+        void didExecute(ExecState* callerCallFrame, JSValue function);
+        void didExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber);
+
+        void exceptionUnwind(ExecState* handlerCallFrame);
 
         const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; };
 
index 29f075c421d2887f7c9c3b1e4eb6b1c7fc9daf9d..a2c5d9ec789ea5ca9518f6faa92ae7800d76e132 100644 (file)
@@ -30,7 +30,7 @@
 #import "JSRetainPtr.h"
 #import <Foundation/Foundation.h>
 
-#if PLATFORM(IPHONE_SIMULATOR)
+#if PLATFORM(IOS_SIMULATOR)
 #import <Foundation/NSDistributedNotificationCenter.h>
 #endif
 
@@ -65,7 +65,7 @@
     if ([defaults boolForKey:@"EnableJSProfiling"])
         [self startProfiling];
 
-#if PLATFORM(IPHONE_SIMULATOR)
+#if PLATFORM(IOS_SIMULATOR)
     // FIXME: <rdar://problem/6546135>
     // The catch-all notifications
     [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(startProfiling) name:@"ProfilerServerStartNotification" object:nil];
@@ -76,7 +76,7 @@
     NSProcessInfo *processInfo = [NSProcessInfo processInfo];
     _serverName = [[NSString alloc] initWithFormat:@"ProfilerServer-%d", [processInfo processIdentifier]];
 
-#if PLATFORM(IPHONE_SIMULATOR)
+#if PLATFORM(IOS_SIMULATOR)
     // FIXME: <rdar://problem/6546135>
     [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(startProfiling) name:[_serverName stringByAppendingString:@"-Start"] object:nil];
     [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(stopProfiling) name:[_serverName stringByAppendingString:@"-Stop"] object:nil];
diff --git a/qt/ChangeLog b/qt/ChangeLog
new file mode 100644 (file)
index 0000000..22484b7
--- /dev/null
@@ -0,0 +1,467 @@
+2011-03-01  Andras Becsi  <abecsi@webkit.org>
+
+        Reviewed by Csaba Osztrogonác.
+
+        [Qt] Clean up the project files and move common options to WebKit.pri.
+
+        * api/QtScript.pro: Deduplicate options.
+
+2011-02-24  Andras Becsi  <abecsi@webkit.org>
+
+        Reviewed by Laszlo Gombos.
+
+        [Qt] MinGW build fails to link
+        https://bugs.webkit.org/show_bug.cgi?id=55050
+
+        Prepend the libraries of subcomponents instead of appending them
+        to fix the library order according to the dependency of the libraries
+
+        * api/QtScript.pro:
+
+2010-09-29  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
+
+        Reviewed by Andreas Kling.
+
+        [Qt] QScriptEngine should have an API for creating Date objects
+        https://bugs.webkit.org/show_bug.cgi?id=41667
+
+        Implement newDate(), isDate() and toDateTime() functions. Use the
+        QDateTime::{to,set}MSecsSinceEpoch() functions to do the
+        calculations.
+
+        * api/qscriptengine.cpp:
+        (QScriptEngine::newDate):
+        * api/qscriptengine.h:
+        * api/qscriptengine_p.cpp:
+        (QScriptEnginePrivate::newDate):
+        * api/qscriptengine_p.h:
+        (QScriptEnginePrivate::isDate):
+
+        * api/qscriptoriginalglobalobject_p.h:
+        (QScriptOriginalGlobalObject::QScriptOriginalGlobalObject): need
+        to keep track of Date Constructor and Prototype.
+        (QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject): ditto.
+        (QScriptOriginalGlobalObject::isDate): use the Date Constructor
+        and Prototype to identify Date values.
+
+        * api/qscriptvalue.cpp:
+        (QScriptValue::isDate):
+        (QScriptValue::toDateTime):
+        * api/qscriptvalue.h:
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::isDate):
+        (QScriptValuePrivate::toDateTime):
+        * tests/qscriptengine/tst_qscriptengine.cpp:
+        (tst_QScriptEngine::newDate):
+
+2010-07-27  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Update the QScriptValue autotests suite.
+
+        QScriptValue generated files were updated, changes are:
+         - More tested values (for example QSE::newObject() and QSE::newArray())
+         - Tested values are recreated before each test and are not reused.
+         The change implies better code coverage and some expected result changes.
+         - A new test to check copy and assign functions.
+         - Tests are using standard QTestLib interface, without any custom macros.
+
+        [Qt] Improve test coverage for the QScriptValue
+        https://bugs.webkit.org/show_bug.cgi?id=42366
+
+        * tests/qscriptvalue/tst_qscriptvalue.cpp:
+        (tst_QScriptValue::tst_QScriptValue):
+        (tst_QScriptValue::~tst_QScriptValue):
+        (tst_QScriptValue::assignAndCopyConstruct_data):
+        (tst_QScriptValue::assignAndCopyConstruct):
+        * tests/qscriptvalue/tst_qscriptvalue.h:
+        * tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp:
+        (tst_QScriptValue::equals_data):
+        (tst_QScriptValue::equals):
+        (tst_QScriptValue::strictlyEquals_data):
+        (tst_QScriptValue::strictlyEquals):
+        (tst_QScriptValue::instanceOf_data):
+        (tst_QScriptValue::instanceOf):
+        * tests/qscriptvalue/tst_qscriptvalue_generated_init.cpp:
+        (tst_QScriptValue::initScriptValues):
+        * tests/qscriptvalue/tst_qscriptvalue_generated_istype.cpp:
+        (tst_QScriptValue::isValid_data):
+        (tst_QScriptValue::isValid):
+        (tst_QScriptValue::isBool_data):
+        (tst_QScriptValue::isBool):
+        (tst_QScriptValue::isBoolean_data):
+        (tst_QScriptValue::isBoolean):
+        (tst_QScriptValue::isNumber_data):
+        (tst_QScriptValue::isNumber):
+        (tst_QScriptValue::isFunction_data):
+        (tst_QScriptValue::isFunction):
+        (tst_QScriptValue::isNull_data):
+        (tst_QScriptValue::isNull):
+        (tst_QScriptValue::isString_data):
+        (tst_QScriptValue::isString):
+        (tst_QScriptValue::isUndefined_data):
+        (tst_QScriptValue::isUndefined):
+        (tst_QScriptValue::isObject_data):
+        (tst_QScriptValue::isObject):
+        (tst_QScriptValue::isArray_data):
+        (tst_QScriptValue::isArray):
+        (tst_QScriptValue::isError_data):
+        (tst_QScriptValue::isError):
+        * tests/qscriptvalue/tst_qscriptvalue_generated_totype.cpp:
+        (tst_QScriptValue::toString_data):
+        (tst_QScriptValue::toString):
+        (tst_QScriptValue::toNumber_data):
+        (tst_QScriptValue::toNumber):
+        (tst_QScriptValue::toBool_data):
+        (tst_QScriptValue::toBool):
+        (tst_QScriptValue::toBoolean_data):
+        (tst_QScriptValue::toBoolean):
+        (tst_QScriptValue::toInteger_data):
+        (tst_QScriptValue::toInteger):
+        (tst_QScriptValue::toInt32_data):
+        (tst_QScriptValue::toInt32):
+        (tst_QScriptValue::toUInt32_data):
+        (tst_QScriptValue::toUInt32):
+        (tst_QScriptValue::toUInt16_data):
+        (tst_QScriptValue::toUInt16):
+
+2010-07-27  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] Implement QScriptEngine::newFunction() parts that doesn't depend on QScriptContext
+        https://bugs.webkit.org/show_bug.cgi?id=42174
+
+        Since our function can be called in Javascript both as a function
+        and as a constructor, we couldn't use the existing
+        JSObjectMakeFunctionWithCallback() and JSObjectMakeConstructor().
+
+        Instead, a JSClassRef was created, implementing the needed
+        callbacks (the callAsConstructor is not there yet because its
+        behaviour depends on QScriptContext).
+
+        For the moment, QScriptContext is defined as a void type, since we
+        still don't use it.
+
+        The variant of newFunction() that also takes an external argument
+        was also implemented. The details of implementation were added to
+        the qscriptfunction{.c,_p.h} files.
+
+        This commit also adds tests, some of them from Qt's upstream.
+
+        * api/QtScript.pro:
+        * api/qscriptengine.cpp:
+        (QScriptEngine::newFunction):
+        * api/qscriptengine.h:
+        * api/qscriptengine_p.cpp:
+        (QScriptEnginePrivate::QScriptEnginePrivate):
+        (QScriptEnginePrivate::~QScriptEnginePrivate):
+        (QScriptEnginePrivate::newFunction):
+        * api/qscriptengine_p.h:
+        * api/qscriptfunction.cpp: Added.
+        (qt_NativeFunction_finalize):
+        (qt_NativeFunction_callAsFunction):
+        (qt_NativeFunctionWithArg_finalize):
+        (qt_NativeFunctionWithArg_callAsFunction):
+        * api/qscriptfunction_p.h: Added.
+        (QNativeFunctionData::QNativeFunctionData):
+        (QNativeFunctionWithArgData::QNativeFunctionWithArgData):
+        * api/qscriptoriginalglobalobject_p.h:
+        (QScriptOriginalGlobalObject::QScriptOriginalGlobalObject):
+        (QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject):
+        (QScriptOriginalGlobalObject::functionPrototype):
+        * tests/qscriptengine/tst_qscriptengine.cpp:
+        (myFunction):
+        (myFunctionWithArg):
+        (myFunctionThatReturns):
+        (myFunctionThatReturnsWithoutEngine):
+        (myFunctionThatReturnsWrongEngine):
+        (tst_QScriptEngine::newFunction):
+
+2010-07-23  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        QScriptValue::equals benchmark crash fix.
+
+        Patch changes QScriptValue::equals implementation to cover
+        more edge cases.
+
+        Problem exposes an issue in our autotests (all values got
+        bound to an engine too fast - bug 42366).
+
+        [Qt] QScriptValue::equals asserts
+        https://bugs.webkit.org/show_bug.cgi?id=42363
+
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::equals):
+
+2010-07-14  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Introduce QScriptOriginalGlobalObject.
+
+        QtScript exposes more functionality than JSC C API. Sometimes it is
+        necessary to take a shortcut in implementation. Really often we have
+        to use a standard JS function. These function could be changed or
+        even deleted by a script, so a backup of a reference to an object is needed.
+
+        In them same time this is rather a workaround then real fix, so the code
+        should be separated and changed easily in future. It is why we need
+        the new internal class.
+
+        The patch fixes a few crashes.
+
+        [Qt] QScriptEngine should work correctly even after global object changes
+        https://bugs.webkit.org/show_bug.cgi?id=41839
+
+        * api/QtScript.pro:
+        * api/qscriptengine_p.cpp:
+        (QScriptEnginePrivate::QScriptEnginePrivate):
+        (QScriptEnginePrivate::~QScriptEnginePrivate):
+        * api/qscriptengine_p.h:
+        (QScriptEnginePrivate::isArray):
+        (QScriptEnginePrivate::isError):
+        (QScriptEnginePrivate::objectHasOwnProperty):
+        (QScriptEnginePrivate::objectGetOwnPropertyNames):
+        * api/qscriptoriginalglobalobject_p.h: Added.
+        (QScriptOriginalGlobalObject::QScriptOriginalGlobalObject):
+        (QScriptOriginalGlobalObject::initializeMember):
+        (QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject):
+        (QScriptOriginalGlobalObject::objectHasOwnProperty):
+        (QScriptOriginalGlobalObject::objectGetOwnPropertyNames):
+        (QScriptOriginalGlobalObject::isArray):
+        (QScriptOriginalGlobalObject::isError):
+        (QScriptOriginalGlobalObject::isType):
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::isError):
+        (QScriptValuePrivate::hasOwnProperty):
+        * api/qscriptvalueiterator_p.h:
+        (QScriptValueIteratorPrivate::QScriptValueIteratorPrivate):
+        * tests/qscriptvalue/tst_qscriptvalue.cpp:
+        (tst_QScriptValue::globalObjectChanges):
+        * tests/qscriptvalue/tst_qscriptvalue.h:
+
+2010-07-13  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Simon Hausmann.
+
+        Introduce QScriptValueIterator.
+
+        The QScriptValueIterator class permits to iterate over a QScriptValue's properties.
+
+        [Qt] QtScript should provide an API for enumerating a JS object's properties
+        https://bugs.webkit.org/show_bug.cgi?id=41680
+
+        * api/QtScript.pro:
+        * api/qscriptvalueiterator.cpp: Added.
+        (QScriptValueIterator::QScriptValueIterator):
+        (QScriptValueIterator::~QScriptValueIterator):
+        (QScriptValueIterator::hasNext):
+        (QScriptValueIterator::next):
+        (QScriptValueIterator::hasPrevious):
+        (QScriptValueIterator::previous):
+        (QScriptValueIterator::toFront):
+        (QScriptValueIterator::toBack):
+        (QScriptValueIterator::name):
+        (QScriptValueIterator::scriptName):
+        (QScriptValueIterator::value):
+        (QScriptValueIterator::setValue):
+        (QScriptValueIterator::remove):
+        (QScriptValueIterator::flags):
+        (QScriptValueIterator::operator=):
+        * api/qscriptvalueiterator.h: Added.
+        * api/qscriptvalueiterator_p.h: Added.
+        (QScriptValueIteratorPrivate::QScriptValueIteratorPrivate):
+        (QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate):
+        (QScriptValueIteratorPrivate::hasNext):
+        (QScriptValueIteratorPrivate::next):
+        (QScriptValueIteratorPrivate::hasPrevious):
+        (QScriptValueIteratorPrivate::previous):
+        (QScriptValueIteratorPrivate::name):
+        (QScriptValueIteratorPrivate::scriptName):
+        (QScriptValueIteratorPrivate::value):
+        (QScriptValueIteratorPrivate::setValue):
+        (QScriptValueIteratorPrivate::remove):
+        (QScriptValueIteratorPrivate::toFront):
+        (QScriptValueIteratorPrivate::toBack):
+        (QScriptValueIteratorPrivate::flags):
+        (QScriptValueIteratorPrivate::isValid):
+        (QScriptValueIteratorPrivate::engine):
+        * tests/qscriptvalueiterator/qscriptvalueiterator.pro: Added.
+        * tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp: Added.
+        (tst_QScriptValueIterator::tst_QScriptValueIterator):
+        (tst_QScriptValueIterator::~tst_QScriptValueIterator):
+        (tst_QScriptValueIterator::iterateForward_data):
+        (tst_QScriptValueIterator::iterateForward):
+        (tst_QScriptValueIterator::iterateBackward_data):
+        (tst_QScriptValueIterator::iterateBackward):
+        (tst_QScriptValueIterator::iterateArray_data):
+        (tst_QScriptValueIterator::iterateArray):
+        (tst_QScriptValueIterator::iterateBackAndForth):
+        (tst_QScriptValueIterator::setValue):
+        (tst_QScriptValueIterator::remove):
+        (tst_QScriptValueIterator::removeMixed):
+        (tst_QScriptValueIterator::removeUndeletable):
+        (tst_QScriptValueIterator::iterateString):
+        (tst_QScriptValueIterator::assignObjectToIterator):
+        * tests/tests.pro:
+
+2010-07-09  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Simon Hausmann.
+
+        Implementation of the QScriptValue::propertyFlags function.
+
+        The function returns the flags of a property with the given name,
+        using a given mode to resolve the property. This is a simple
+        implementation that is sufficient to test the QScriptValueIterator.
+
+        [Qt] QScriptValue API should have a property flag accessor.
+        https://bugs.webkit.org/show_bug.cgi?id=41769
+
+        * api/qscriptvalue.cpp:
+        (QScriptValue::propertyFlags):
+        * api/qscriptvalue.h:
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::propertyFlags):
+        * tests/qscriptvalue/tst_qscriptvalue.cpp:
+        (tst_QScriptValue::propertyFlag_data):
+        (tst_QScriptValue::propertyFlag):
+        * tests/qscriptvalue/tst_qscriptvalue.h:
+
+2010-07-07  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Implementation of QScriptValue::isArray()
+        https://bugs.webkit.org/show_bug.cgi?id=41713
+
+        Since we don't have access to the [[Class]] internal property of
+        builtins (including Array), the solution was to keep the original 'Array'
+        (constructor) and 'Array.prototype' objects and use them to identify
+        if a given object is an Array.
+
+        Also uncomment some tests and add some tests of newArray() that
+        depended on isArray(). 
+
+        * api/qscriptengine_p.cpp:
+        (QScriptEnginePrivate::QScriptEnginePrivate):
+        (QScriptEnginePrivate::~QScriptEnginePrivate):
+        * api/qscriptengine_p.h:
+        (QScriptEnginePrivate::isArray):
+        * api/qscriptvalue.cpp:
+        (QScriptValue::isArray):
+        * api/qscriptvalue.h:
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::isArray):
+        * tests/qscriptengine/tst_qscriptengine.cpp:
+        (tst_QScriptEngine::newArray):
+
+2010-07-06  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        Implementation of QScriptValue properties accessors.
+
+        The patch contains implementation of the QScriptValue::property() and
+        the QScriptValue::setProperty(). It is not full functionality, as these
+        method are too complex for one patch, but it is enough to cover about
+        95% of use cases.
+
+        Missing functionality:
+         - Few of the PropertyFlags are ignored.
+         - Only a public part of the ResolveFlags can be used (ResolveLocal,
+         ResolvePrototype).
+
+        A lot of new test cases were added.
+
+        [Qt] QScriptValue should have API for accessing object properties
+        https://bugs.webkit.org/show_bug.cgi?id=40903
+
+        * api/qscriptconverter_p.h:
+        (QScriptConverter::toPropertyFlags):
+        * api/qscriptstring_p.h:
+        (QScriptStringPrivate::operator JSStringRef):
+        * api/qscriptvalue.cpp:
+        (QScriptValue::property):
+        (QScriptValue::setProperty):
+        * api/qscriptvalue.h:
+        (QScriptValue::):
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::assignEngine):
+        (QScriptValuePrivate::property):
+        (QScriptValuePrivate::hasOwnProperty):
+        (QScriptValuePrivate::setProperty):
+        (QScriptValuePrivate::deleteProperty):
+        * tests/qscriptvalue/tst_qscriptvalue.cpp:
+        (tst_QScriptValue::getPropertySimple_data):
+        (tst_QScriptValue::getPropertySimple):
+        (tst_QScriptValue::setPropertySimple):
+        (tst_QScriptValue::getPropertyResolveFlag):
+        (tst_QScriptValue::getSetProperty):
+        (tst_QScriptValue::setProperty_data):
+        (tst_QScriptValue::setProperty):
+        * tests/qscriptvalue/tst_qscriptvalue.h:
+
+2010-07-02  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Simon Hausmann.
+
+        Compilation fix.
+
+        QScriptEnginePrivate::newArray can't be const because it can
+        throw an exception.
+
+        [Qt] QScriptEnginePrivate compilation fix
+        https://bugs.webkit.org/show_bug.cgi?id=41520
+
+        * api/qscriptengine_p.cpp:
+        (QScriptEnginePrivate::newArray):
+        * api/qscriptengine_p.h:
+
+2010-06-28  Jedrzej Nowacki  <jedrzej.nowacki@nokia.com>
+
+        Reviewed by Simon Hausmann.
+
+        Implement exception reporting in the QtScript API.
+
+        The exception should be accessible through the API by the uncaughtException
+        function. Functions; hasUncaughtException, clearExceptions, uncaughtExceptionLineNumber,
+        uncaughtExceptionBacktrace were added to facilitate error checking and debugging.
+
+        [Qt] QtScript API should be exceptions aware.
+        https://bugs.webkit.org/show_bug.cgi?id=41199
+
+        * api/qscriptengine.cpp:
+        (QScriptEngine::hasUncaughtException):
+        (QScriptEngine::uncaughtException):
+        (QScriptEngine::clearExceptions):
+        (QScriptEngine::uncaughtExceptionLineNumber):
+        (QScriptEngine::uncaughtExceptionBacktrace):
+        * api/qscriptengine.h:
+        * api/qscriptengine_p.cpp:
+        (QScriptEnginePrivate::QScriptEnginePrivate):
+        (QScriptEnginePrivate::~QScriptEnginePrivate):
+        (QScriptEnginePrivate::uncaughtException):
+        * api/qscriptengine_p.h:
+        (QScriptEnginePrivate::):
+        (QScriptEnginePrivate::evaluate):
+        (QScriptEnginePrivate::hasUncaughtException):
+        (QScriptEnginePrivate::clearExceptions):
+        (QScriptEnginePrivate::setException):
+        (QScriptEnginePrivate::uncaughtExceptionLineNumber):
+        (QScriptEnginePrivate::uncaughtExceptionBacktrace):
+        * api/qscriptvalue_p.h:
+        (QScriptValuePrivate::toString):
+        (QScriptValuePrivate::toNumber):
+        (QScriptValuePrivate::toObject):
+        (QScriptValuePrivate::equals):
+        (QScriptValuePrivate::instanceOf):
+        (QScriptValuePrivate::call):
+        (QScriptValuePrivate::inherits):
+        * tests/qscriptengine/tst_qscriptengine.cpp:
+        (tst_QScriptEngine::uncaughtException):
+
index 88629c79f6b59d8d85afd75bc18c239c55857be2..22e8b0ccf9c2ed8a07abe684cedd937ad750c987 100644 (file)
@@ -7,39 +7,39 @@ INCLUDEPATH += $$PWD
 CONFIG += building-libs
 
 isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = ../../generated
-CONFIG(debug, debug|release) {
-    OBJECTS_DIR = obj/debug
-} else { # Release
-    OBJECTS_DIR = obj/release
-}
 
 isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../..
 include($$PWD/../../../WebKit.pri)
 
 include($$PWD/../../JavaScriptCore.pri)
-addJavaScriptCoreLib(../..)
+prependJavaScriptCoreLib(../..)
 
 INCLUDEPATH += $$PWD/../../API
 
 SOURCES +=  $$PWD/qscriptengine.cpp \
             $$PWD/qscriptengine_p.cpp \
             $$PWD/qscriptvalue.cpp \
+            $$PWD/qscriptvalueiterator.cpp \
             $$PWD/qscriptstring.cpp \
             $$PWD/qscriptprogram.cpp \
             $$PWD/qscriptsyntaxcheckresult.cpp \
+            $$PWD/qscriptfunction.cpp
 
 HEADERS +=  $$PWD/qtscriptglobal.h \
             $$PWD/qscriptengine.h \
             $$PWD/qscriptengine_p.h \
             $$PWD/qscriptvalue.h \
             $$PWD/qscriptvalue_p.h \
+            $$PWD/qscriptvalueiterator.h \
+            $$PWD/qscriptvalueiterator_p.h \
             $$PWD/qscriptconverter_p.h \
             $$PWD/qscriptstring.h \
             $$PWD/qscriptstring_p.h \
             $$PWD/qscriptprogram.h \
             $$PWD/qscriptprogram_p.h \
             $$PWD/qscriptsyntaxcheckresult.h \
-
+            $$PWD/qscriptoriginalglobalobject_p.h \
+            $$PWD/qscriptfunction_p.h
 
 !static: DEFINES += QT_MAKEDLL
 
index cd86e2074c7c2930001d7d728ea423d9895476c3..0c57d9554a1d6f1e3542cb7c744ac3994e34eb2f 100644 (file)
@@ -20,7 +20,9 @@
 #ifndef qscriptconverter_p_h
 #define qscriptconverter_p_h
 
+#include "qscriptvalue.h"
 #include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qglobal.h>
 #include <QtCore/qnumeric.h>
 #include <QtCore/qstring.h>
 #include <QtCore/qvarlengtharray.h>
@@ -127,6 +129,18 @@ public:
         buf.append(0);
         return QString::fromLatin1(buf.constData());
     }
+
+    static JSPropertyAttributes toPropertyFlags(const QFlags<QScriptValue::PropertyFlag>& flags)
+    {
+        JSPropertyAttributes attr = 0;
+        if (flags.testFlag(QScriptValue::ReadOnly))
+            attr |= kJSPropertyAttributeReadOnly;
+        if (flags.testFlag(QScriptValue::Undeletable))
+            attr |= kJSPropertyAttributeDontDelete;
+        if (flags.testFlag(QScriptValue::SkipInEnumeration))
+            attr |= kJSPropertyAttributeDontEnum;
+        return attr;
+    }
 };
 
 #endif // qscriptconverter_p_h
index d49c578162c1b7702d16eaccb297179ac52ef5e7..607b0b9dcd6f81bc022fd783a1f648b85f2bf8e5 100644 (file)
@@ -25,6 +25,8 @@
 #include "qscriptprogram_p.h"
 #include "qscriptsyntaxcheckresult_p.h"
 #include "qscriptvalue_p.h"
+#include <QtCore/qdatetime.h>
+#include <QtCore/qnumeric.h>
 
 /*!
     Constructs a QScriptEngine object.
@@ -95,6 +97,71 @@ QScriptValue QScriptEngine::evaluate(const QScriptProgram& program)
     return QScriptValuePrivate::get(d_ptr->evaluate(QScriptProgramPrivate::get(program)));
 }
 
+/*!
+    Returns true if the last script evaluation resulted in an uncaught
+    exception; otherwise returns false.
+
+    The exception state is cleared when evaluate() is called.
+
+    \sa uncaughtException(), uncaughtExceptionLineNumber(),
+      uncaughtExceptionBacktrace()
+*/
+bool QScriptEngine::hasUncaughtException() const
+{
+    return d_ptr->hasUncaughtException();
+}
+
+/*!
+    Returns the current uncaught exception, or an invalid QScriptValue
+    if there is no uncaught exception.
+
+    The exception value is typically an \c{Error} object; in that case,
+    you can call toString() on the return value to obtain an error
+    message.
+
+    \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
+      uncaughtExceptionBacktrace()
+*/
+QScriptValue QScriptEngine::uncaughtException() const
+{
+    return QScriptValuePrivate::get(d_ptr->uncaughtException());
+}
+
+/*!
+    Clears any uncaught exceptions in this engine.
+
+    \sa hasUncaughtException()
+*/
+void QScriptEngine::clearExceptions()
+{
+    d_ptr->clearExceptions();
+}
+
+/*!
+    Returns the line number where the last uncaught exception occurred.
+
+    Line numbers are 1-based, unless a different base was specified as
+    the second argument to evaluate().
+
+    \sa hasUncaughtException(), uncaughtExceptionBacktrace()
+*/
+int QScriptEngine::uncaughtExceptionLineNumber() const
+{
+    return d_ptr->uncaughtExceptionLineNumber();
+}
+
+/*!
+    Returns a human-readable backtrace of the last uncaught exception.
+
+    Each line is of the form \c{<function-name>(<arguments>)@<file-name>:<line-number>}.
+
+    \sa uncaughtException()
+*/
+QStringList QScriptEngine::uncaughtExceptionBacktrace() const
+{
+    return d_ptr->uncaughtExceptionBacktrace();
+}
+
 /*!
     Runs the garbage collector.
 
@@ -150,6 +217,28 @@ QScriptString QScriptEngine::toStringHandle(const QString& str)
     return QScriptStringPrivate::get(d_ptr->toStringHandle(str));
 }
 
+/*!
+  Converts the given \a value to an object, if such a conversion is
+  possible; otherwise returns an invalid QScriptValue. The conversion
+  is performed according to the following table:
+
+    \table
+    \header \o Input Type \o Result
+    \row    \o Undefined  \o An invalid QScriptValue.
+    \row    \o Null       \o An invalid QScriptValue.
+    \row    \o Boolean    \o A new Boolean object whose internal value is set to the value of the boolean.
+    \row    \o Number     \o A new Number object whose internal value is set to the value of the number.
+    \row    \o String     \o A new String object whose internal value is set to the value of the string.
+    \row    \o Object     \o The result is the object itself (no conversion).
+    \endtable
+
+    \sa newObject()
+*/
+QScriptValue QScriptEngine::toObject(const QScriptValue& value)
+{
+    return QScriptValuePrivate::get(QScriptValuePrivate::get(value)->toObject(d_ptr.data()));
+}
+
 /*!
   Returns a QScriptValue of the primitive type Null.
 
@@ -170,6 +259,137 @@ QScriptValue QScriptEngine::undefinedValue()
     return QScriptValue(this, QScriptValue::UndefinedValue);
 }
 
+/*!
+    Creates a QScriptValue that wraps a native (C++) function. \a fun
+    must be a C++ function with signature QScriptEngine::FunctionSignature.
+    \a length is the number of arguments that \a fun expects; this becomes
+    the \c{length} property of the created QScriptValue.
+
+    Note that \a length only gives an indication of the number of
+    arguments that the function expects; an actual invocation of a
+    function can include any number of arguments. You can check the
+    \l{QScriptContext::argumentCount()}{argumentCount()} of the
+    QScriptContext associated with the invocation to determine the
+    actual number of arguments passed.
+
+    A \c{prototype} property is automatically created for the resulting
+    function object, to provide for the possibility that the function
+    will be used as a constructor.
+
+    By combining newFunction() and the property flags
+    QScriptValue::PropertyGetter and QScriptValue::PropertySetter, you
+    can create script object properties that behave like normal
+    properties in script code, but are in fact accessed through
+    functions (analogous to how properties work in \l{Qt's Property
+    System}). Example:
+
+    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 11
+
+    When the property \c{foo} of the script object is subsequently
+    accessed in script code, \c{getSetFoo()} will be invoked to handle
+    the access.  In this particular case, we chose to store the "real"
+    value of \c{foo} as a property of the accessor function itself; you
+    are of course free to do whatever you like in this function.
+
+    In the above example, a single native function was used to handle
+    both reads and writes to the property; the argument count is used to
+    determine if we are handling a read or write. You can also use two
+    separate functions; just specify the relevant flag
+    (QScriptValue::PropertyGetter or QScriptValue::PropertySetter) when
+    setting the property, e.g.:
+
+    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 12
+
+    \sa QScriptValue::call()
+*/
+QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, int length)
+{
+    return QScriptValuePrivate::get(d_ptr->newFunction(fun, 0, length));
+}
+
+/*!
+    Creates a constructor function from \a fun, with the given \a length.
+    The \c{prototype} property of the resulting function is set to be the
+    given \a prototype. The \c{constructor} property of \a prototype is
+    set to be the resulting function.
+
+    When a function is called as a constructor (e.g. \c{new Foo()}), the
+    `this' object associated with the function call is the new object
+    that the function is expected to initialize; the prototype of this
+    default constructed object will be the function's public
+    \c{prototype} property. If you always want the function to behave as
+    a constructor (e.g. \c{Foo()} should also create a new object), or
+    if you need to create your own object rather than using the default
+    `this' object, you should make sure that the prototype of your
+    object is set correctly; either by setting it manually, or, when
+    wrapping a custom type, by having registered the defaultPrototype()
+    of that type. Example:
+
+    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 9
+
+    To wrap a custom type and provide a constructor for it, you'd typically
+    do something like this:
+
+    \snippet doc/src/snippets/code/src_script_qscriptengine.cpp 10
+*/
+QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, const QScriptValue& prototype, int length)
+{
+    return QScriptValuePrivate::get(d_ptr->newFunction(fun, QScriptValuePrivate::get(prototype), length));
+}
+
+/*!
+    \internal
+    \since 4.4
+*/
+QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg)
+{
+    return QScriptValuePrivate::get(d_ptr->newFunction(fun, arg));
+}
+
+/*!
+  Creates a QtScript object of class Object.
+
+  The prototype of the created object will be the Object
+  prototype object.
+
+  \sa newArray(), QScriptValue::setProperty()
+*/
+QScriptValue QScriptEngine::newObject()
+{
+    return QScriptValuePrivate::get(d_ptr->newObject());
+}
+
+/*!
+  Creates a QtScript object of class Array with the given \a length.
+
+  \sa newObject()
+*/
+QScriptValue QScriptEngine::newArray(uint length)
+{
+    return QScriptValuePrivate::get(d_ptr->newArray(length));
+}
+
+/*!
+    Creates a QtScript object of class Date with the given \a value
+    (the number of milliseconds since 01 January 1970, UTC).
+*/
+QScriptValue QScriptEngine::newDate(qsreal value)
+{
+    return QScriptValuePrivate::get(d_ptr->newDate(value));
+}
+
+/*!
+    Creates a QtScript object of class Date from the given \a value.
+
+    \sa QScriptValue::toDateTime()
+*/
+QScriptValue QScriptEngine::newDate(const QDateTime& value)
+{
+    if (value.isValid())
+        return QScriptValuePrivate::get(d_ptr->newDate(qsreal(value.toMSecsSinceEpoch())));
+    return QScriptValuePrivate::get(d_ptr->newDate(qSNaN()));
+}
+
 /*!
   Returns this engine's Global Object.
 
@@ -184,3 +404,23 @@ QScriptValue QScriptEngine::globalObject() const
 {
     return QScriptValuePrivate::get(d_ptr->globalObject());
 }
+
+/*!
+    \typedef QScriptEngine::FunctionSignature
+    \relates QScriptEngine
+
+    The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *)}.
+
+    A function with such a signature can be passed to
+    QScriptEngine::newFunction() to wrap the function.
+*/
+
+/*!
+    \typedef QScriptEngine::FunctionWithArgSignature
+    \relates QScriptEngine
+
+    The function signature \c{QScriptValue f(QScriptContext *, QScriptEngine *, void *)}.
+
+    A function with such a signature can be passed to
+    QScriptEngine::newFunction() to wrap the function.
+*/
index e10888dc1b41476b9afeee1bbd9c4a85c42e64c7..281707f60c76ea0ad5d6eb1e4691d263695a0be6 100644 (file)
 #include "qscriptprogram.h"
 #include "qscriptstring.h"
 #include "qscriptsyntaxcheckresult.h"
+#include "qscriptvalue.h"
 #include <QtCore/qobject.h>
 #include <QtCore/qshareddata.h>
 #include <QtCore/qstring.h>
 
-class QScriptValue;
+class QDateTime;
 class QScriptEnginePrivate;
 
+// FIXME: Remove this once QScriptContext is properly defined.
+typedef void QScriptContext;
+
 // Internal typedef
 typedef QExplicitlySharedDataPointer<QScriptEnginePrivate> QScriptEnginePtr;
 
@@ -42,13 +46,32 @@ public:
     QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1);
     QScriptValue evaluate(const QScriptProgram& program);
 
+    bool hasUncaughtException() const;
+    QScriptValue uncaughtException() const;
+    void clearExceptions();
+    int uncaughtExceptionLineNumber() const;
+    QStringList uncaughtExceptionBacktrace() const;
+
     void collectGarbage();
     void reportAdditionalMemoryCost(int cost);
 
     QScriptString toStringHandle(const QString& str);
+    QScriptValue toObject(const QScriptValue& value);
 
     QScriptValue nullValue();
     QScriptValue undefinedValue();
+
+    typedef QScriptValue (*FunctionSignature)(QScriptContext *, QScriptEngine *);
+    typedef QScriptValue (*FunctionWithArgSignature)(QScriptContext *, QScriptEngine *, void *);
+
+    QScriptValue newFunction(FunctionSignature fun, int length = 0);
+    QScriptValue newFunction(FunctionSignature fun, const QScriptValue& prototype, int length = 0);
+    QScriptValue newFunction(FunctionWithArgSignature fun, void* arg);
+
+    QScriptValue newObject();
+    QScriptValue newArray(uint length = 0);
+    QScriptValue newDate(qsreal value);
+    QScriptValue newDate(const QDateTime& value);
     QScriptValue globalObject() const;
 private:
     friend class QScriptEnginePrivate;
index 38185abd91e9eb02613a2552b55a58dc4dbd92d1..89054c085574a802e81f31063e52911ec644599d 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "qscriptengine_p.h"
 
+#include "qscriptfunction_p.h"
 #include "qscriptprogram_p.h"
 #include "qscriptvalue_p.h"
 
 QScriptEnginePrivate::QScriptEnginePrivate(const QScriptEngine* engine)
     : q_ptr(const_cast<QScriptEngine*>(engine))
     , m_context(JSGlobalContextCreate(0))
+    , m_exception(0)
+    , m_originalGlobalObject(m_context)
+    , m_nativeFunctionClass(JSClassCreate(&qt_NativeFunctionClass))
+    , m_nativeFunctionWithArgClass(JSClassCreate(&qt_NativeFunctionWithArgClass))
 {
 }
 
 QScriptEnginePrivate::~QScriptEnginePrivate()
 {
+    JSClassRelease(m_nativeFunctionClass);
+    JSClassRelease(m_nativeFunctionWithArgClass);
+    if (m_exception)
+        JSValueUnprotect(m_context, m_exception);
     JSGlobalContextRelease(m_context);
 }
 
@@ -74,11 +83,85 @@ QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QScriptProgramPrivate*
 {
     if (program->isNull())
         return new QScriptValuePrivate;
-    return new QScriptValuePrivate(this, evaluate(program->program(), program->file(), program->line()));
+    return new QScriptValuePrivate(this, evaluate(*program, program->file(), program->line()));
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::uncaughtException() const
+{
+    return m_exception ? new QScriptValuePrivate(this, m_exception) : new QScriptValuePrivate();
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::newFunction(QScriptEngine::FunctionSignature fun, QScriptValuePrivate* prototype, int length)
+{
+    // Note that this private data will be deleted in the object finalize function.
+    QNativeFunctionData* data = new QNativeFunctionData(this, fun);
+    JSObjectRef funJS = JSObjectMake(m_context, m_nativeFunctionClass, reinterpret_cast<void*>(data));
+    QScriptValuePrivate* proto = prototype ? prototype : newObject();
+    return newFunction(funJS, proto);
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg)
+{
+    // Note that this private data will be deleted in the object finalize function.
+    QNativeFunctionWithArgData* data = new QNativeFunctionWithArgData(this, fun, arg);
+    JSObjectRef funJS = JSObjectMake(m_context, m_nativeFunctionWithArgClass, reinterpret_cast<void*>(data));
+    QScriptValuePrivate* proto = newObject();
+    return newFunction(funJS, proto);
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::newFunction(JSObjectRef funJS, QScriptValuePrivate* prototype)
+{
+    JSObjectSetPrototype(m_context, funJS, m_originalGlobalObject.functionPrototype());
+
+    QScriptValuePrivate* result = new QScriptValuePrivate(this, funJS);
+    static JSStringRef protoName = QScriptConverter::toString("prototype");
+    static JSStringRef constructorName = QScriptConverter::toString("constructor");
+    result->setProperty(protoName, prototype, QScriptValue::Undeletable);
+    prototype->setProperty(constructorName, result, QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration));
+
+    return result;
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::newObject() const
+{
+    return new QScriptValuePrivate(this, JSObjectMake(m_context, /* jsClass */ 0, /* userData */ 0));
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::newArray(uint length)
+{
+    JSValueRef exception = 0;
+    JSObjectRef array = JSObjectMakeArray(m_context, /* argumentCount */ 0, /* arguments */ 0, &exception);
+
+    if (!exception) {
+        if (length > 0) {
+            JSRetainPtr<JSStringRef> lengthRef(Adopt, JSStringCreateWithUTF8CString("length"));
+            // array is an Array instance, so an exception should not occure here.
+            JSObjectSetProperty(m_context, array, lengthRef.get(), JSValueMakeNumber(m_context, length), kJSPropertyAttributeNone, /* exception */ 0);
+        }
+    } else {
+        setException(exception, NotNullException);
+        return new QScriptValuePrivate();
+    }
+
+    return new QScriptValuePrivate(this, array);
+}
+
+QScriptValuePrivate* QScriptEnginePrivate::newDate(qsreal value)
+{
+    JSValueRef exception = 0;
+    JSValueRef argument = JSValueMakeNumber(m_context, value);
+    JSObjectRef result = JSObjectMakeDate(m_context, /* argumentCount */ 1, &argument, &exception);
+
+    if (exception) {
+        setException(exception, NotNullException);
+        return new QScriptValuePrivate();
+    }
+
+    return new QScriptValuePrivate(this, result);
 }
 
 QScriptValuePrivate* QScriptEnginePrivate::globalObject() const
 {
-    JSObjectRef globalObject = JSContextGetGlobalObject(context());
-    return new QScriptValuePrivate(this, globalObject, globalObject);
+    JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
+    return new QScriptValuePrivate(this, globalObject);
 }
index c6c64dd9fed483b723313c618c094a3ce1c5e9ca..4603b91791c9105026f6c36d6d2b13f0a2ff330c 100644 (file)
 
 #include "qscriptconverter_p.h"
 #include "qscriptengine.h"
+#include "qscriptoriginalglobalobject_p.h"
 #include "qscriptstring_p.h"
 #include "qscriptsyntaxcheckresult_p.h"
 #include "qscriptvalue.h"
 #include <JavaScriptCore/JavaScript.h>
+#include <JavaScriptCore/JSRetainPtr.h>
 #include <JSBasePrivate.h>
 #include <QtCore/qshareddata.h>
 #include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
 
 class QScriptEngine;
 class QScriptSyntaxCheckResultPrivate;
@@ -41,11 +44,23 @@ public:
     QScriptEnginePrivate(const QScriptEngine*);
     ~QScriptEnginePrivate();
 
+    enum SetExceptionFlag {
+        IgnoreNullException = 0x01,
+        NotNullException = 0x02,
+    };
+
     QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program);
     QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber);
     QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program);
     inline JSValueRef evaluate(JSStringRef program, JSStringRef fileName, int lineNumber);
 
+    inline bool hasUncaughtException() const;
+    QScriptValuePrivate* uncaughtException() const;
+    inline void clearExceptions();
+    inline void setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags = IgnoreNullException);
+    inline int uncaughtExceptionLineNumber() const;
+    inline QStringList uncaughtExceptionBacktrace() const;
+
     inline void collectGarbage();
     inline void reportAdditionalMemoryCost(int cost);
 
@@ -56,14 +71,34 @@ public:
     inline JSValueRef makeJSValue(bool number) const;
     inline JSValueRef makeJSValue(QScriptValue::SpecialValue value) const;
 
+    QScriptValuePrivate* newFunction(QScriptEngine::FunctionSignature fun, QScriptValuePrivate* prototype, int length);
+    QScriptValuePrivate* newFunction(QScriptEngine::FunctionWithArgSignature fun, void* arg);
+    QScriptValuePrivate* newFunction(JSObjectRef funObject, QScriptValuePrivate* prototype);
+
+    QScriptValuePrivate* newObject() const;
+    QScriptValuePrivate* newArray(uint length);
+    QScriptValuePrivate* newDate(qsreal value);
     QScriptValuePrivate* globalObject() const;
 
     inline QScriptStringPrivate* toStringHandle(const QString& str) const;
 
-    inline JSGlobalContextRef context() const;
+    inline operator JSGlobalContextRef() const;
+
+    inline bool isDate(JSValueRef value) const;
+    inline bool isArray(JSValueRef value) const;
+    inline bool isError(JSValueRef value) const;
+    inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const;
+    inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const;
+
 private:
     QScriptEngine* q_ptr;
     JSGlobalContextRef m_context;
+    JSValueRef m_exception;
+
+    QScriptOriginalGlobalObject m_originalGlobalObject;
+
+    JSClassRef m_nativeFunctionClass;
+    JSClassRef m_nativeFunctionWithArgClass;
 };
 
 
@@ -76,11 +111,67 @@ JSValueRef QScriptEnginePrivate::evaluate(JSStringRef program, JSStringRef fileN
 {
     JSValueRef exception;
     JSValueRef result = JSEvaluateScript(m_context, program, /* Global Object */ 0, fileName, lineNumber, &exception);
-    if (!result)
+    if (!result) {
+        setException(exception, NotNullException);
         return exception; // returns an exception
+    }
+    clearExceptions();
     return result;
 }
 
+bool QScriptEnginePrivate::hasUncaughtException() const
+{
+    return m_exception;
+}
+
+void QScriptEnginePrivate::clearExceptions()
+{
+    if (m_exception)
+        JSValueUnprotect(m_context, m_exception);
+    m_exception = 0;
+}
+
+void QScriptEnginePrivate::setException(JSValueRef exception, const /* SetExceptionFlags */ unsigned flags)
+{
+    if (!((flags & NotNullException) || exception))
+        return;
+    Q_ASSERT(exception);
+
+    if (m_exception)
+        JSValueUnprotect(m_context, m_exception);
+    JSValueProtect(m_context, exception);
+    m_exception = exception;
+}
+
+int QScriptEnginePrivate::uncaughtExceptionLineNumber() const
+{
+    if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception))
+        return -1;
+
+    JSValueRef exception = 0;
+    JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line"));
+    JSValueRef lineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception);
+    int result = JSValueToNumber(m_context, lineNumber, &exception);
+    return exception ? -1 : result;
+}
+
+QStringList QScriptEnginePrivate::uncaughtExceptionBacktrace() const
+{
+    if (!hasUncaughtException() || !JSValueIsObject(m_context, m_exception))
+        return QStringList();
+
+    JSValueRef exception = 0;
+    JSRetainPtr<JSStringRef> fileNamePropertyName(Adopt, QScriptConverter::toString("sourceURL"));
+    JSRetainPtr<JSStringRef> lineNumberPropertyName(Adopt, QScriptConverter::toString("line"));
+    JSValueRef jsFileName = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), fileNamePropertyName.get(), &exception);
+    JSValueRef jsLineNumber = JSObjectGetProperty(m_context, const_cast<JSObjectRef>(m_exception), lineNumberPropertyName.get(), &exception);
+    JSRetainPtr<JSStringRef> fileName(Adopt, JSValueToStringCopy(m_context, jsFileName, &exception));
+    int lineNumber = JSValueToNumber(m_context, jsLineNumber, &exception);
+    return QStringList(QString::fromLatin1("<anonymous>()@%0:%1")
+            .arg(QScriptConverter::toString(fileName.get()))
+            .arg(QScriptConverter::toString(exception ? -1 : lineNumber)));
+}
+
 void QScriptEnginePrivate::collectGarbage()
 {
     JSGarbageCollect(m_context);
@@ -132,9 +223,37 @@ QScriptStringPrivate* QScriptEnginePrivate::toStringHandle(const QString& str) c
     return new QScriptStringPrivate(str);
 }
 
-JSGlobalContextRef QScriptEnginePrivate::context() const
+QScriptEnginePrivate::operator JSGlobalContextRef() const
 {
+    Q_ASSERT(this);
     return m_context;
 }
 
+bool QScriptEnginePrivate::isDate(JSValueRef value) const
+{
+    return m_originalGlobalObject.isDate(value);
+}
+
+bool QScriptEnginePrivate::isArray(JSValueRef value) const
+{
+    return m_originalGlobalObject.isArray(value);
+}
+
+bool QScriptEnginePrivate::isError(JSValueRef value) const
+{
+    return m_originalGlobalObject.isError(value);
+}
+
+inline bool QScriptEnginePrivate::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const
+{
+    // FIXME We need a JSC C API function for this.
+    return m_originalGlobalObject.objectHasOwnProperty(object, property);
+}
+
+inline QVector<JSStringRef> QScriptEnginePrivate::objectGetOwnPropertyNames(JSObjectRef object) const
+{
+    // FIXME We can't use C API function JSObjectGetPropertyNames as it returns only enumerable properties.
+    return m_originalGlobalObject.objectGetOwnPropertyNames(object);
+}
+
 #endif
diff --git a/qt/api/qscriptfunction.cpp b/qt/api/qscriptfunction.cpp
new file mode 100644 (file)
index 0000000..9fe37e6
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+// Contains the necessary helper structures to make possible expose
+// C/C++ functions to JavaScript environment.
+
+#include "config.h"
+
+#include "qscriptfunction_p.h"
+
+static void qt_NativeFunction_finalize(JSObjectRef object)
+{
+    void* priv = JSObjectGetPrivate(object);
+    delete reinterpret_cast<QNativeFunctionData*>(priv);
+}
+
+static JSValueRef qt_NativeFunction_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    QNativeFunctionData* data = reinterpret_cast<QNativeFunctionData*>(JSObjectGetPrivate(object));
+
+    // TODO: build a QScriptContext and use it in the native call.
+    QScriptContext* scriptContext = 0;
+    Q_UNUSED(context);
+    Q_UNUSED(thisObject);
+    Q_UNUSED(argumentCount);
+    Q_UNUSED(arguments);
+    Q_UNUSED(exception);
+
+    QScriptEnginePrivate* engine = data->engine;
+    QScriptValuePrivate* result = QScriptValuePrivate::get(data->fun(scriptContext, QScriptEnginePrivate::get(engine)));
+    if (!result->isValid()) {
+        qWarning("Invalid value returned from native function, returning undefined value instead.");
+        return engine->makeJSValue(QScriptValue::UndefinedValue);
+    }
+
+    // Make sure that the result will be assigned to the correct engine.
+    if (!result->engine()) {
+        Q_ASSERT(result->isValid());
+        result->assignEngine(engine);
+    } else if (result->engine() != engine) {
+        qWarning("Value from different engine returned from native function, returning undefined value instead.");
+        return engine->makeJSValue(QScriptValue::UndefinedValue);
+    }
+
+    return *result;
+}
+
+JSClassDefinition qt_NativeFunctionClass = {
+    0,                                     // version
+    kJSClassAttributeNoAutomaticPrototype, // attributes
+
+    "",                         // className
+    0,                          // parentClass
+
+    0,                          // staticValues
+    0,                          // staticFunctions
+
+    0,                                // initialize
+    qt_NativeFunction_finalize,       // finalize
+    0,                                // hasProperty
+    0,                                // getProperty
+    0,                                // setProperty
+    0,                                // deleteProperty
+    0,                                // getPropertyNames
+    qt_NativeFunction_callAsFunction, // callAsFunction
+    0,                                // callAsConstructor
+    0,                                // hasInstance
+    0                                 // convertToType
+};
+
+static void qt_NativeFunctionWithArg_finalize(JSObjectRef object)
+{
+    void* priv = JSObjectGetPrivate(object);
+    delete reinterpret_cast<QNativeFunctionWithArgData*>(priv);
+}
+
+static JSValueRef qt_NativeFunctionWithArg_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    QNativeFunctionWithArgData* data = reinterpret_cast<QNativeFunctionWithArgData*>(JSObjectGetPrivate(object));
+
+    // TODO: build a QScriptContext and use it in the native call.
+    QScriptContext* scriptContext = 0;
+    Q_UNUSED(context);
+    Q_UNUSED(thisObject);
+    Q_UNUSED(argumentCount);
+    Q_UNUSED(arguments);
+    Q_UNUSED(exception);
+
+    QScriptEnginePrivate* engine = data->engine;
+    QScriptValuePrivate* result = QScriptValuePrivate::get(data->fun(scriptContext, QScriptEnginePrivate::get(engine), data->arg));
+    if (!result->isValid()) {
+        qWarning("Invalid value returned from native function, returning undefined value instead.");
+        return engine->makeJSValue(QScriptValue::UndefinedValue);
+    }
+
+    // Make sure that the result will be assigned to the correct engine.
+    if (!result->engine()) {
+        Q_ASSERT(result->isValid());
+        result->assignEngine(engine);
+    } else if (result->engine() != engine) {
+        qWarning("Value from different engine returned from native function, returning undefined value instead.");
+        return engine->makeJSValue(QScriptValue::UndefinedValue);
+    }
+
+    return *result;
+}
+
+JSClassDefinition qt_NativeFunctionWithArgClass = {
+    0,                                     // version
+    kJSClassAttributeNoAutomaticPrototype, // attributes
+
+    "",                         // className
+    0,                          // parentClass
+
+    0,                          // staticValues
+    0,                          // staticFunctions
+
+    0,                                       // initialize
+    qt_NativeFunctionWithArg_finalize,       // finalize
+    0,                                       // hasProperty
+    0,                                       // getProperty
+    0,                                       // setProperty
+    0,                                       // deleteProperty
+    0,                                       // getPropertyNames
+    qt_NativeFunctionWithArg_callAsFunction, // callAsFunction
+    0,                                       // callAsConstructor
+    0,                                       // hasInstance
+    0                                        // convertToType
+};
diff --git a/qt/api/qscriptfunction_p.h b/qt/api/qscriptfunction_p.h
new file mode 100644 (file)
index 0000000..65b6046
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptfunction_p_h
+#define qscriptfunction_p_h
+
+#include "config.h"
+
+#include "qscriptengine.h"
+#include "qscriptvalue_p.h"
+
+extern JSClassDefinition qt_NativeFunctionClass;
+extern JSClassDefinition qt_NativeFunctionWithArgClass;
+
+struct QNativeFunctionData
+{
+    QNativeFunctionData(QScriptEnginePrivate* engine, QScriptEngine::FunctionSignature fun)
+        : engine(engine)
+        , fun(fun)
+    {
+    }
+
+    QScriptEnginePrivate* engine;
+    QScriptEngine::FunctionSignature fun;
+};
+
+struct QNativeFunctionWithArgData
+{
+    QNativeFunctionWithArgData(QScriptEnginePrivate* engine, QScriptEngine::FunctionWithArgSignature fun, void* arg)
+        : engine(engine)
+        , fun(fun)
+        , arg(arg)
+    {
+    }
+
+    QScriptEnginePrivate* engine;
+    QScriptEngine::FunctionWithArgSignature fun;
+    void* arg;
+};
+
+#endif
diff --git a/qt/api/qscriptoriginalglobalobject_p.h b/qt/api/qscriptoriginalglobalobject_p.h
new file mode 100644 (file)
index 0000000..2bd945f
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptoriginalglobalobject_p_h
+#define qscriptoriginalglobalobject_p_h
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <QtCore/qvector.h>
+
+/*!
+    \internal
+    This class is a workaround for missing JSC C API functionality. This class keeps all important
+    properties of an original (default) global object, so we can use it even if the global object was
+    changed.
+
+    FIXME this class is a container for workarounds :-) it should be replaced by proper JSC C API calls.
+
+    The class have to be created on the QScriptEnginePrivate creation time (before any change got applied to
+    global object).
+*/
+class QScriptOriginalGlobalObject {
+public:
+    inline QScriptOriginalGlobalObject(JSGlobalContextRef context);
+    inline ~QScriptOriginalGlobalObject();
+
+    inline bool objectHasOwnProperty(JSObjectRef object, JSStringRef property) const;
+    inline QVector<JSStringRef> objectGetOwnPropertyNames(JSObjectRef object) const;
+
+    inline bool isDate(JSValueRef value) const;
+    inline bool isArray(JSValueRef value) const;
+    inline bool isError(JSValueRef value) const;
+
+    inline JSValueRef functionPrototype() const;
+private:
+    inline bool isType(JSValueRef value, JSObjectRef constructor, JSValueRef prototype) const;
+    inline void initializeMember(JSObjectRef globalObject, JSStringRef prototypeName, const char* type, JSObjectRef& constructor, JSValueRef& prototype);
+
+    // Copy of the global context reference (the same as in QScriptEnginePrivate).
+    JSGlobalContextRef m_context;
+
+    // Copy of constructors and prototypes used in isType functions.
+    JSObjectRef m_arrayConstructor;
+    JSValueRef m_arrayPrototype;
+    JSObjectRef m_errorConstructor;
+    JSValueRef m_errorPrototype;
+    JSObjectRef m_functionConstructor;
+    JSValueRef m_functionPrototype;
+    JSObjectRef m_dateConstructor;
+    JSValueRef m_datePrototype;
+
+    // Reference to standard JS functions that are not exposed by JSC C API.
+    JSObjectRef m_hasOwnPropertyFunction;
+    JSObjectRef m_getOwnPropertyNamesFunction;
+};
+
+QScriptOriginalGlobalObject::QScriptOriginalGlobalObject(JSGlobalContextRef context)
+    : m_context(JSGlobalContextRetain(context))
+{
+    JSObjectRef globalObject = JSContextGetGlobalObject(m_context);
+    JSValueRef exception = 0;
+    JSRetainPtr<JSStringRef> propertyName;
+
+    propertyName.adopt(JSStringCreateWithUTF8CString("prototype"));
+    initializeMember(globalObject, propertyName.get(), "Array", m_arrayConstructor, m_arrayPrototype);
+    initializeMember(globalObject, propertyName.get(), "Error", m_errorConstructor, m_errorPrototype);
+    initializeMember(globalObject, propertyName.get(), "Function", m_functionConstructor, m_functionPrototype);
+    initializeMember(globalObject, propertyName.get(), "Date", m_dateConstructor, m_datePrototype);
+
+    propertyName.adopt(JSStringCreateWithUTF8CString("hasOwnProperty"));
+    m_hasOwnPropertyFunction = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, globalObject, propertyName.get(), &exception));
+    JSValueProtect(m_context, m_hasOwnPropertyFunction);
+    Q_ASSERT(JSValueIsObject(m_context, m_hasOwnPropertyFunction));
+    Q_ASSERT(JSObjectIsFunction(m_context, m_hasOwnPropertyFunction));
+    Q_ASSERT(!exception);
+
+    propertyName.adopt(JSStringCreateWithUTF8CString("Object"));
+    JSObjectRef objectConstructor
+            = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, globalObject, propertyName.get(), &exception));
+    propertyName.adopt(JSStringCreateWithUTF8CString("getOwnPropertyNames"));
+    m_getOwnPropertyNamesFunction
+            = const_cast<JSObjectRef>(JSObjectGetProperty(m_context, objectConstructor, propertyName.get(), &exception));
+    JSValueProtect(m_context, m_getOwnPropertyNamesFunction);
+    Q_ASSERT(JSValueIsObject(m_context, m_getOwnPropertyNamesFunction));
+    Q_ASSERT(JSObjectIsFunction(m_context, m_getOwnPropertyNamesFunction));
+    Q_ASSERT(!exception);
+}
+
+inline void QScriptOriginalGlobalObject::initializeMember(JSObjectRef globalObject, JSStringRef prototypeName, const char* type, JSObjectRef& constructor, JSValueRef& prototype)
+{
+    JSRetainPtr<JSStringRef> typeName(Adopt, JSStringCreateWithUTF8CString(type));
+    JSValueRef exception = 0;
+
+    // Save references to the Type constructor and prototype.
+    JSValueRef typeConstructor = JSObjectGetProperty(m_context, globalObject, typeName.get(), &exception);
+    Q_ASSERT(JSValueIsObject(m_context, typeConstructor));
+    constructor = JSValueToObject(m_context, typeConstructor, &exception);
+    JSValueProtect(m_context, constructor);
+
+    // Note that this is not the [[Prototype]] internal property (which we could
+    // get via JSObjectGetPrototype), but the Type.prototype, that will be set
+    // as [[Prototype]] of Type instances.
+    prototype = JSObjectGetProperty(m_context, constructor, prototypeName, &exception);
+    Q_ASSERT(JSValueIsObject(m_context, prototype));
+    JSValueProtect(m_context, prototype);
+    Q_ASSERT(!exception);
+}
+
+QScriptOriginalGlobalObject::~QScriptOriginalGlobalObject()
+{
+    JSValueUnprotect(m_context, m_arrayConstructor);
+    JSValueUnprotect(m_context, m_arrayPrototype);
+    JSValueUnprotect(m_context, m_errorConstructor);
+    JSValueUnprotect(m_context, m_errorPrototype);
+    JSValueUnprotect(m_context, m_functionConstructor);
+    JSValueUnprotect(m_context, m_functionPrototype);
+    JSValueUnprotect(m_context, m_dateConstructor);
+    JSValueUnprotect(m_context, m_datePrototype);
+    JSValueUnprotect(m_context, m_hasOwnPropertyFunction);
+    JSValueUnprotect(m_context, m_getOwnPropertyNamesFunction);
+    JSGlobalContextRelease(m_context);
+}
+
+inline bool QScriptOriginalGlobalObject::objectHasOwnProperty(JSObjectRef object, JSStringRef property) const
+{
+    // FIXME This function should be replaced by JSC C API.
+    JSValueRef exception = 0;
+    JSValueRef propertyName[] = { JSValueMakeString(m_context, property) };
+    JSValueRef result = JSObjectCallAsFunction(m_context, m_hasOwnPropertyFunction, object, 1, propertyName, &exception);
+    return exception ? false : JSValueToBoolean(m_context, result);
+}
+
+/*!
+    \internal
+    This method gives ownership of all JSStringRefs.
+*/
+inline QVector<JSStringRef> QScriptOriginalGlobalObject::objectGetOwnPropertyNames(JSObjectRef object) const
+{
+    JSValueRef exception = 0;
+    JSObjectRef propertyNames
+            = const_cast<JSObjectRef>(JSObjectCallAsFunction(m_context,
+                                                            m_getOwnPropertyNamesFunction,
+                                                            /* thisObject */ 0,
+                                                            /* argumentCount */ 1,
+                                                            &object,
+                                                            &exception));
+    Q_ASSERT(JSValueIsObject(m_context, propertyNames));
+    Q_ASSERT(!exception);
+    JSStringRef lengthName = QScriptConverter::toString("length");
+    int count = JSValueToNumber(m_context, JSObjectGetProperty(m_context, propertyNames, lengthName, &exception), &exception);
+
+    Q_ASSERT(!exception);
+    QVector<JSStringRef> names;
+    names.reserve(count);
+    for (int i = 0; i < count; ++i) {
+        JSValueRef tmp = JSObjectGetPropertyAtIndex(m_context, propertyNames, i, &exception);
+        names.append(JSValueToStringCopy(m_context, tmp, &exception));
+        Q_ASSERT(!exception);
+    }
+    return names;
+}
+
+inline bool QScriptOriginalGlobalObject::isDate(JSValueRef value) const
+{
+    return isType(value, m_dateConstructor, m_datePrototype);
+}
+
+inline bool QScriptOriginalGlobalObject::isArray(JSValueRef value) const
+{
+    return isType(value, m_arrayConstructor, m_arrayPrototype);
+}
+
+inline bool QScriptOriginalGlobalObject::isError(JSValueRef value) const
+{
+    return isType(value, m_errorConstructor, m_errorPrototype);
+}
+
+inline JSValueRef QScriptOriginalGlobalObject::functionPrototype() const
+{
+    return m_functionPrototype;
+}
+
+inline bool QScriptOriginalGlobalObject::isType(JSValueRef value, JSObjectRef constructor, JSValueRef prototype) const
+{
+    // JSC API doesn't export the [[Class]] information for the builtins. But we know that a value
+    // is an object of the Type if it was created with the Type constructor or if it is the Type.prototype.
+    JSValueRef exception = 0;
+    bool result = JSValueIsInstanceOfConstructor(m_context, value, constructor, &exception) || JSValueIsStrictEqual(m_context, value, prototype);
+    Q_ASSERT(!exception);
+    return result;
+}
+
+#endif // qscriptoriginalglobalobject_p_h
index 6e80e853b79d24407136c7be91891d1c3e79bd88..f6882c54581300abadb85ff95cbab90731e18eed 100644 (file)
@@ -52,7 +52,7 @@ public:
     inline bool operator==(const QScriptProgramPrivate& other) const;
     inline bool operator!=(const QScriptProgramPrivate& other) const;
 
-    inline JSStringRef program() const;
+    inline operator JSStringRef() const;
     inline JSStringRef file() const;
     inline int line() const;
 private:
@@ -122,7 +122,11 @@ bool QScriptProgramPrivate::operator!=(const QScriptProgramPrivate& other) const
             || !JSStringIsEqual(m_program, other.m_program);
 }
 
-JSStringRef QScriptProgramPrivate::program() const { return m_program; }
+QScriptProgramPrivate::operator JSStringRef() const
+{
+    return m_program;
+}
+
 JSStringRef QScriptProgramPrivate::file() const {return m_fileName; }
 int QScriptProgramPrivate::line() const { return m_line; }
 
index d4fc88e3e6b195d0c6950709b37504af5b66abf0..fe84f4dbde04e56b00d22a322192c4b183f617e0 100644 (file)
@@ -46,6 +46,8 @@ public:
 
     inline quint64 id() const;
 
+    inline operator JSStringRef() const;
+
 private:
     JSStringRef m_string;
 };
@@ -109,4 +111,14 @@ quint64 QScriptStringPrivate::id() const
     return reinterpret_cast<quint32>(m_string);
 }
 
+/*!
+    \internal
+    This method should be used for invoking JSC functions.
+    \note This method keeps ownership of an internal JSStringRef.
+*/
+QScriptStringPrivate::operator JSStringRef() const
+{
+    return m_string;
+}
+
 #endif // qscriptstring_p_h
index 5cf02ef74ca942ded8e43a9cf5887db36fc05837..3948c5de37e8937c1c75749ce5f0d3df6329ddab 100644 (file)
@@ -119,7 +119,7 @@ QString QScriptSyntaxCheckResult::errorMessage() const
 QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate()
 {
     if (m_exception)
-        JSValueUnprotect(m_engine->context(), m_exception);
+        JSValueUnprotect(*m_engine, m_exception);
 }
 
 QString QScriptSyntaxCheckResultPrivate::errorMessage() const
@@ -127,7 +127,7 @@ QString QScriptSyntaxCheckResultPrivate::errorMessage() const
     if (!m_exception)
         return QString();
 
-    JSStringRef tmp = JSValueToStringCopy(m_engine->context(), m_exception, /* exception */ 0);
+    JSStringRef tmp = JSValueToStringCopy(*m_engine, m_exception, /* exception */ 0);
     QString message = QScriptConverter::toString(tmp);
     JSStringRelease(tmp);
     return message;
@@ -139,10 +139,10 @@ int QScriptSyntaxCheckResultPrivate::errorLineNumber() const
         return -1;
     // m_exception is an instance of the Exception so it has "line" attribute.
     JSStringRef lineAttrName = QScriptConverter::toString("line");
-    JSValueRef line = JSObjectGetProperty(m_engine->context(),
+    JSValueRef line = JSObjectGetProperty(*m_engine,
                                           m_exception,
                                           lineAttrName,
                                           /* exceptions */0);
     JSStringRelease(lineAttrName);
-    return JSValueToNumber(m_engine->context(), line, /* exceptions */0);
+    return JSValueToNumber(*m_engine, line, /* exceptions */0);
 }
index f692817439274ee5cc1a220e2c84b7ff8d85d5e0..8a7a6c47aac0251f4e7d6fcd15e835d8dd83e7ad 100644 (file)
@@ -312,6 +312,28 @@ bool QScriptValue::isError() const
     return d_ptr->isError();
 }
 
+/*!
+  Returns true if this QScriptValue is an object of the Array class;
+  otherwise returns false.
+
+  \sa QScriptEngine::newArray()
+*/
+bool QScriptValue::isArray() const
+{
+    return d_ptr->isArray();
+}
+
+/*!
+    Returns true if this QScriptValue is an object of the Date class;
+    otherwise returns false.
+
+    \sa QScriptEngine::newDate()
+*/
+bool QScriptValue::isDate() const
+{
+    return d_ptr->isDate();
+}
+
 /*!
   Returns true if this QScriptValue is of the Object type; otherwise
   returns false.
@@ -466,6 +488,28 @@ quint16 QScriptValue::toUInt16() const
     return d_ptr->toUInt16();
 }
 
+/*!
+  \obsolete
+
+  This function is obsolete; use QScriptEngine::toObject() instead.
+*/
+QScriptValue QScriptValue::toObject() const
+{
+    return QScriptValuePrivate::get(d_ptr->toObject());
+}
+
+/*!
+    Returns a QDateTime representation of this value, in local time.
+    If this QScriptValue is not a date, or the value of the date is
+    NaN (Not-a-Number), an invalid QDateTime is returned.
+
+    \sa isDate()
+*/
+QDateTime QScriptValue::toDateTime() const
+{
+    return d_ptr->toDateTime();
+}
+
 /*!
   Calls this QScriptValue as a function, using \a thisObject as
   the `this' object in the function call, and passing \a args
@@ -507,6 +551,34 @@ QScriptEngine* QScriptValue::engine() const
     return 0;
 }
 
+/*!
+  If this QScriptValue is an object, returns the internal prototype
+  (\c{__proto__} property) of this object; otherwise returns an
+  invalid QScriptValue.
+
+  \sa setPrototype(), isObject()
+*/
+QScriptValue QScriptValue::prototype() const
+{
+    return QScriptValuePrivate::get(d_ptr->prototype());
+}
+
+/*!
+  If this QScriptValue is an object, sets the internal prototype
+  (\c{__proto__} property) of this object to be \a prototype;
+  otherwise does nothing.
+
+  The internal prototype should not be confused with the public
+  property with name "prototype"; the public prototype is usually
+  only set on functions that act as constructors.
+
+  \sa prototype(), isObject()
+*/
+void QScriptValue::setPrototype(const QScriptValue& prototype)
+{
+    d_ptr->setPrototype(QScriptValuePrivate::get(prototype));
+}
+
 /*!
   Assigns the \a other value to this QScriptValue.
 
@@ -546,7 +618,7 @@ QScriptValue& QScriptValue::operator=(const QScriptValue& other)
 */
 bool QScriptValue::equals(const QScriptValue& other) const
 {
-    return d_ptr == other.d_ptr || d_ptr->equals(QScriptValuePrivate::get(other));
+    return d_ptr->equals(QScriptValuePrivate::get(other));
 }
 
 /*!
@@ -573,5 +645,158 @@ bool QScriptValue::equals(const QScriptValue& other) const
 */
 bool QScriptValue::strictlyEquals(const QScriptValue& other) const
 {
-    return d_ptr == other.d_ptr || d_ptr->strictlyEquals(QScriptValuePrivate::get(other));
+    return d_ptr->strictlyEquals(QScriptValuePrivate::get(other));
+}
+
+/*!
+    Returns true if this QScriptValue is an instance of
+    \a other; otherwise returns false.
+
+    This QScriptValue is considered to be an instance of \a other if
+    \a other is a function and the value of the \c{prototype}
+    property of \a other is in the prototype chain of this
+    QScriptValue.
+*/
+bool QScriptValue::instanceOf(const QScriptValue& other) const
+{
+    return d_ptr->instanceOf(QScriptValuePrivate::get(other));
+}
+
+/*!
+  Returns the value of this QScriptValue's property with the given \a name,
+  using the given \a mode to resolve the property.
+
+  If no such property exists, an invalid QScriptValue is returned.
+
+  If the property is implemented using a getter function (i.e. has the
+  PropertyGetter flag set), calling property() has side-effects on the
+  script engine, since the getter function will be called (possibly
+  resulting in an uncaught script exception). If an exception
+  occurred, property() returns the value that was thrown (typically
+  an \c{Error} object).
+
+  \sa setProperty(), propertyFlags(), QScriptValueIterator
+*/
+QScriptValue QScriptValue::property(const QString& name, const ResolveFlags& mode) const
+{
+    return QScriptValuePrivate::get(d_ptr->property(name, mode));
+}
+
+/*!
+  \overload
+
+  Returns the value of this QScriptValue's property with the given \a name,
+  using the given \a mode to resolve the property.
+
+  This overload of property() is useful when you need to look up the
+  same property repeatedly, since the lookup can be performed faster
+  when the name is represented as an interned string.
+
+  \sa QScriptEngine::toStringHandle(), setProperty()
+*/
+QScriptValue QScriptValue::property(const QScriptString& name, const ResolveFlags& mode) const
+{
+    return QScriptValuePrivate::get(d_ptr->property(QScriptStringPrivate::get(name).constData(), mode));
+}
+
+/*!
+  \overload
+
+  Returns the property at the given \a arrayIndex, using the given \a
+  mode to resolve the property.
+
+  This function is provided for convenience and performance when
+  working with array objects.
+
+  If this QScriptValue is not an Array object, this function behaves
+  as if property() was called with the string representation of \a
+  arrayIndex.
+*/
+QScriptValue QScriptValue::property(quint32 arrayIndex, const ResolveFlags& mode) const
+{
+    return QScriptValuePrivate::get(d_ptr->property(arrayIndex, mode));
+}
+
+/*!
+  Sets the value of this QScriptValue's property with the given \a name to
+  the given \a value.
+
+  If this QScriptValue is not an object, this function does nothing.
+
+  If this QScriptValue does not already have a property with name \a name,
+  a new property is created; the given \a flags then specify how this
+  property may be accessed by script code.
+
+  If \a value is invalid, the property is removed.
+
+  If the property is implemented using a setter function (i.e. has the
+  PropertySetter flag set), calling setProperty() has side-effects on
+  the script engine, since the setter function will be called with the
+  given \a value as argument (possibly resulting in an uncaught script
+  exception).
+
+  Note that you cannot specify custom getter or setter functions for
+  built-in properties, such as the \c{length} property of Array objects
+  or meta properties of QObject objects.
+
+  \sa property()
+*/
+void QScriptValue::setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags)
+{
+    d_ptr->setProperty(name, QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+  \overload
+
+  Sets the property at the given \a arrayIndex to the given \a value.
+
+  This function is provided for convenience and performance when
+  working with array objects.
+
+  If this QScriptValue is not an Array object, this function behaves
+  as if setProperty() was called with the string representation of \a
+  arrayIndex.
+*/
+void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags)
+{
+    d_ptr->setProperty(arrayIndex, QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+  Sets the value of this QScriptValue's property with the given \a
+  name to the given \a value. The given \a flags specify how this
+  property may be accessed by script code.
+
+  This overload of setProperty() is useful when you need to set the
+  same property repeatedly, since the operation can be performed
+  faster when the name is represented as an interned string.
+
+  \sa QScriptEngine::toStringHandle()
+*/
+void QScriptValue::setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags)
+{
+    d_ptr->setProperty(QScriptStringPrivate::get(name).constData(), QScriptValuePrivate::get(value), flags);
+}
+
+/*!
+  Returns the flags of the property with the given \a name, using the
+  given \a mode to resolve the property.
+
+  \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString& name, const ResolveFlags& mode) const
+{
+    return d_ptr->propertyFlags(name, mode);
+}
+
+/*!
+  Returns the flags of the property with the given \a name, using the
+  given \a mode to resolve the property.
+
+  \sa property()
+*/
+QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString& name, const ResolveFlags& mode) const
+{
+    return d_ptr->propertyFlags(QScriptStringPrivate::get(name).constData(), mode);
 }
index d45aed359f83ff5dacf3387987110422cf53b2e6..bd33849be64a912f3ff891f6e4079acdecb35ea7 100644 (file)
 #ifndef qscriptvalue_h
 #define qscriptvalue_h
 
+#include "qscriptstring.h"
 #include <QtCore/qlist.h>
 #include <QtCore/qshareddata.h>
 
 class QScriptEngine;
 class QScriptValuePrivate;
+class QDateTime;
 
 class QScriptValue;
 typedef QList<QScriptValue> QScriptValueList;
@@ -32,7 +34,27 @@ typedef QList<QScriptValue> QScriptValueList;
 typedef double qsreal;
 
 class QScriptValue {
-public:    
+public:
+    enum ResolveFlag {
+        ResolveLocal        = 0x00,
+        ResolvePrototype    = 0x01,
+        ResolveScope        = 0x02,
+        ResolveFull         = ResolvePrototype | ResolveScope
+    };
+    Q_DECLARE_FLAGS(ResolveFlags, ResolveFlag)
+
+    enum PropertyFlag {
+        ReadOnly            = 0x00000001,
+        Undeletable         = 0x00000002,
+        SkipInEnumeration   = 0x00000004,
+        PropertyGetter      = 0x00000008,
+        PropertySetter      = 0x00000010,
+        QObjectMember       = 0x00000020,
+        KeepExistingFlags   = 0x00000800,
+        UserRange           = 0xff000000 // Users may use these as they see fit.
+    };
+    Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
+
     enum SpecialValue {
         NullValue,
         UndefinedValue
@@ -59,8 +81,24 @@ public:
     ~QScriptValue();
 
     QScriptValue& operator=(const QScriptValue& other);
+
+    QScriptValue prototype() const;
+    void setPrototype(const QScriptValue& prototype);
+
     bool equals(const QScriptValue& other) const;
     bool strictlyEquals(const QScriptValue& other) const;
+    bool instanceOf(const QScriptValue& other) const;
+
+    QScriptValue property(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
+    QScriptValue property(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
+    QScriptValue property(quint32 arrayIndex, const ResolveFlags& mode = ResolvePrototype) const;
+
+    void setProperty(const QString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+    void setProperty(quint32 arrayIndex, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+    void setProperty(const QScriptString& name, const QScriptValue& value, const PropertyFlags& flags = KeepExistingFlags);
+
+    PropertyFlags propertyFlags(const QString& name, const ResolveFlags& mode = ResolvePrototype) const;
+    PropertyFlags propertyFlags(const QScriptString& name, const ResolveFlags& mode = ResolvePrototype) const;
 
     QScriptEngine* engine() const;
 
@@ -74,6 +112,8 @@ public:
     bool isUndefined() const;
     bool isObject() const;
     bool isError() const;
+    bool isArray() const;
+    bool isDate() const;
 
     QString toString() const;
     qsreal toNumber() const;
@@ -83,10 +123,11 @@ public:
     qint32 toInt32() const;
     quint32 toUInt32() const;
     quint16 toUInt16() const;
+    QScriptValue toObject() const;
+    QDateTime toDateTime() const;
 
     QScriptValue call(const QScriptValue& thisObject = QScriptValue(),
                       const QScriptValueList& args = QScriptValueList());
-
 private:
     QScriptValue(void*);
     QScriptValue(QScriptValuePrivate*);
index 03e8621a3ef3fa90f1c468d10b9940baedeb5221..f98a06a61c1365d7f4ddfb746cff3d829a0bd6c6 100644 (file)
@@ -25,6 +25,8 @@
 #include "qscriptvalue.h"
 #include <JavaScriptCore/JavaScript.h>
 #include <JavaScriptCore/JSRetainPtr.h>
+#include <JSObjectRefPrivate.h>
+#include <QtCore/qdatetime.h>
 #include <QtCore/qmath.h>
 #include <QtCore/qnumeric.h>
 #include <QtCore/qshareddata.h>
@@ -49,9 +51,9 @@ class QScriptValue;
     CNumber -> QSVP is created from int, uint, double... and no JSC engine has been bind yet. Current
         value is kept in m_number
     CBool -> QSVP is created from bool and no JSC engine has been associated yet. Current value is kept
-        in m_number
-    CSpecial -> QSVP is Undefined or Null, but a JSC engine hasn't been associated yet, current value
-        is kept in m_number (cast of QScriptValue::SpecialValue)
+        in m_bool
+    CNull -> QSVP is null, but a JSC engine hasn't been associated yet.
+    CUndefined -> QSVP is undefined, but a JSC engine hasn't been associated yet.
     JSValue -> QSVP is associated with engine, but there is no information about real type, the state
         have really short live cycle. Normally it is created as a function call result.
     JSPrimitive -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object.
@@ -59,6 +61,10 @@ class QScriptValue;
 
   Each state keep all necessary information to invoke all methods, if not it should be changed to
   a proper state. Changed state shouldn't be reverted.
+
+  The QScriptValuePrivate use the JSC C API directly. The QSVP type is equal to combination of
+  the JSValueRef and the JSObjectRef, and it could be automatically casted to these types by cast
+  operators.
 */
 
 class QScriptValuePrivate : public QSharedData {
@@ -85,7 +91,7 @@ public:
     inline QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value);
 
     inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value);
-    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object);
+    inline QScriptValuePrivate(const QScriptEnginePrivate* engine, JSObjectRef object);
 
     inline bool isValid() const;
     inline bool isBool();
@@ -96,6 +102,8 @@ public:
     inline bool isError();
     inline bool isObject();
     inline bool isFunction();
+    inline bool isArray();
+    inline bool isDate();
 
     inline QString toString() const;
     inline qsreal toNumber() const;
@@ -105,15 +113,46 @@ public:
     inline quint32 toUInt32() const;
     inline quint16 toUInt16() const;
 
+    inline QScriptValuePrivate* toObject(QScriptEnginePrivate* engine);
+    inline QScriptValuePrivate* toObject();
+    inline QDateTime toDateTime();
+    inline QScriptValuePrivate* prototype();
+    inline void setPrototype(QScriptValuePrivate* prototype);
+
     inline bool equals(QScriptValuePrivate* other);
-    inline bool strictlyEquals(const QScriptValuePrivate* other) const;
+    inline bool strictlyEquals(QScriptValuePrivate* other);
+    inline bool instanceOf(QScriptValuePrivate* other);
     inline bool assignEngine(QScriptEnginePrivate* engine);
 
+    inline QScriptValuePrivate* property(const QString& name, const QScriptValue::ResolveFlags& mode);
+    inline QScriptValuePrivate* property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
+    inline QScriptValuePrivate* property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode);
+    inline JSValueRef property(quint32 property, JSValueRef* exception);
+    inline JSValueRef property(JSStringRef property, JSValueRef* exception);
+    inline bool hasOwnProperty(quint32 property);
+    inline bool hasOwnProperty(JSStringRef property);
+    template<typename T>
+    inline QScriptValuePrivate* property(T name, const QScriptValue::ResolveFlags& mode);
+
+    inline void setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+    inline void setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+    inline void setProperty(const quint32 indexArray, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+    inline void setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
+    inline void setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception);
+    inline void deleteProperty(quint32 property, JSValueRef* exception);
+    inline void deleteProperty(JSStringRef property, JSValueRef* exception);
+    template<typename T>
+    inline void setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags);
+
+    QScriptValue::PropertyFlags propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode);
+    QScriptValue::PropertyFlags propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode);
+    QScriptValue::PropertyFlags propertyFlags(const JSStringRef name, const QScriptValue::ResolveFlags& mode);
+
     inline QScriptValuePrivate* call(const QScriptValuePrivate* , const QScriptValueList& args);
 
-    inline JSGlobalContextRef context() const;
-    inline JSValueRef value() const;
-    inline JSObjectRef object() const;
+    inline operator JSValueRef() const;
+    inline operator JSObjectRef() const;
+
     inline QScriptEnginePrivate* engine() const;
 
 private:
@@ -123,20 +162,31 @@ private:
         CString = 0x1000,
         CNumber,
         CBool,
-        CSpecial,
+        CNull,
+        CUndefined,
         JSValue = 0x2000, // JS values are equal or higher then this value.
         JSPrimitive,
         JSObject
     } m_state;
     QScriptEnginePtr m_engine;
-    QString m_string;
-    qsreal m_number;
-    JSValueRef m_value;
-    JSObjectRef m_object;
+    union Value
+    {
+        bool m_bool;
+        qsreal m_number;
+        JSValueRef m_value;
+        JSObjectRef m_object;
+        QString* m_string;
+
+        Value() : m_number(0) {}
+        Value(bool value) : m_bool(value) {}
+        Value(int number) : m_number(number) {}
+        Value(uint number) : m_number(number) {}
+        Value(qsreal number) : m_number(number) {}
+        Value(JSValueRef value) : m_value(value) {}
+        Value(JSObjectRef object) : m_object(object) {}
+        Value(QString* string) : m_string(string) {}
+    } u;
 
-    inline void setValue(JSValueRef);
-
-    inline bool inherits(const char*);
     inline State refinedJSValue();
 
     inline bool isJSBased() const;
@@ -158,132 +208,124 @@ QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
 
 QScriptValuePrivate::~QScriptValuePrivate()
 {
-    if (m_value)
-        JSValueUnprotect(context(), m_value);
+    if (isJSBased())
+        JSValueUnprotect(*m_engine, u.m_value);
+    else if (isStringBased())
+        delete u.m_string;
 }
 
 QScriptValuePrivate::QScriptValuePrivate()
     : m_state(Invalid)
-    , m_value(0)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QString& string)
     : m_state(CString)
-    , m_string(string)
-    , m_value(0)
+    , u(new QString(string))
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(bool value)
     : m_state(CBool)
-    , m_number(value)
-    , m_value(0)
+    , u(value)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(int number)
     : m_state(CNumber)
-    , m_number(number)
-    , m_value(0)
+    , u(number)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(uint number)
     : m_state(CNumber)
-    , m_number(number)
-    , m_value(0)
+    , u(number)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(qsreal number)
     : m_state(CNumber)
-    , m_number(number)
-    , m_value(0)
+    , u(number)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
-    : m_state(CSpecial)
-    , m_number(value)
-    , m_value(0)
+    : m_state(value == QScriptValue::NullValue ? CNull : CUndefined)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, bool value)
     : m_state(JSPrimitive)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(engine->makeJSValue(value))
+    , u(engine->makeJSValue(value))
 {
     Q_ASSERT(engine);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, int value)
     : m_state(JSPrimitive)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(m_engine->makeJSValue(value))
+    , u(m_engine->makeJSValue(value))
 {
     Q_ASSERT(engine);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, uint value)
     : m_state(JSPrimitive)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(m_engine->makeJSValue(value))
+    , u(m_engine->makeJSValue(value))
 {
     Q_ASSERT(engine);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, qsreal value)
     : m_state(JSPrimitive)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(m_engine->makeJSValue(value))
+    , u(m_engine->makeJSValue(value))
 {
     Q_ASSERT(engine);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, const QString& value)
     : m_state(JSPrimitive)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(m_engine->makeJSValue(value))
+    , u(m_engine->makeJSValue(value))
 {
     Q_ASSERT(engine);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, QScriptValue::SpecialValue value)
     : m_state(JSPrimitive)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(m_engine->makeJSValue(value))
+    , u(m_engine->makeJSValue(value))
 {
     Q_ASSERT(engine);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value)
     : m_state(JSValue)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(value)
+    , u(value)
 {
     Q_ASSERT(engine);
     Q_ASSERT(value);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, u.m_value);
 }
 
-QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSValueRef value, JSObjectRef object)
+QScriptValuePrivate::QScriptValuePrivate(const QScriptEnginePrivate* engine, JSObjectRef object)
     : m_state(JSObject)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(value)
-    , m_object(object)
+    , u(object)
 {
     Q_ASSERT(engine);
-    Q_ASSERT(value);
     Q_ASSERT(object);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, object);
 }
 
 bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
@@ -298,7 +340,7 @@ bool QScriptValuePrivate::isBool()
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsBoolean(context(), value());
+        return JSValueIsBoolean(*m_engine, *this);
     default:
         return false;
     }
@@ -314,7 +356,7 @@ bool QScriptValuePrivate::isNumber()
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsNumber(context(), value());
+        return JSValueIsNumber(*m_engine, *this);
     default:
         return false;
     }
@@ -323,14 +365,14 @@ bool QScriptValuePrivate::isNumber()
 bool QScriptValuePrivate::isNull()
 {
     switch (m_state) {
-    case CSpecial:
-        return m_number == static_cast<int>(QScriptValue::NullValue);
+    case CNull:
+        return true;
     case JSValue:
         if (refinedJSValue() != JSPrimitive)
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsNull(context(), value());
+        return JSValueIsNull(*m_engine, *this);
     default:
         return false;
     }
@@ -346,7 +388,7 @@ bool QScriptValuePrivate::isString()
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsString(context(), value());
+        return JSValueIsString(*m_engine, *this);
     default:
         return false;
     }
@@ -355,14 +397,14 @@ bool QScriptValuePrivate::isString()
 bool QScriptValuePrivate::isUndefined()
 {
     switch (m_state) {
-    case CSpecial:
-        return m_number == static_cast<int>(QScriptValue::UndefinedValue);
+    case CUndefined:
+        return true;
     case JSValue:
         if (refinedJSValue() != JSPrimitive)
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsUndefined(context(), value());
+        return JSValueIsUndefined(*m_engine, *this);
     default:
         return false;
     }
@@ -376,7 +418,7 @@ bool QScriptValuePrivate::isError()
             return false;
         // Fall-through.
     case JSObject:
-        return inherits("Error");
+        return m_engine->isError(*this);
     default:
         return false;
     }
@@ -403,7 +445,35 @@ bool QScriptValuePrivate::isFunction()
             return false;
         // Fall-through.
     case JSObject:
-        return JSObjectIsFunction(context(), object());
+        return JSObjectIsFunction(*m_engine, *this);
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isArray()
+{
+    switch (m_state) {
+    case JSValue:
+        if (refinedJSValue() != JSObject)
+            return false;
+        // Fall-through.
+    case JSObject:
+        return m_engine->isArray(*this);
+    default:
+        return false;
+    }
+}
+
+bool QScriptValuePrivate::isDate()
+{
+    switch (m_state) {
+    case JSValue:
+        if (refinedJSValue() != JSObject)
+            return false;
+        // Fall-through.
+    case JSObject:
+        return m_engine->isDate(*this);
     default:
         return false;
     }
@@ -415,17 +485,21 @@ QString QScriptValuePrivate::toString() const
     case Invalid:
         return QString();
     case CBool:
-        return m_number ? QString::fromLatin1("true") : QString::fromLatin1("false");
+        return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false");
     case CString:
-        return m_string;
+        return *u.m_string;
     case CNumber:
-        return QScriptConverter::toString(m_number);
-    case CSpecial:
-        return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined");
+        return QScriptConverter::toString(u.m_number);
+    case CNull:
+        return QString::fromLatin1("null");
+    case CUndefined:
+        return QString::fromLatin1("undefined");
     case JSValue:
     case JSPrimitive:
     case JSObject:
-        JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(context(), value(), /* exception */ 0));
+        JSValueRef exception = 0;
+        JSRetainPtr<JSStringRef> ptr(Adopt, JSValueToStringCopy(*m_engine, *this, &exception));
+        m_engine->setException(exception);
         return QScriptConverter::toString(ptr.get());
     }
 
@@ -439,26 +513,32 @@ qsreal QScriptValuePrivate::toNumber() const
     case JSValue:
     case JSPrimitive:
     case JSObject:
-        return JSValueToNumber(context(), value(), /* exception */ 0);
+        {
+            JSValueRef exception = 0;
+            qsreal result = JSValueToNumber(*m_engine, *this, &exception);
+            m_engine->setException(exception);
+            return result;
+        }
     case CNumber:
-        return m_number;
+        return u.m_number;
     case CBool:
-        return m_number ? 1 : 0;
+        return u.m_bool ? 1 : 0;
+    case CNull:
     case Invalid:
         return 0;
-    case CSpecial:
-        return m_number == QScriptValue::NullValue ? 0 : qQNaN();
+    case CUndefined:
+        return qQNaN();
     case CString:
         bool ok;
-        qsreal result = m_string.toDouble(&ok);
+        qsreal result = u.m_string->toDouble(&ok);
         if (ok)
             return result;
-        result = m_string.toInt(&ok, 0); // Try other bases.
+        result = u.m_string->toInt(&ok, 0); // Try other bases.
         if (ok)
             return result;
-        if (m_string == "Infinity" || m_string == "-Infinity")
+        if (*u.m_string == "Infinity" || *u.m_string == "-Infinity")
             return qInf();
-        return m_string.length() ? qQNaN() : 0;
+        return u.m_string->length() ? qQNaN() : 0;
     }
 
     Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement.");
@@ -470,18 +550,19 @@ bool QScriptValuePrivate::toBool() const
     switch (m_state) {
     case JSValue:
     case JSPrimitive:
-        return JSValueToBoolean(context(), value());
+        return JSValueToBoolean(*m_engine, *this);
     case JSObject:
         return true;
     case CNumber:
-        return !(qIsNaN(m_number) || !m_number);
+        return !(qIsNaN(u.m_number) || !u.m_number);
     case CBool:
-        return m_number;
+        return u.m_bool;
     case Invalid:
-    case CSpecial:
+    case CNull:
+    case CUndefined:
         return false;
     case CString:
-        return m_string.length();
+        return u.m_string->length();
     }
 
     Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement.");
@@ -523,16 +604,176 @@ quint16 QScriptValuePrivate::toUInt16() const
     return toInt32();
 }
 
+/*!
+  Creates a copy of this value and converts it to an object. If this value is an object
+  then pointer to this value will be returned.
+  \attention it should not happen but if this value is bounded to a different engine that the given, the first
+  one will be used.
+  \internal
+  */
+QScriptValuePrivate* QScriptValuePrivate::toObject(QScriptEnginePrivate* engine)
+{
+    switch (m_state) {
+    case Invalid:
+    case CNull:
+    case CUndefined:
+        return new QScriptValuePrivate;
+    case CString:
+        {
+            // Exception can't occur here.
+            JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(*u.m_string), /* exception */ 0);
+            Q_ASSERT(object);
+            return new QScriptValuePrivate(engine, object);
+        }
+    case CNumber:
+        {
+            // Exception can't occur here.
+            JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(u.m_number), /* exception */ 0);
+            Q_ASSERT(object);
+            return new QScriptValuePrivate(engine, object);
+        }
+    case CBool:
+        {
+            // Exception can't occure here.
+            JSObjectRef object = JSValueToObject(*engine, engine->makeJSValue(u.m_bool), /* exception */ 0);
+            Q_ASSERT(object);
+            return new QScriptValuePrivate(engine, object);
+        }
+    case JSValue:
+        if (refinedJSValue() != JSPrimitive)
+            break;
+        // Fall-through.
+    case JSPrimitive:
+        {
+            if (engine != this->engine())
+                qWarning("QScriptEngine::toObject: cannot convert value created in a different engine");
+            JSValueRef exception = 0;
+            JSObjectRef object = JSValueToObject(*m_engine, *this, &exception);
+            if (object)
+                return new QScriptValuePrivate(m_engine.constData(), object);
+            else
+                m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
+
+        }
+        return new QScriptValuePrivate;
+    case JSObject:
+        break;
+    }
+
+    if (engine != this->engine())
+        qWarning("QScriptEngine::toObject: cannot convert value created in a different engine");
+    Q_ASSERT(m_state == JSObject);
+    return this;
+}
+
+/*!
+  This method is created only for QScriptValue::toObject() purpose which is obsolete.
+  \internal
+ */
+QScriptValuePrivate* QScriptValuePrivate::toObject()
+{
+    if (isJSBased())
+        return toObject(m_engine.data());
+
+    // Without an engine there is not much we can do.
+    return new QScriptValuePrivate;
+}
+
+QDateTime QScriptValuePrivate::toDateTime()
+{
+    if (!isDate())
+        return QDateTime();
+
+    JSValueRef exception = 0;
+    qsreal t = JSValueToNumber(*m_engine, *this, &exception);
+
+    if (exception) {
+        m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
+        return QDateTime();
+    }
+
+    QDateTime result;
+    result.setMSecsSinceEpoch(qint64(t));
+    return result;
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::prototype()
+{
+    if (isObject()) {
+        JSValueRef prototype = JSObjectGetPrototype(*m_engine, *this);
+        if (JSValueIsNull(*m_engine, prototype))
+            return new QScriptValuePrivate(engine(), prototype);
+        // The prototype could be either a null or a JSObject, so it is safe to cast the prototype
+        // to the JSObjectRef here.
+        return new QScriptValuePrivate(engine(), const_cast<JSObjectRef>(prototype));
+    }
+    return new QScriptValuePrivate;
+}
+
+inline void QScriptValuePrivate::setPrototype(QScriptValuePrivate* prototype)
+{
+    if (isObject() && prototype->isValid() && (prototype->isObject() || prototype->isNull())) {
+        if (engine() != prototype->engine()) {
+            qWarning("QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine");
+            return;
+        }
+        // FIXME: This could be replaced by a new, faster API
+        // look at https://bugs.webkit.org/show_bug.cgi?id=40060
+        JSObjectSetPrototype(*m_engine, *this, *prototype);
+        JSValueRef proto = JSObjectGetPrototype(*m_engine, *this);
+        if (!JSValueIsStrictEqual(*m_engine, proto, *prototype))
+            qWarning("QScriptValue::setPrototype() failed: cyclic prototype value");
+    }
+}
 
 bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
 {
-    if (!isValid() || !other->isValid())
+    if (!isValid())
+        return !other->isValid();
+
+    if (!other->isValid())
         return false;
 
-    if ((m_state == other->m_state) && !isJSBased()) {
-        if (isNumberBased())
-            return m_number == other->m_number;
-        return m_string == other->m_string;
+    if (!isJSBased() && !other->isJSBased()) {
+        switch (m_state) {
+        case CNull:
+        case CUndefined:
+            return other->isUndefined() || other->isNull();
+        case CNumber:
+            switch (other->m_state) {
+            case CBool:
+            case CString:
+                return u.m_number == other->toNumber();
+            case CNumber:
+                return u.m_number == other->u.m_number;
+            default:
+                return false;
+            }
+        case CBool:
+            switch (other->m_state) {
+            case CBool:
+                return u.m_bool == other->u.m_bool;
+            case CNumber:
+                return toNumber() == other->u.m_number;
+            case CString:
+                return toNumber() == other->toNumber();
+            default:
+                return false;
+            }
+        case CString:
+            switch (other->m_state) {
+            case CBool:
+                return toNumber() == other->toNumber();
+            case CNumber:
+                return toNumber() == other->u.m_number;
+            case CString:
+                return *u.m_string == *other->u.m_string;
+            default:
+                return false;
+            }
+        default:
+            Q_ASSERT_X(false, "equals()", "Not all states are included in the previous switch statement.");
+        }
     }
 
     if (isJSBased() && !other->isJSBased()) {
@@ -541,32 +782,63 @@ bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
             return false;
         }
     } else if (!isJSBased() && other->isJSBased()) {
-        if (!other->assignEngine(other->engine())) {
+        if (!assignEngine(other->engine())) {
             qWarning("equals(): Cannot compare to a value created in a different engine");
             return false;
         }
     }
 
-    return JSValueIsEqual(context(), value(), other->value(), /* exception */ 0);
+    JSValueRef exception = 0;
+    bool result = JSValueIsEqual(*m_engine, *this, *other, &exception);
+    m_engine->setException(exception);
+    return result;
 }
 
-bool QScriptValuePrivate::strictlyEquals(const QScriptValuePrivate* other) const
+bool QScriptValuePrivate::strictlyEquals(QScriptValuePrivate* other)
 {
-    if (m_state != other->m_state)
-        return false;
     if (isJSBased()) {
+        // We can't compare these two values without binding to the same engine.
+        if (!other->isJSBased()) {
+            if (other->assignEngine(engine()))
+                return JSValueIsStrictEqual(*m_engine, *this, *other);
+            return false;
+        }
         if (other->engine() != engine()) {
             qWarning("strictlyEquals(): Cannot compare to a value created in a different engine");
             return false;
         }
-        return JSValueIsStrictEqual(context(), value(), other->value());
+        return JSValueIsStrictEqual(*m_engine, *this, *other);
     }
-    if (isStringBased())
-        return m_string == other->m_string;
-    if (isNumberBased())
-        return m_number == other->m_number;
+    if (isStringBased()) {
+        if (other->isStringBased())
+            return *u.m_string == *(other->u.m_string);
+        if (other->isJSBased()) {
+            assignEngine(other->engine());
+            return JSValueIsStrictEqual(*m_engine, *this, *other);
+        }
+    }
+    if (isNumberBased()) {
+        if (other->isNumberBased())
+            return u.m_number == other->u.m_number;
+        if (other->isJSBased()) {
+            assignEngine(other->engine());
+            return JSValueIsStrictEqual(*m_engine, *this, *other);
+        }
+    }
+    if (!isValid() && !other->isValid())
+        return true;
+
+    return false;
+}
 
-    return false; // Invalid state.
+inline bool QScriptValuePrivate::instanceOf(QScriptValuePrivate* other)
+{
+    if (!isJSBased() || !other->isObject())
+        return false;
+    JSValueRef exception = 0;
+    bool result = JSValueIsInstanceOfConstructor(*m_engine, *this, *other, &exception);
+    m_engine->setException(exception);
+    return result;
 }
 
 /*!
@@ -574,19 +846,24 @@ bool QScriptValuePrivate::strictlyEquals(const QScriptValuePrivate* other) const
 */
 bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
 {
+    Q_ASSERT(engine);
     JSValueRef value;
     switch (m_state) {
     case CBool:
-        value = engine->makeJSValue(static_cast<bool>(m_number));
+        value = engine->makeJSValue(u.m_bool);
         break;
     case CString:
-        value = engine->makeJSValue(m_string);
+        value = engine->makeJSValue(*u.m_string);
+        delete u.m_string;
         break;
     case CNumber:
-        value = engine->makeJSValue(m_number);
+        value = engine->makeJSValue(u.m_number);
         break;
-    case CSpecial:
-        value = engine->makeJSValue(static_cast<QScriptValue::SpecialValue>(m_number));
+    case CNull:
+        value = engine->makeJSValue(QScriptValue::NullValue);
+        break;
+    case CUndefined:
+        value = engine->makeJSValue(QScriptValue::UndefinedValue);
         break;
     default:
         if (!isJSBased())
@@ -597,10 +874,255 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
     }
     m_engine = engine;
     m_state = JSPrimitive;
-    setValue(value);
+    u.m_value = value;
+    JSValueProtect(*m_engine, value);
     return true;
 }
 
+inline QScriptValuePrivate* QScriptValuePrivate::property(const QString& name, const QScriptValue::ResolveFlags& mode)
+{
+    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+    return property<JSStringRef>(propertyName.get(), mode);
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::property(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
+{
+    return property<JSStringRef>(*name, mode);
+}
+
+inline QScriptValuePrivate* QScriptValuePrivate::property(quint32 arrayIndex, const QScriptValue::ResolveFlags& mode)
+{
+    return property<quint32>(arrayIndex, mode);
+}
+
+/*!
+    \internal
+    This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
+*/
+inline JSValueRef QScriptValuePrivate::property(quint32 property, JSValueRef* exception)
+{
+    return JSObjectGetPropertyAtIndex(*m_engine, *this, property, exception);
+}
+
+/*!
+    \internal
+    This method was created to unify access to the JSObjectGetPropertyAtIndex and the JSObjectGetProperty.
+*/
+inline JSValueRef QScriptValuePrivate::property(JSStringRef property, JSValueRef* exception)
+{
+    return JSObjectGetProperty(*m_engine, *this, property, exception);
+}
+
+/*!
+    \internal
+    This method was created to unify acccess to hasOwnProperty, same function for an array index
+    and a property name access.
+*/
+inline bool QScriptValuePrivate::hasOwnProperty(quint32 property)
+{
+    Q_ASSERT(isObject());
+    // FIXME it could be faster, but JSC C API doesn't expose needed functionality.
+    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+    return hasOwnProperty(propertyName.get());
+}
+
+/*!
+    \internal
+    This method was created to unify acccess to hasOwnProperty, same function for an array index
+    and a property name access.
+*/
+inline bool QScriptValuePrivate::hasOwnProperty(JSStringRef property)
+{
+    Q_ASSERT(isObject());
+    return m_engine->objectHasOwnProperty(*this, property);
+}
+
+/*!
+    \internal
+    This function gets property of an object.
+    \arg propertyName could be type of quint32 (an array index) or JSStringRef (a property name).
+*/
+template<typename T>
+inline QScriptValuePrivate* QScriptValuePrivate::property(T propertyName, const QScriptValue::ResolveFlags& mode)
+{
+    if (!isObject())
+        return new QScriptValuePrivate();
+
+    if ((mode == QScriptValue::ResolveLocal) && (!hasOwnProperty(propertyName)))
+        return new QScriptValuePrivate();
+
+    JSValueRef exception = 0;
+    JSValueRef value = property(propertyName, &exception);
+
+    if (exception) {
+        m_engine->setException(exception, QScriptEnginePrivate::NotNullException);
+        return new QScriptValuePrivate(engine(), exception);
+    }
+    if (JSValueIsUndefined(*m_engine, value))
+        return new QScriptValuePrivate;
+    return new QScriptValuePrivate(engine(), value);
+}
+
+inline void QScriptValuePrivate::setProperty(const QString& name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+    setProperty<JSStringRef>(propertyName.get(), value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(quint32 arrayIndex, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+    setProperty<quint32>(arrayIndex, value, flags);
+}
+
+inline void QScriptValuePrivate::setProperty(const QScriptStringPrivate* name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+    setProperty<JSStringRef>(*name, value, flags);
+}
+
+/*!
+    \internal
+    This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
+*/
+inline void QScriptValuePrivate::setProperty(quint32 property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
+{
+    Q_ASSERT(isObject());
+    if (flags) {
+        // FIXME This could be better, but JSC C API doesn't expose needed functionality. It is
+        // not possible to create / modify a property attribute via an array index.
+        JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+        JSObjectSetProperty(*m_engine, *this, propertyName.get(), value, flags, exception);
+        return;
+    }
+    JSObjectSetPropertyAtIndex(*m_engine, *this, property, value, exception);
+}
+
+/*!
+    \internal
+    This method was created to unify access to the JSObjectSetPropertyAtIndex and the JSObjectSetProperty.
+*/
+inline void QScriptValuePrivate::setProperty(JSStringRef property, JSValueRef value, JSPropertyAttributes flags, JSValueRef* exception)
+{
+    Q_ASSERT(isObject());
+    JSObjectSetProperty(*m_engine, *this, property, value, flags, exception);
+}
+
+/*!
+    \internal
+    This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex
+    which doesn't exist now.
+*/
+inline void QScriptValuePrivate::deleteProperty(quint32 property, JSValueRef* exception)
+{
+    // FIXME It could be faster, we need a JSC C API for deleting array index properties.
+    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(QString::number(property)));
+    JSObjectDeleteProperty(*m_engine, *this, propertyName.get(), exception);
+}
+
+/*!
+    \internal
+    This method was created to unify access to the JSObjectDeleteProperty and a teoretical JSObjectDeletePropertyAtIndex.
+*/
+inline void QScriptValuePrivate::deleteProperty(JSStringRef property, JSValueRef* exception)
+{
+    Q_ASSERT(isObject());
+    JSObjectDeleteProperty(*m_engine, *this, property, exception);
+}
+
+template<typename T>
+inline void QScriptValuePrivate::setProperty(T name, QScriptValuePrivate* value, const QScriptValue::PropertyFlags& flags)
+{
+    if (!isObject())
+        return;
+
+    if (!value->isJSBased())
+        value->assignEngine(engine());
+
+    JSValueRef exception = 0;
+    if (!value->isValid()) {
+        // Remove the property.
+        deleteProperty(name, &exception);
+        m_engine->setException(exception);
+        return;
+    }
+    if (m_engine != value->m_engine) {
+        qWarning("QScriptValue::setProperty() failed: cannot set value created in a different engine");
+        return;
+    }
+
+    setProperty(name, *value, QScriptConverter::toPropertyFlags(flags), &exception);
+    m_engine->setException(exception);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QString& name, const QScriptValue::ResolveFlags& mode)
+{
+    JSRetainPtr<JSStringRef> propertyName(Adopt, QScriptConverter::toString(name));
+    return propertyFlags(propertyName.get(), mode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const QScriptStringPrivate* name, const QScriptValue::ResolveFlags& mode)
+{
+    return propertyFlags(*name, mode);
+}
+
+inline QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(JSStringRef name, const QScriptValue::ResolveFlags& mode)
+{
+    unsigned flags = 0;
+    if (!isObject())
+        return QScriptValue::PropertyFlags(flags);
+
+    // FIXME It could be faster and nicer, but new JSC C API should be created.
+    static JSStringRef objectName = QScriptConverter::toString("Object");
+    static JSStringRef propertyDescriptorName = QScriptConverter::toString("getOwnPropertyDescriptor");
+
+    // FIXME This is dangerous if global object was modified (bug 41839).
+    JSValueRef exception = 0;
+    JSObjectRef globalObject = JSContextGetGlobalObject(*m_engine);
+    JSValueRef objectConstructor = JSObjectGetProperty(*m_engine, globalObject, objectName, &exception);
+    Q_ASSERT(JSValueIsObject(*m_engine, objectConstructor));
+    JSValueRef propertyDescriptorGetter = JSObjectGetProperty(*m_engine, const_cast<JSObjectRef>(objectConstructor), propertyDescriptorName, &exception);
+    Q_ASSERT(JSValueIsObject(*m_engine, propertyDescriptorGetter));
+
+    JSValueRef arguments[] = { *this, JSValueMakeString(*m_engine, name) };
+    JSObjectRef propertyDescriptor
+            = const_cast<JSObjectRef>(JSObjectCallAsFunction(*m_engine,
+                                                            const_cast<JSObjectRef>(propertyDescriptorGetter),
+                                                            /* thisObject */ 0,
+                                                            /* argumentCount */ 2,
+                                                            arguments,
+                                                            &exception));
+    if (exception) {
+        // Invalid property.
+        return QScriptValue::PropertyFlags(flags);
+    }
+
+    if (!JSValueIsObject(*m_engine, propertyDescriptor)) {
+        // Property isn't owned by this object.
+        JSObjectRef proto;
+        if (mode == QScriptValue::ResolveLocal
+                || ((proto = const_cast<JSObjectRef>(JSObjectGetPrototype(*m_engine, *this))) && JSValueIsNull(*m_engine, proto))) {
+            return QScriptValue::PropertyFlags(flags);
+        }
+        QScriptValuePrivate p(engine(), proto);
+        return p.propertyFlags(name, QScriptValue::ResolvePrototype);
+    }
+
+    static JSStringRef writableName = QScriptConverter::toString("writable");
+    static JSStringRef configurableName = QScriptConverter::toString("configurable");
+    static JSStringRef enumerableName = QScriptConverter::toString("enumerable");
+
+    bool readOnly = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, writableName, &exception));
+    if (!exception && readOnly)
+        flags |= QScriptValue::ReadOnly;
+    bool undeletable = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, configurableName, &exception));
+    if (!exception && undeletable)
+        flags |= QScriptValue::Undeletable;
+    bool skipInEnum = !JSValueToBoolean(*m_engine, JSObjectGetProperty(*m_engine, propertyDescriptor, enumerableName, &exception));
+    if (!exception && skipInEnum)
+        flags |= QScriptValue::SkipInEnumeration;
+
+    return QScriptValue::PropertyFlags(flags);
+}
+
 QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const QScriptValueList& args)
 {
     switch (m_state) {
@@ -620,14 +1142,16 @@ QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const
                     qWarning("QScriptValue::call() failed: cannot call function with values created in a different engine");
                     return new QScriptValuePrivate;
                 }
-                argv[j] = value->value();
+                argv[j] = *value;
             }
 
             // Make the call
             JSValueRef exception = 0;
-            JSValueRef result = JSObjectCallAsFunction(context(), object(), /* thisObject */ 0, argc, argv.constData(), &exception);
-            if (!result && exception)
+            JSValueRef result = JSObjectCallAsFunction(*m_engine, *this, /* thisObject */ 0, argc, argv.constData(), &exception);
+            if (!result && exception) {
+                m_engine->setException(exception);
                 return new QScriptValuePrivate(engine(), exception);
+            }
             if (result && !exception)
                 return new QScriptValuePrivate(engine(), result);
         }
@@ -644,46 +1168,18 @@ QScriptEnginePrivate* QScriptValuePrivate::engine() const
     return m_engine.data();
 }
 
-JSGlobalContextRef QScriptValuePrivate::context() const
-{
-    Q_ASSERT(isJSBased());
-    return m_engine->context();
-}
-
-JSValueRef QScriptValuePrivate::value() const
+QScriptValuePrivate::operator JSValueRef() const
 {
     Q_ASSERT(isJSBased());
-    return m_value;
+    Q_ASSERT(u.m_value);
+    return u.m_value;
 }
 
-JSObjectRef QScriptValuePrivate::object() const
+QScriptValuePrivate::operator JSObjectRef() const
 {
     Q_ASSERT(m_state == JSObject);
-    return m_object;
-}
-
-void QScriptValuePrivate::setValue(JSValueRef value)
-{
-    if (m_value)
-        JSValueUnprotect(context(), m_value);
-    if (value)
-        JSValueProtect(context(), value);
-    m_value = value;
-}
-
-/*!
-  \internal
-  Returns true if QSV is created from constructor with the given \a name, it has to be a
-  built-in type.
-*/
-bool QScriptValuePrivate::inherits(const char* name)
-{
-    Q_ASSERT(isJSBased());
-    JSObjectRef globalObject = JSContextGetGlobalObject(context());
-    JSStringRef errorAttrName = QScriptConverter::toString(name);
-    JSValueRef error = JSObjectGetProperty(context(), globalObject, errorAttrName, /* exception */ 0);
-    JSStringRelease(errorAttrName);
-    return JSValueIsInstanceOfConstructor(context(), value(), JSValueToObject(context(), error, /* exception */ 0), /* exception */ 0);
+    Q_ASSERT(u.m_object);
+    return u.m_object;
 }
 
 /*!
@@ -693,13 +1189,12 @@ bool QScriptValuePrivate::inherits(const char* name)
 QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue()
 {
     Q_ASSERT(m_state == JSValue);
-    if (!JSValueIsObject(context(), value())) {
+    if (!JSValueIsObject(*m_engine, *this)) {
         m_state = JSPrimitive;
     } else {
+        // Difference between JSValueRef and JSObjectRef is only in their type, binarywise it is the same.
+        // As m_value and m_object are stored in the u union, it is enough to change the m_state only.
         m_state = JSObject;
-        // We are sure that value is an JSObject, so we can const_cast safely without
-        // calling JSC C API (JSValueToObject(context(), value(), /* exceptions */ 0)).
-        m_object = const_cast<JSObjectRef>(m_value);
     }
     return m_state;
 }
@@ -714,7 +1209,7 @@ bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; }
   \internal
   Returns true if current value of QSV is placed in m_number.
 */
-bool QScriptValuePrivate::isNumberBased() const { return !isJSBased() && !isStringBased() && m_state != Invalid; }
+bool QScriptValuePrivate::isNumberBased() const { return m_state == CNumber || m_state == CBool; }
 
 /*!
   \internal
diff --git a/qt/api/qscriptvalueiterator.cpp b/qt/api/qscriptvalueiterator.cpp
new file mode 100644 (file)
index 0000000..f1caa61
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include "qscriptvalueiterator.h"
+
+#include "qscriptvalue_p.h"
+#include "qscriptvalueiterator_p.h"
+
+/*!
+    \class QScriptValueIterator
+
+    \brief The QScriptValueIterator class provides a Java-style iterator for QScriptValue.
+
+    \ingroup script
+
+
+    The QScriptValueIterator constructor takes a QScriptValue as
+    argument.  After construction, the iterator is located at the very
+    beginning of the sequence of properties. Here's how to iterate over
+    all the properties of a QScriptValue:
+
+    \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 0
+
+    The next() advances the iterator. The name(), value() and flags()
+    functions return the name, value and flags of the last item that was
+    jumped over.
+
+    If you want to remove properties as you iterate over the
+    QScriptValue, use remove(). If you want to modify the value of a
+    property, use setValue().
+
+    Note that QScriptValueIterator only iterates over the QScriptValue's
+    own properties; i.e. it does not follow the prototype chain. You can
+    use a loop like this to follow the prototype chain:
+
+    \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 1
+
+    Note that QScriptValueIterator will not automatically skip over
+    properties that have the QScriptValue::SkipInEnumeration flag set;
+    that flag only affects iteration in script code.  If you want, you
+    can skip over such properties with code like the following:
+
+    \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 2
+
+    \sa QScriptValue::property()
+*/
+
+/*!
+    Constructs an iterator for traversing \a object. The iterator is
+    set to be at the front of the sequence of properties (before the
+    first property).
+*/
+QScriptValueIterator::QScriptValueIterator(const QScriptValue& object)
+    : d_ptr(new QScriptValueIteratorPrivate(QScriptValuePrivate::get(object)))
+{}
+
+/*!
+    Destroys the iterator.
+*/
+QScriptValueIterator::~QScriptValueIterator()
+{}
+
+/*!
+    Returns true if there is at least one item ahead of the iterator
+    (i.e. the iterator is \e not at the back of the property sequence);
+    otherwise returns false.
+
+    \sa next(), hasPrevious()
+*/
+bool QScriptValueIterator::hasNext() const
+{
+    return d_ptr->hasNext();
+}
+
+/*!
+    Advances the iterator by one position.
+
+    Calling this function on an iterator located at the back of the
+    container leads to undefined results.
+
+    \sa hasNext(), previous(), name()
+*/
+void QScriptValueIterator::next()
+{
+    d_ptr->next();
+}
+
+/*!
+    Returns true if there is at least one item behind the iterator
+    (i.e. the iterator is \e not at the front of the property sequence);
+    otherwise returns false.
+
+    \sa previous(), hasNext()
+*/
+bool QScriptValueIterator::hasPrevious() const
+{
+    return d_ptr->hasPrevious();
+}
+
+/*!
+    Moves the iterator back by one position.
+
+    Calling this function on an iterator located at the front of the
+    container leads to undefined results.
+
+    \sa hasPrevious(), next(), name()
+*/
+void QScriptValueIterator::previous()
+{
+    d_ptr->previous();
+}
+
+/*!
+    Moves the iterator to the front of the QScriptValue (before the
+    first property).
+
+    \sa toBack(), next()
+*/
+void QScriptValueIterator::toFront()
+{
+    d_ptr->toFront();
+}
+
+/*!
+    Moves the iterator to the back of the QScriptValue (after the
+    last property).
+
+    \sa toFront(), previous()
+*/
+void QScriptValueIterator::toBack()
+{
+    d_ptr->toBack();
+}
+
+/*!
+    Returns the name of the last property that was jumped over using
+    next() or previous().
+
+    \sa value(), flags()
+*/
+QString QScriptValueIterator::name() const
+{
+    return d_ptr->name();
+}
+
+/*!
+    Returns the name of the last property that was jumped over using
+    next() or previous().
+*/
+QScriptString QScriptValueIterator::scriptName() const
+{
+    return QScriptStringPrivate::get(d_ptr->scriptName());
+}
+
+/*!
+    Returns the value of the last property that was jumped over using
+    next() or previous().
+
+    \sa setValue(), name()
+*/
+QScriptValue QScriptValueIterator::value() const
+{
+    return QScriptValuePrivate::get(d_ptr->value());
+}
+
+/*!
+    Sets the \a value of the last property that was jumped over using
+    next() or previous().
+
+    \sa value(), name()
+*/
+void QScriptValueIterator::setValue(const QScriptValue& value)
+{
+    d_ptr->setValue(QScriptValuePrivate::get(value));
+}
+
+/*!
+    Removes the last property that was jumped over using next()
+    or previous().
+
+    \sa setValue()
+*/
+void QScriptValueIterator::remove()
+{
+    d_ptr->remove();
+}
+
+/*!
+    Returns the flags of the last property that was jumped over using
+    next() or previous().
+
+    \sa value()
+*/
+QScriptValue::PropertyFlags QScriptValueIterator::flags() const
+{
+    return d_ptr->flags();
+}
+
+/*!
+    Makes the iterator operate on \a object. The iterator is set to be
+    at the front of the sequence of properties (before the first
+    property).
+*/
+QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue& object)
+{
+    d_ptr = new QScriptValueIteratorPrivate(QScriptValuePrivate::get(object));
+    return *this;
+}
diff --git a/qt/api/qscriptvalueiterator.h b/qt/api/qscriptvalueiterator.h
new file mode 100644 (file)
index 0000000..0c90661
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptvalueiterator_h
+#define qscriptvalueiterator_h
+
+#include "qtscriptglobal.h"
+#include "qscriptstring.h"
+#include <QtCore/qshareddata.h>
+#include "qscriptvalue.h"
+
+class QScriptValue;
+class QScriptValueIteratorPrivate;
+
+
+class Q_JAVASCRIPT_EXPORT QScriptValueIterator {
+public:
+    QScriptValueIterator(const QScriptValue& value);
+    ~QScriptValueIterator();
+
+    bool hasNext() const;
+    void next();
+
+    bool hasPrevious() const;
+    void previous();
+
+    QString name() const;
+    QScriptString scriptName() const;
+
+    QScriptValue value() const;
+    void setValue(const QScriptValue& value);
+
+    void remove();
+    QScriptValue::PropertyFlags flags() const;
+
+    void toFront();
+    void toBack();
+
+    QScriptValueIterator& operator=(QScriptValue& value);
+private:
+    QExplicitlySharedDataPointer<QScriptValueIteratorPrivate> d_ptr;
+
+    Q_DECLARE_PRIVATE(QScriptValueIterator)
+    Q_DISABLE_COPY(QScriptValueIterator)
+};
+
+#endif // qscriptvalueiterator_h
diff --git a/qt/api/qscriptvalueiterator_p.h b/qt/api/qscriptvalueiterator_p.h
new file mode 100644 (file)
index 0000000..b93b518
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptvalueiterator_p_h
+#define qscriptvalueiterator_p_h
+
+#include "qscriptvalue_p.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qvector.h>
+
+class QScriptValueIteratorPrivate: public QSharedData {
+public:
+    inline QScriptValueIteratorPrivate(const QScriptValuePrivate* value);
+    inline ~QScriptValueIteratorPrivate();
+
+    inline bool hasNext();
+    inline void next();
+
+    inline bool hasPrevious();
+    inline void previous();
+
+    inline QString name() const;
+    inline QScriptStringPrivate* scriptName() const;
+
+    inline QScriptValuePrivate* value() const;
+    inline void setValue(const QScriptValuePrivate* value);
+
+    inline void remove();
+
+    inline void toFront();
+    inline void toBack();
+
+    QScriptValue::PropertyFlags flags() const;
+
+    inline bool isValid() const;
+private:
+    inline QScriptEnginePrivate* engine() const;
+
+    QExplicitlySharedDataPointer<QScriptValuePrivate> m_object;
+    QVector<JSStringRef> m_names;
+    QMutableVectorIterator<JSStringRef> m_idx;
+};
+
+inline QScriptValueIteratorPrivate::QScriptValueIteratorPrivate(const QScriptValuePrivate* value)
+    : m_object(const_cast<QScriptValuePrivate*>(value))
+    , m_idx(m_names)
+{
+    if (m_object->isObject()) {
+        m_names = engine()->objectGetOwnPropertyNames(*m_object);
+        m_idx = m_names;
+    } else
+        m_object = 0;
+}
+
+inline QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate()
+{
+    QVector<JSStringRef>::const_iterator i = m_names.constBegin();
+    for (; i != m_names.constEnd(); ++i)
+        JSStringRelease(*i);
+}
+
+inline bool QScriptValueIteratorPrivate::hasNext()
+{
+    return m_idx.hasNext();
+}
+
+inline void QScriptValueIteratorPrivate::next()
+{
+    // FIXME (Qt5) This method should return a value (QTBUG-11226).
+    m_idx.next();
+}
+
+inline bool QScriptValueIteratorPrivate::hasPrevious()
+{
+    return m_idx.hasPrevious();
+}
+
+inline void QScriptValueIteratorPrivate::previous()
+{
+    m_idx.previous();
+}
+
+inline QString QScriptValueIteratorPrivate::name() const
+{
+    if (!isValid())
+        return QString();
+    return QScriptConverter::toString(m_idx.value());
+}
+
+inline QScriptStringPrivate* QScriptValueIteratorPrivate::scriptName() const
+{
+    if (!isValid())
+        return new QScriptStringPrivate();
+    return new QScriptStringPrivate(QScriptConverter::toString(m_idx.value()));
+}
+
+inline QScriptValuePrivate* QScriptValueIteratorPrivate::value() const
+{
+    if (!isValid())
+        return new QScriptValuePrivate();
+    JSValueRef exception = 0;
+    JSValueRef value = m_object->property(m_idx.value(), &exception);
+    engine()->setException(exception);
+    return new QScriptValuePrivate(engine(), value);
+}
+
+inline void QScriptValueIteratorPrivate::setValue(const QScriptValuePrivate* value)
+{
+    if (!isValid())
+        return;
+    JSValueRef exception = 0;
+    m_object->setProperty(m_idx.value(), *value, /* flags */ 0, &exception);
+    engine()->setException(exception);
+}
+
+inline void QScriptValueIteratorPrivate::remove()
+{
+    if (!isValid())
+        return;
+    JSValueRef exception = 0;
+    m_object->deleteProperty(m_idx.value(), &exception);
+    engine()->setException(exception);
+    m_idx.remove();
+}
+
+inline void QScriptValueIteratorPrivate::toFront()
+{
+    m_idx.toFront();
+}
+
+inline void QScriptValueIteratorPrivate::toBack()
+{
+    m_idx.toBack();
+}
+
+QScriptValue::PropertyFlags QScriptValueIteratorPrivate::flags() const
+{
+    if (!isValid())
+        return QScriptValue::PropertyFlags(0);
+    return m_object->propertyFlags(m_idx.value(), QScriptValue::ResolveLocal);
+}
+
+inline bool QScriptValueIteratorPrivate::isValid() const
+{
+    return m_object;
+}
+
+inline QScriptEnginePrivate* QScriptValueIteratorPrivate::engine() const
+{
+    Q_ASSERT(isValid());
+    return m_object->engine();
+}
+
+#endif // qscriptvalueiterator_p_h
diff --git a/qt/benchmarks/benchmarks.pri b/qt/benchmarks/benchmarks.pri
new file mode 100644 (file)
index 0000000..5af3383
--- /dev/null
@@ -0,0 +1,19 @@
+QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR
+QMAKE_LIBDIR = $$OUTPUT_DIR/lib $$QMAKE_LIBDIR
+mac:!static:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework) {
+    LIBS += -framework QtScript
+    QMAKE_FRAMEWORKPATH = $$OUTPUT_DIR/lib $$QMAKE_FRAMEWORKPATH
+} else {
+    win32-*|wince* {
+        LIBS += -lQtScript$${QT_MAJOR_VERSION}
+    } else {
+        LIBS += -lQtScript
+    }
+}
+
+CONFIG(release, debug|release) {
+    DEFINES += NDEBUG
+}
+
+INCLUDEPATH += $$PWD/../api
+
diff --git a/qt/benchmarks/benchmarks.pro b/qt/benchmarks/benchmarks.pro
new file mode 100644 (file)
index 0000000..85fa82c
--- /dev/null
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+SUBDIRS =   qscriptengine \
+            qscriptvalue \
+
diff --git a/qt/benchmarks/qscriptengine/qscriptengine.pro b/qt/benchmarks/qscriptengine/qscriptengine.pro
new file mode 100644 (file)
index 0000000..e94137d
--- /dev/null
@@ -0,0 +1,13 @@
+TEMPLATE = app
+TARGET = tst_bench_qscriptengine
+
+SOURCES += tst_qscriptengine.cpp
+
+QT += testlib
+
+include(../benchmarks.pri)
+
+symbian* {
+    TARGET.EPOCHEAPSIZE  = 0x20000 0x2000000 // Min 128kB, Max 32MB
+    TARGET.EPOCSTACKSIZE = 0x14000
+}
diff --git a/qt/benchmarks/qscriptengine/tst_qscriptengine.cpp b/qt/benchmarks/qscriptengine/tst_qscriptengine.cpp
new file mode 100644 (file)
index 0000000..0c447c6
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "qscriptengine.h"
+#include "qscriptvalue.h"
+#include <qtest.h>
+
+class tst_QScriptEngine : public QObject {
+    Q_OBJECT
+
+private slots:
+    void checkSyntax_data();
+    void checkSyntax();
+    void constructor();
+    void evaluateString_data();
+    void evaluateString();
+    void evaluateProgram_data();
+    void evaluateProgram();
+    void newObject();
+    void nullValue();
+    void undefinedValue();
+    void globalObject();
+    void toStringHandle();
+};
+
+void tst_QScriptEngine::checkSyntax_data()
+{
+    evaluateString_data();
+}
+
+void tst_QScriptEngine::checkSyntax()
+{
+    QFETCH(QString, code);
+    QScriptEngine engine;
+    QBENCHMARK {
+        engine.checkSyntax(code);
+    }
+}
+
+void tst_QScriptEngine::constructor()
+{
+    QBENCHMARK {
+        QScriptEngine engine;
+    }
+}
+
+void tst_QScriptEngine::evaluateString_data()
+{
+    QTest::addColumn<QString>("code");
+    QTest::newRow("empty script") << QString::fromLatin1("");
+    QTest::newRow("number literal") << QString::fromLatin1("123");
+    QTest::newRow("string literal") << QString::fromLatin1("'ciao'");
+    QTest::newRow("regexp literal") << QString::fromLatin1("/foo/gim");
+    QTest::newRow("null literal") << QString::fromLatin1("null");
+    QTest::newRow("undefined literal") << QString::fromLatin1("undefined");
+    QTest::newRow("empty object literal") << QString::fromLatin1("{}");
+    QTest::newRow("this") << QString::fromLatin1("this");
+}
+
+void tst_QScriptEngine::evaluateString()
+{
+    QFETCH(QString, code);
+    QScriptEngine engine;
+    QBENCHMARK {
+        engine.evaluate(code);
+    }
+}
+
+void tst_QScriptEngine::evaluateProgram_data()
+{
+    evaluateString_data();
+}
+
+void tst_QScriptEngine::evaluateProgram()
+{
+    QFETCH(QString, code);
+    QScriptEngine engine;
+    QScriptProgram program(code);
+    QBENCHMARK {
+        engine.evaluate(program);
+    }
+}
+
+void tst_QScriptEngine::newObject()
+{
+    QScriptEngine engine;
+    QBENCHMARK {
+        engine.newObject();
+    }
+}
+
+void tst_QScriptEngine::nullValue()
+{
+    QScriptEngine engine;
+    QBENCHMARK {
+        engine.nullValue();
+    }
+}
+
+void tst_QScriptEngine::undefinedValue()
+{
+    QScriptEngine engine;
+    QBENCHMARK {
+        engine.undefinedValue();
+    }
+}
+
+void tst_QScriptEngine::globalObject()
+{
+    QScriptEngine engine;
+    QBENCHMARK {
+        engine.globalObject();
+    }
+}
+
+void tst_QScriptEngine::toStringHandle()
+{
+    QScriptEngine engine;
+    QString str = QString::fromLatin1("foobarbaz");
+    QBENCHMARK {
+        engine.toStringHandle(str);
+    }
+}
+
+QTEST_MAIN(tst_QScriptEngine)
+#include "tst_qscriptengine.moc"
diff --git a/qt/benchmarks/qscriptvalue/qscriptvalue.pro b/qt/benchmarks/qscriptvalue/qscriptvalue.pro
new file mode 100644 (file)
index 0000000..673fe65
--- /dev/null
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET = tst_bench_qscriptvalue
+QT += testlib
+
+isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../..
+include(../benchmarks.pri)
+
+SOURCES += tst_qscriptvalue.cpp
+
diff --git a/qt/benchmarks/qscriptvalue/tst_qscriptvalue.cpp b/qt/benchmarks/qscriptvalue/tst_qscriptvalue.cpp
new file mode 100644 (file)
index 0000000..7c39b8e
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "qscriptengine.h"
+#include "qscriptstring.h"
+#include "qscriptvalue.h"
+#include <qtest.h>
+
+Q_DECLARE_METATYPE(QScriptValue);
+
+class tst_QScriptValue : public QObject {
+    Q_OBJECT
+
+public:
+    tst_QScriptValue()
+        : m_engine(0)
+    {}
+
+    ~tst_QScriptValue()
+    {
+        if (m_engine)
+            delete m_engine;
+    }
+
+private slots:
+    void values_data();
+
+    void ctorBool();
+    void ctorReal();
+    void ctorNumber();
+    void ctorQString();
+    void ctorCString();
+    void ctorSpecial();
+    void ctorQScriptValue();
+
+    void isValid_data();
+    void isValid();
+    void isBool_data();
+    void isBool();
+    void isNumber_data();
+    void isNumber();
+    void isFunction_data();
+    void isFunction();
+    void isNull_data();
+    void isNull();
+    void isString_data();
+    void isString();
+    void isUndefined_data();
+    void isUndefined();
+    void isObject_data();
+    void isObject();
+    void isError_data();
+    void isError();
+
+    void toString_data();
+    void toString();
+    void toNumber_data();
+    void toNumber();
+    void toBool_data();
+    void toBool();
+    void toInteger_data();
+    void toInteger();
+    void toInt32_data();
+    void toInt32();
+    void toUInt32_data();
+    void toUInt32();
+    void toUInt16_data();
+    void toUInt16();
+    void toObject_data();
+    void toObject();
+
+    void equals_data();
+    void equals();
+    void strictlyEquals_data();
+    void strictlyEquals();
+    void instanceOf_data();
+    void instanceOf();
+
+private:
+    QScriptEngine* m_engine;
+};
+
+void tst_QScriptValue::values_data()
+{
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine;
+
+    QTest::addColumn<QScriptValue>("value");
+
+    QTest::newRow("invalid") << QScriptValue();
+
+    QTest::newRow("cbool") << QScriptValue(true);
+    QTest::newRow("cnumber") << QScriptValue(1234);
+    QTest::newRow("cstring") << QScriptValue("abc");
+    QTest::newRow("cnull") << QScriptValue(QScriptValue::NullValue);
+    QTest::newRow("cundefined") << QScriptValue(QScriptValue::UndefinedValue);
+
+    QTest::newRow("jsbool") << m_engine->evaluate("true");
+    QTest::newRow("jsnumber") << m_engine->evaluate("12345");
+    QTest::newRow("jsstring") << m_engine->evaluate("'go'");
+    QTest::newRow("jsfunction") << m_engine->evaluate("(function {})");
+    QTest::newRow("jsnull") << m_engine->nullValue();
+    QTest::newRow("jsundefined") << m_engine->undefinedValue();
+    QTest::newRow("jsobject") << m_engine->newObject();
+    QTest::newRow("jserror") << m_engine->evaluate("new Error()");
+}
+
+void tst_QScriptValue::ctorBool()
+{
+    QBENCHMARK {
+        QScriptValue(true);
+    }
+}
+
+void tst_QScriptValue::ctorReal()
+{
+    QBENCHMARK {
+        QScriptValue(12.3);
+    }
+}
+
+void tst_QScriptValue::ctorNumber()
+{
+    QBENCHMARK {
+        QScriptValue(123);
+    }
+}
+
+void tst_QScriptValue::ctorQString()
+{
+    QString str = QString::fromLatin1("ciao");
+    QBENCHMARK {
+        QScriptValue(str);
+    }
+}
+
+void tst_QScriptValue::ctorCString()
+{
+    QBENCHMARK {
+        QScriptValue("Pong!");
+    }
+}
+
+void tst_QScriptValue::ctorSpecial()
+{
+    QBENCHMARK {
+        (void)QScriptValue(QScriptValue::NullValue);
+    }
+}
+
+void tst_QScriptValue::ctorQScriptValue()
+{
+    QScriptValue tmp(1234);
+    QBENCHMARK {
+        QScriptValue(tmp);
+    }
+}
+
+void tst_QScriptValue::isValid_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isValid()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isValid();
+    }
+}
+
+void tst_QScriptValue::isBool_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isBool()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isBool();
+    }
+}
+
+void tst_QScriptValue::isNumber_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isNumber()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isNumber();
+    }
+}
+
+void tst_QScriptValue::isFunction_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isFunction()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isFunction();
+    }
+}
+
+void tst_QScriptValue::isNull_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isNull()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isNull();
+    }
+}
+
+void tst_QScriptValue::isString_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isString()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isString();
+    }
+}
+
+void tst_QScriptValue::isUndefined_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isUndefined()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isUndefined();
+    }
+}
+
+void tst_QScriptValue::isObject_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isObject()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isObject();
+    }
+}
+
+void tst_QScriptValue::isError_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::isError()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.isError();
+    }
+}
+
+void tst_QScriptValue::toString_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toString()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toString();
+    }
+}
+
+void tst_QScriptValue::toNumber_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toNumber()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toNumber();
+    }
+}
+
+void tst_QScriptValue::toBool_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toBool()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toBool();
+    }
+}
+
+void tst_QScriptValue::toInteger_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toInteger()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toInteger();
+    }
+}
+
+void tst_QScriptValue::toInt32_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toInt32()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toInt32();
+    }
+}
+
+void tst_QScriptValue::toUInt32_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toUInt32()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toUInt32();
+    }
+}
+
+void tst_QScriptValue::toUInt16_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toUInt16()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toUInt16();
+    }
+}
+
+void tst_QScriptValue::toObject_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::toObject()
+{
+    QFETCH(QScriptValue, value);
+    QBENCHMARK {
+        value.toObject();
+    }
+}
+
+void tst_QScriptValue::equals_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::equals()
+{
+    QFETCH(QScriptValue, value);
+    static QScriptValue previous;
+    QBENCHMARK {
+        value.equals(previous);
+    }
+    previous = value;
+}
+
+void tst_QScriptValue::strictlyEquals_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::strictlyEquals()
+{
+    QFETCH(QScriptValue, value);
+    static QScriptValue previous;
+    QBENCHMARK {
+        value.strictlyEquals(previous);
+    }
+    previous = value;
+}
+
+void tst_QScriptValue::instanceOf_data()
+{
+    values_data();
+}
+
+void tst_QScriptValue::instanceOf()
+{
+    QFETCH(QScriptValue, value);
+    static QScriptValue object = m_engine->newObject();
+    QBENCHMARK {
+        value.instanceOf(object);
+    }
+}
+
+QTEST_MAIN(tst_QScriptValue)
+#include "tst_qscriptvalue.moc"
index 1ec9ad3f0c0979c6c756ff1ea183a375cb0e3f06..dabcfb2e813ed9c7bc5fc4b0b43a1fd25efe7652 100644 (file)
@@ -21,6 +21,7 @@
 #include "qscriptprogram.h"
 #include "qscriptsyntaxcheckresult.h"
 #include "qscriptvalue.h"
+#include <QtCore/qnumeric.h>
 #include <QtTest/qtest.h>
 
 class tst_QScriptEngine : public QObject {
@@ -35,6 +36,8 @@ public slots:
     void cleanup() {}
 
 private slots:
+    void newFunction();
+    void newObject();
     void globalObject();
     void evaluate();
     void collectGarbage();
@@ -44,6 +47,11 @@ private slots:
     void evaluateProgram();
     void checkSyntax_data();
     void checkSyntax();
+    void toObject();
+    void toObjectTwoEngines();
+    void newArray();
+    void uncaughtException();
+    void newDate();
 };
 
 /* Evaluating a script that throw an unhandled exception should return an invalid value. */
@@ -54,6 +62,158 @@ void tst_QScriptEngine::evaluate()
     QVERIFY2(engine.evaluate("ping").isValid(), "Script throwing an unhandled exception should return an exception value");
 }
 
+static QScriptValue myFunction(QScriptContext*, QScriptEngine* eng)
+{
+    return eng->nullValue();
+}
+
+static QScriptValue myFunctionWithArg(QScriptContext*, QScriptEngine* eng, void* arg)
+{
+    int* result = reinterpret_cast<int*>(arg);
+    return QScriptValue(eng, *result);
+}
+
+static QScriptValue myFunctionThatReturns(QScriptContext*, QScriptEngine* eng)
+{
+    return QScriptValue(eng, 42);
+}
+
+static QScriptValue myFunctionThatReturnsWithoutEngine(QScriptContext*, QScriptEngine*)
+{
+    return QScriptValue(1024);
+}
+
+static QScriptValue myFunctionThatReturnsWrongEngine(QScriptContext*, QScriptEngine*, void* arg)
+{
+    QScriptEngine* wrongEngine = reinterpret_cast<QScriptEngine*>(arg);
+    return QScriptValue(wrongEngine, 42);
+}
+
+void tst_QScriptEngine::newFunction()
+{
+    QScriptEngine eng;
+    {
+        QScriptValue fun = eng.newFunction(myFunction);
+        QCOMPARE(fun.isValid(), true);
+        QCOMPARE(fun.isFunction(), true);
+        QCOMPARE(fun.isObject(), true);
+        // QCOMPARE(fun.scriptClass(), (QScriptClass*)0);
+        // a prototype property is automatically constructed
+        {
+            QScriptValue prot = fun.property("prototype", QScriptValue::ResolveLocal);
+            QVERIFY(prot.isObject());
+            QVERIFY(prot.property("constructor").strictlyEquals(fun));
+            QEXPECT_FAIL("", "JSCallbackObject::getOwnPropertyDescriptor() doesn't return correct information yet", Continue);
+            QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable);
+            QEXPECT_FAIL("", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+            QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration));
+        }
+        // prototype should be Function.prototype
+        QCOMPARE(fun.prototype().isValid(), true);
+        QCOMPARE(fun.prototype().isFunction(), true);
+        QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true);
+
+        QCOMPARE(fun.call().isNull(), true);
+        // QCOMPARE(fun.construct().isObject(), true);
+    }
+    // the overload that takes an extra argument
+    {
+        int expectedResult = 42;
+        QScriptValue fun = eng.newFunction(myFunctionWithArg, reinterpret_cast<void*>(&expectedResult));
+        QVERIFY(fun.isFunction());
+        // QCOMPARE(fun.scriptClass(), (QScriptClass*)0);
+        // a prototype property is automatically constructed
+        {
+            QScriptValue prot = fun.property("prototype", QScriptValue::ResolveLocal);
+            QVERIFY(prot.isObject());
+            QVERIFY(prot.property("constructor").strictlyEquals(fun));
+            QEXPECT_FAIL("", "JSCallbackObject::getOwnPropertyDescriptor() doesn't return correct information yet", Continue);
+            QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable);
+            QEXPECT_FAIL("", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+            QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration));
+        }
+        // prototype should be Function.prototype
+        QCOMPARE(fun.prototype().isValid(), true);
+        QCOMPARE(fun.prototype().isFunction(), true);
+        QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true);
+
+        QScriptValue result = fun.call();
+        QCOMPARE(result.isNumber(), true);
+        QCOMPARE(result.toInt32(), expectedResult);
+    }
+    // the overload that takes a prototype
+    {
+        QScriptValue proto = eng.newObject();
+        QScriptValue fun = eng.newFunction(myFunction, proto);
+        QCOMPARE(fun.isValid(), true);
+        QCOMPARE(fun.isFunction(), true);
+        QCOMPARE(fun.isObject(), true);
+        // internal prototype should be Function.prototype
+        QCOMPARE(fun.prototype().isValid(), true);
+        QCOMPARE(fun.prototype().isFunction(), true);
+        QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true);
+        // public prototype should be the one we passed
+        QCOMPARE(fun.property("prototype").strictlyEquals(proto), true);
+        QEXPECT_FAIL("", "JSCallbackObject::getOwnPropertyDescriptor() doesn't return correct information yet", Continue);
+        QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable);
+        QCOMPARE(proto.property("constructor").strictlyEquals(fun), true);
+        QEXPECT_FAIL("", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+        QCOMPARE(proto.propertyFlags("constructor"), QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration));
+
+        QCOMPARE(fun.call().isNull(), true);
+        // QCOMPARE(fun.construct().isObject(), true);
+    }
+    // whether the return value is correct
+    {
+        QScriptValue fun = eng.newFunction(myFunctionThatReturns);
+        QCOMPARE(fun.isValid(), true);
+        QCOMPARE(fun.isFunction(), true);
+        QCOMPARE(fun.isObject(), true);
+
+        QScriptValue result = fun.call();
+        QCOMPARE(result.isNumber(), true);
+        QCOMPARE(result.toInt32(), 42);
+    }
+    // whether the return value is assigned to the correct engine
+    {
+        QScriptValue fun = eng.newFunction(myFunctionThatReturnsWithoutEngine);
+        QCOMPARE(fun.isValid(), true);
+        QCOMPARE(fun.isFunction(), true);
+        QCOMPARE(fun.isObject(), true);
+
+        QScriptValue result = fun.call();
+        QCOMPARE(result.engine(), &eng);
+        QCOMPARE(result.isNumber(), true);
+        QCOMPARE(result.toInt32(), 1024);
+    }
+    // whether the return value is undefined when returning a value with wrong engine
+    {
+        QScriptEngine wrongEngine;
+
+        QScriptValue fun = eng.newFunction(myFunctionThatReturnsWrongEngine, reinterpret_cast<void*>(&wrongEngine));
+        QCOMPARE(fun.isValid(), true);
+        QCOMPARE(fun.isFunction(), true);
+        QCOMPARE(fun.isObject(), true);
+
+        QTest::ignoreMessage(QtWarningMsg, "Value from different engine returned from native function, returning undefined value instead.");
+        QScriptValue result = fun.call();
+        QCOMPARE(result.isValid(), true);
+        QCOMPARE(result.isUndefined(), true);
+    }
+}
+
+void tst_QScriptEngine::newObject()
+{
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    QVERIFY(object.isObject());
+    QVERIFY(object.engine() == &engine);
+    QVERIFY(!object.isError());
+    QVERIFY(!object.equals(engine.newObject()));
+    QVERIFY(!object.strictlyEquals(engine.newObject()));
+    QCOMPARE(object.toString(), QString::fromAscii("[object Object]"));
+}
+
 void tst_QScriptEngine::globalObject()
 {
     QScriptEngine engine;
@@ -61,7 +221,6 @@ void tst_QScriptEngine::globalObject()
     QScriptValue self = engine.evaluate("this");
     QVERIFY(global.isObject());
     QVERIFY(engine.globalObject().equals(engine.evaluate("this")));
-    QEXPECT_FAIL("", "strictlyEquals is broken - bug 36600 in bugs.webkit.org", Continue);
     QVERIFY(engine.globalObject().strictlyEquals(self));
 }
 
@@ -303,6 +462,273 @@ void tst_QScriptEngine::checkSyntax()
     QCOMPARE(result.errorMessage(), errorMessage);
 }
 
+void tst_QScriptEngine::toObject()
+{
+    QScriptEngine eng;
+    QVERIFY(!eng.toObject(eng.undefinedValue()).isValid());
+    QVERIFY(!eng.toObject(eng.nullValue()).isValid());
+    QVERIFY(!eng.toObject(QScriptValue()).isValid());
+
+    QScriptValue falskt(false);
+    {
+        QScriptValue tmp = eng.toObject(falskt);
+        QVERIFY(tmp.isObject());
+        QVERIFY(!falskt.isObject());
+        QVERIFY(!falskt.engine());
+        QCOMPARE(tmp.toNumber(), falskt.toNumber());
+    }
+
+    QScriptValue sant(true);
+    {
+        QScriptValue tmp = eng.toObject(sant);
+        QVERIFY(tmp.isObject());
+        QVERIFY(!sant.isObject());
+        QVERIFY(!sant.engine());
+        QCOMPARE(tmp.toNumber(), sant.toNumber());
+    }
+
+    QScriptValue number(123.0);
+    {
+        QScriptValue tmp = eng.toObject(number);
+        QVERIFY(tmp.isObject());
+        QVERIFY(!number.isObject());
+        QVERIFY(!number.engine());
+        QCOMPARE(tmp.toNumber(), number.toNumber());
+    }
+
+    QScriptValue str = QScriptValue(&eng, QString("ciao"));
+    {
+        QScriptValue tmp = eng.toObject(str);
+        QVERIFY(tmp.isObject());
+        QVERIFY(!str.isObject());
+        QCOMPARE(tmp.toString(), str.toString());
+    }
+
+    QScriptValue object = eng.evaluate("new Object");
+    {
+        QScriptValue tmp = eng.toObject(object);
+        QVERIFY(tmp.isObject());
+        QVERIFY(object.isObject());
+        QVERIFY(tmp.strictlyEquals(object));
+    }
+}
+
+void tst_QScriptEngine::toObjectTwoEngines()
+{
+    QScriptEngine engine1;
+    QScriptEngine engine2;
+
+    {
+        QScriptValue null = engine1.nullValue();
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(!engine2.toObject(null).isValid());
+        QVERIFY(null.isValid());
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(engine2.toObject(null).engine() != &engine2);
+    }
+    {
+        QScriptValue undefined = engine1.undefinedValue();
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(!engine2.toObject(undefined).isValid());
+        QVERIFY(undefined.isValid());
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(engine2.toObject(undefined).engine() != &engine2);
+    }
+    {
+        QScriptValue value = engine1.evaluate("1");
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(engine2.toObject(value).engine() != &engine2);
+        QVERIFY(!value.isObject());
+    }
+    {
+        QScriptValue string = engine1.evaluate("'Qt'");
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(engine2.toObject(string).engine() != &engine2);
+        QVERIFY(!string.isObject());
+    }
+    {
+        QScriptValue object = engine1.evaluate("new Object");
+        QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::toObject: cannot convert value created in a different engine");
+        QVERIFY(engine2.toObject(object).engine() != &engine2);
+        QVERIFY(object.isObject());
+    }
+}
+
+void tst_QScriptEngine::newArray()
+{
+    QScriptEngine eng;
+    QScriptValue array = eng.newArray();
+    QCOMPARE(array.isValid(), true);
+    QCOMPARE(array.isArray(), true);
+    QCOMPARE(array.isObject(), true);
+    QVERIFY(!array.isFunction());
+    // QCOMPARE(array.scriptClass(), (QScriptClass*)0);
+
+    // Prototype should be Array.prototype.
+    QCOMPARE(array.prototype().isValid(), true);
+    QCOMPARE(array.prototype().isArray(), true);
+    QCOMPARE(array.prototype().strictlyEquals(eng.evaluate("Array.prototype")), true);
+
+    QScriptValue arrayWithSize = eng.newArray(42);
+    QCOMPARE(arrayWithSize.isValid(), true);
+    QCOMPARE(arrayWithSize.isArray(), true);
+    QCOMPARE(arrayWithSize.isObject(), true);
+    QCOMPARE(arrayWithSize.property("length").toInt32(), 42);
+
+    // task 218092
+    {
+        QScriptValue ret = eng.evaluate("[].splice(0, 0, 'a')");
+        QVERIFY(ret.isArray());
+        QCOMPARE(ret.property("length").toInt32(), 0);
+    }
+    {
+        QScriptValue ret = eng.evaluate("['a'].splice(0, 1, 'b')");
+        QVERIFY(ret.isArray());
+        QCOMPARE(ret.property("length").toInt32(), 1);
+    }
+    {
+        QScriptValue ret = eng.evaluate("['a', 'b'].splice(0, 1, 'c')");
+        QVERIFY(ret.isArray());
+        QCOMPARE(ret.property("length").toInt32(), 1);
+    }
+    {
+        QScriptValue ret = eng.evaluate("['a', 'b', 'c'].splice(0, 2, 'd')");
+        QVERIFY(ret.isArray());
+        QCOMPARE(ret.property("length").toInt32(), 2);
+    }
+    {
+        QScriptValue ret = eng.evaluate("['a', 'b', 'c'].splice(1, 2, 'd', 'e', 'f')");
+        QVERIFY(ret.isArray());
+        QCOMPARE(ret.property("length").toInt32(), 2);
+    }
+}
+
+void tst_QScriptEngine::uncaughtException()
+{
+    QScriptEngine eng;
+    QScriptValue fun = eng.evaluate("(function foo () { return null; });");
+    QVERIFY(!eng.uncaughtException().isValid());
+    QVERIFY(fun.isFunction());
+    QScriptValue throwFun = eng.evaluate("( function() { throw new Error('Pong'); });");
+    QVERIFY(throwFun.isFunction());
+    {
+        eng.evaluate("a = 10");
+        QVERIFY(!eng.hasUncaughtException());
+        QVERIFY(!eng.uncaughtException().isValid());
+    }
+    {
+        eng.evaluate("1 = 2");
+        QVERIFY(eng.hasUncaughtException());
+        eng.clearExceptions();
+        QVERIFY(!eng.hasUncaughtException());
+    }
+    {
+        // Check if the call or toString functions can remove the last exception.
+        QVERIFY(throwFun.call().isError());
+        QVERIFY(eng.hasUncaughtException());
+        QScriptValue exception = eng.uncaughtException();
+        fun.call();
+        exception.toString();
+        QVERIFY(eng.hasUncaughtException());
+        QVERIFY(eng.uncaughtException().strictlyEquals(exception));
+    }
+    eng.clearExceptions();
+    {
+        // Check if in the call function a new exception can override an existing one.
+        throwFun.call();
+        QVERIFY(eng.hasUncaughtException());
+        QScriptValue exception = eng.uncaughtException();
+        throwFun.call();
+        QVERIFY(eng.hasUncaughtException());
+        QVERIFY(!exception.strictlyEquals(eng.uncaughtException()));
+    }
+    {
+        eng.evaluate("throwFun = (function foo () { throw new Error('bla') });");
+        eng.evaluate("1;\nthrowFun();");
+        QVERIFY(eng.hasUncaughtException());
+        QCOMPARE(eng.uncaughtExceptionLineNumber(), 1);
+        eng.clearExceptions();
+        QVERIFY(!eng.hasUncaughtException());
+    }
+    for (int x = 1; x < 4; ++x) {
+        QScriptValue ret = eng.evaluate("a = 10;\nb = 20;\n0 = 0;\n",
+                                        QString::fromLatin1("FooScript") + QString::number(x),
+                                        /* lineNumber */ x);
+        QVERIFY(eng.hasUncaughtException());
+        QCOMPARE(eng.uncaughtExceptionLineNumber(), x + 2);
+        QVERIFY(eng.uncaughtException().strictlyEquals(ret));
+        QVERIFY(eng.hasUncaughtException());
+        QVERIFY(eng.uncaughtException().strictlyEquals(ret));
+        QString backtrace = QString::fromLatin1("<anonymous>()@FooScript") + QString::number(x) + ":" + QString::number(x + 2);
+        QCOMPARE(eng.uncaughtExceptionBacktrace().join(""), backtrace);
+        QVERIFY(fun.call().isNull());
+        QVERIFY(eng.hasUncaughtException());
+        QCOMPARE(eng.uncaughtExceptionLineNumber(), x + 2);
+        QVERIFY(eng.uncaughtException().strictlyEquals(ret));
+        eng.clearExceptions();
+        QVERIFY(!eng.hasUncaughtException());
+        QCOMPARE(eng.uncaughtExceptionLineNumber(), -1);
+        QVERIFY(!eng.uncaughtException().isValid());
+        eng.evaluate("2 = 3");
+        QVERIFY(eng.hasUncaughtException());
+        QScriptValue ret2 = throwFun.call();
+        QVERIFY(ret2.isError());
+        QVERIFY(eng.hasUncaughtException());
+        QVERIFY(eng.uncaughtException().strictlyEquals(ret2));
+        QCOMPARE(eng.uncaughtExceptionLineNumber(), 1);
+        eng.clearExceptions();
+        QVERIFY(!eng.hasUncaughtException());
+        eng.evaluate("1 + 2");
+        QVERIFY(!eng.hasUncaughtException());
+    }
+}
+
+void tst_QScriptEngine::newDate()
+{
+    QScriptEngine eng;
+    {
+        QScriptValue date = eng.newDate(0);
+        QCOMPARE(date.isValid(), true);
+        QCOMPARE(date.isDate(), true);
+        QCOMPARE(date.isObject(), true);
+        QVERIFY(!date.isFunction());
+        // prototype should be Date.prototype
+        QCOMPARE(date.prototype().isValid(), true);
+        QCOMPARE(date.prototype().isDate(), true);
+        QCOMPARE(date.prototype().strictlyEquals(eng.evaluate("Date.prototype")), true);
+    }
+    {
+        QDateTime dt = QDateTime(QDate(1, 2, 3), QTime(4, 5, 6, 7), Qt::LocalTime);
+        QScriptValue date = eng.newDate(dt);
+        QCOMPARE(date.isValid(), true);
+        QCOMPARE(date.isDate(), true);
+        QCOMPARE(date.isObject(), true);
+        // prototype should be Date.prototype
+        QCOMPARE(date.prototype().isValid(), true);
+        QCOMPARE(date.prototype().isDate(), true);
+        QCOMPARE(date.prototype().strictlyEquals(eng.evaluate("Date.prototype")), true);
+
+        QCOMPARE(date.toDateTime(), dt);
+    }
+    {
+        QDateTime dt = QDateTime(QDate(1, 2, 3), QTime(4, 5, 6, 7), Qt::UTC);
+        QScriptValue date = eng.newDate(dt);
+        // toDateTime() result should be in local time
+        QCOMPARE(date.toDateTime(), dt.toLocalTime());
+    }
+    // Date.parse() should return NaN when it fails
+    {
+        QScriptValue ret = eng.evaluate("Date.parse()");
+        QVERIFY(ret.isNumber());
+        QVERIFY(qIsNaN(ret.toNumber()));
+    }
+    // Date.parse() should be able to parse the output of Date().toString()
+    {
+        QScriptValue ret = eng.evaluate("var x = new Date(); var s = x.toString(); s == new Date(Date.parse(s)).toString()");
+        QVERIFY(ret.isBoolean());
+        QCOMPARE(ret.toBoolean(), true);
+    }
+}
 
 QTEST_MAIN(tst_QScriptEngine)
 #include "tst_qscriptengine.moc"
index 35cc17da9083768a845bae214b5ba1ce926e8557..02e94ecdd2b1ab5fa28731b81831c0ffd0b4c49b 100644 (file)
@@ -6,7 +6,10 @@ include(../tests.pri)
 
 SOURCES += \
     tst_qscriptvalue.cpp \
-    tst_qscriptvalue_generated.cpp
+    tst_qscriptvalue_generated_init.cpp \
+    tst_qscriptvalue_generated_comparison.cpp \
+    tst_qscriptvalue_generated_istype.cpp \
+    tst_qscriptvalue_generated_totype.cpp \
 
 HEADERS += \
     tst_qscriptvalue.h
index 82f09014fa81a9d7f3300205a1fc5eef1c6f781b..e04d3e91dcb35ed343ccaff56bd546349bb693ab 100644 (file)
 #include <QtCore/qnumeric.h>
 
 tst_QScriptValue::tst_QScriptValue()
-    : engine(0)
+    : m_engine(0)
 {
 }
 
 tst_QScriptValue::~tst_QScriptValue()
 {
-    delete engine;
+    delete m_engine;
 }
 
-void tst_QScriptValue::dataHelper(InitDataFunction init, DefineDataFunction define)
-{
-    QTest::addColumn<QString>("__expression__");
-    (this->*init)();
-    QHash<QString, QScriptValue>::const_iterator it;
-    for (it = m_values.constBegin(); it != m_values.constEnd(); ++it) {
-        m_currentExpression = it.key();
-        (this->*define)(it.key().toLatin1());
-    }
-    m_currentExpression = QString();
-}
-
-QTestData& tst_QScriptValue::newRow(const char* tag)
-{
-    return QTest::newRow(tag) << m_currentExpression;
-}
-
-void tst_QScriptValue::testHelper(TestFunction fun)
-{
-    QFETCH(QString, __expression__);
-    QScriptValue value = m_values.value(__expression__);
-    (this->*fun)(__expression__.toLatin1(), value);
-}
-
-
 void tst_QScriptValue::ctor()
 {
     QScriptEngine eng;
@@ -274,6 +249,392 @@ void tst_QScriptValue::ctor()
     QVERIFY(QScriptValue(0, QString("ciao")).isString());
 }
 
+void tst_QScriptValue::getPropertySimple_data()
+{
+    QTest::addColumn<QString>("code");
+    QTest::addColumn<QString>("propertyName");
+    QTest::addColumn<QString>("desc");
+    QTest::addColumn<bool>("isArrayIndex");
+
+    QTest::newRow("new Array()")
+            << QString::fromAscii("new Array()")
+            << QString::fromAscii("length")
+            << QString::fromAscii("0")
+            << false;
+    QTest::newRow("new Object().length")
+            << QString::fromAscii("new Object()")
+            << QString::fromAscii("length")
+            << QString::fromAscii("") // Undefined is an invalid property.
+            << false;
+    QTest::newRow("new Object().toString")
+            << QString::fromAscii("new Object()")
+            << QString::fromAscii("toString")
+            << QString::fromAscii("function toString() {\n    [native code]\n}")
+            << false;
+    QTest::newRow("[1,2,3,4]")
+            << QString::fromAscii("[1,2,3,'s',4]")
+            << QString::fromAscii("2")
+            << QString::fromAscii("3")
+            << true;
+    QTest::newRow("[1,3,'a','b']")
+            << QString::fromAscii("[1,3,'a','b']")
+            << QString::fromAscii("3")
+            << QString::fromAscii("b")
+            << true;
+    QTest::newRow("[4,5]")
+            << QString::fromAscii("[4,5]")
+            << QString::fromAscii("123")
+            << QString::fromAscii("") // Undefined is an invalid property.
+            << true;
+    QTest::newRow("[1,3,4]")
+            << QString::fromAscii("[1,3,4]")
+            << QString::fromAscii("abc")
+            << QString::fromAscii("") // Undefined is an invalid property.
+            << true;
+}
+
+void tst_QScriptValue::getPropertySimple()
+{
+    QFETCH(QString, code);
+    QFETCH(QString, propertyName);
+    QFETCH(QString, desc);
+
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate(code);
+    QVERIFY(object.isValid());
+    {
+        QScriptValue property = object.property(propertyName);
+        QCOMPARE(property.toString(), desc);
+    }
+    {
+        QScriptString name = engine.toStringHandle(propertyName);
+        QScriptValue property = object.property(name);
+        QCOMPARE(property.toString(), desc);
+    }
+    {
+        bool ok;
+        quint32 idx = engine.toStringHandle(propertyName).toArrayIndex(&ok);
+        if (ok) {
+            QScriptValue property = object.property(idx);
+            QCOMPARE(property.toString(), desc);
+        }
+    }
+}
+
+void tst_QScriptValue::setPropertySimple()
+{
+    QScriptEngine engine;
+    {
+        QScriptValue invalid;
+        QScriptValue property(1234);
+
+        invalid.setProperty("aaa", property);
+        invalid.setProperty(13, property);
+        invalid.setProperty(engine.toStringHandle("aaa"), property);
+
+        QVERIFY(!invalid.property("aaa").isValid());
+        QVERIFY(!invalid.property(13).isValid());
+        QVERIFY(!invalid.property(engine.toStringHandle("aaa")).isValid());
+    }
+    {
+        QScriptValue object = engine.newObject();
+        QScriptValue property;
+
+        object.setProperty(13, property);
+        object.setProperty("aaa", property);
+        object.setProperty(engine.toStringHandle("aaa"), property);
+
+        QVERIFY(!object.property(13).isValid());
+        QVERIFY(!object.property("aaa").isValid());
+        QVERIFY(!object.property(engine.toStringHandle("aaa")).isValid());
+    }
+    {
+        // Check if setting an invalid property works as deleteProperty.
+        QScriptValue object = engine.evaluate("o = {13: 0, 'aaa': 3, 'bbb': 1}");
+        QScriptValue property;
+
+        QVERIFY(object.property(13).isValid());
+        QVERIFY(object.property("aaa").isValid());
+        QVERIFY(object.property(engine.toStringHandle("aaa")).isValid());
+
+        object.setProperty(13, property);
+        object.setProperty("aaa", property);
+        object.setProperty(engine.toStringHandle("bbb"), property);
+
+        QVERIFY(!object.property(13).isValid());
+        QVERIFY(!object.property("aaa").isValid());
+        QVERIFY(!object.property(engine.toStringHandle("aaa")).isValid());
+    }
+    {
+        QScriptValue object = engine.evaluate("new Object");
+        QVERIFY(object.isObject());
+        QScriptValue property = object.property("foo");
+        QVERIFY(!property.isValid());
+        property = QScriptValue(2);
+        object.setProperty("foo", property);
+        QVERIFY(object.property("foo").isNumber());
+        QVERIFY(object.property("foo").toNumber() == 2);
+    }
+    {
+        QScriptValue o1 = engine.evaluate("o1 = new Object; o1");
+        QScriptValue o2 = engine.evaluate("o2 = new Object; o2");
+        QVERIFY(engine.evaluate("o1.__proto__ = o2; o1.__proto__ === o2").toBool());
+        QVERIFY(engine.evaluate("o2.foo = 22; o1.foo == 22").toBool());
+        QVERIFY(o1.property("foo").toString() == "22");
+        o2.setProperty("foo", QScriptValue(&engine, 456.0));
+        QVERIFY(engine.evaluate("o1.foo == 456").toBool());
+        QVERIFY(o1.property("foo").isNumber());
+    }
+}
+
+void tst_QScriptValue::getPropertyResolveFlag()
+{
+    QScriptEngine engine;
+    QScriptValue object1 = engine.evaluate("o1 = new Object();");
+    QScriptValue object2 = engine.evaluate("o2 = new Object(); o1.__proto__ = o2; o2");
+    QScriptValue number(&engine, 456.0);
+    QVERIFY(object1.isObject());
+    QVERIFY(object2.isObject());
+    QVERIFY(number.isNumber());
+
+    object2.setProperty("propertyInPrototype", number);
+    QVERIFY(object2.property("propertyInPrototype").isNumber());
+    // default is ResolvePrototype
+    QCOMPARE(object1.property("propertyInPrototype").strictlyEquals(number), true);
+    QCOMPARE(object1.property("propertyInPrototype", QScriptValue::ResolvePrototype)
+             .strictlyEquals(number), true);
+    QCOMPARE(object1.property("propertyInPrototype", QScriptValue::ResolveLocal).isValid(), false);
+}
+
+void tst_QScriptValue::getSetProperty()
+{
+    QScriptEngine eng;
+
+    QScriptValue object = eng.newObject();
+
+    QScriptValue str = QScriptValue(&eng, "bar");
+    object.setProperty("foo", str);
+    QCOMPARE(object.property("foo").toString(), str.toString());
+
+    QScriptValue num = QScriptValue(&eng, 123.0);
+    object.setProperty("baz", num);
+    QCOMPARE(object.property("baz").toNumber(), num.toNumber());
+
+    QScriptValue strstr = QScriptValue("bar");
+    QCOMPARE(strstr.engine(), (QScriptEngine *)0);
+    object.setProperty("foo", strstr);
+    QCOMPARE(object.property("foo").toString(), strstr.toString());
+    QCOMPARE(strstr.engine(), &eng); // the value has been bound to the engine
+
+    QScriptValue numnum = QScriptValue(123.0);
+    object.setProperty("baz", numnum);
+    QCOMPARE(object.property("baz").toNumber(), numnum.toNumber());
+
+    QScriptValue inv;
+    inv.setProperty("foo", num);
+    QCOMPARE(inv.property("foo").isValid(), false);
+
+    QScriptValue array = eng.newArray();
+    array.setProperty(0, num);
+    QCOMPARE(array.property(0).toNumber(), num.toNumber());
+    QCOMPARE(array.property("0").toNumber(), num.toNumber());
+    QCOMPARE(array.property("length").toUInt32(), quint32(1));
+    array.setProperty(1, str);
+    QCOMPARE(array.property(1).toString(), str.toString());
+    QCOMPARE(array.property("1").toString(), str.toString());
+    QCOMPARE(array.property("length").toUInt32(), quint32(2));
+    array.setProperty("length", QScriptValue(&eng, 1));
+    QCOMPARE(array.property("length").toUInt32(), quint32(1));
+    QCOMPARE(array.property(1).isValid(), false);
+
+    // task 162051 -- detecting whether the property is an array index or not
+    QVERIFY(eng.evaluate("a = []; a['00'] = 123; a['00']").strictlyEquals(QScriptValue(&eng, 123)));
+    QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
+    QVERIFY(eng.evaluate("a.hasOwnProperty('00')").strictlyEquals(QScriptValue(&eng, true)));
+    QVERIFY(eng.evaluate("a.hasOwnProperty('0')").strictlyEquals(QScriptValue(&eng, false)));
+    QVERIFY(eng.evaluate("a[0]").isUndefined());
+    QVERIFY(eng.evaluate("a[0.5] = 456; a[0.5]").strictlyEquals(QScriptValue(&eng, 456)));
+    QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
+    QVERIFY(eng.evaluate("a.hasOwnProperty('0.5')").strictlyEquals(QScriptValue(&eng, true)));
+    QVERIFY(eng.evaluate("a[0]").isUndefined());
+    QVERIFY(eng.evaluate("a[0] = 789; a[0]").strictlyEquals(QScriptValue(&eng, 789)));
+    QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 1)));
+
+    // task 183072 -- 0x800000000 is not an array index
+    eng.evaluate("a = []; a[0x800000000] = 123");
+    QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
+    QVERIFY(eng.evaluate("a[0]").isUndefined());
+    QVERIFY(eng.evaluate("a[0x800000000]").strictlyEquals(QScriptValue(&eng, 123)));
+
+    QScriptEngine otherEngine;
+    QScriptValue otherNum = QScriptValue(&otherEngine, 123);
+    QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setProperty() failed: cannot set value created in a different engine");
+    object.setProperty("oof", otherNum);
+    QCOMPARE(object.property("oof").isValid(), false);
+
+    // test ResolveMode
+    QScriptValue object2 = eng.newObject();
+    object.setPrototype(object2);
+    QScriptValue num2 = QScriptValue(&eng, 456.0);
+    object2.setProperty("propertyInPrototype", num2);
+    // default is ResolvePrototype
+    QCOMPARE(object.property("propertyInPrototype")
+             .strictlyEquals(num2), true);
+    QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolvePrototype)
+             .strictlyEquals(num2), true);
+    QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveLocal)
+             .isValid(), false);
+    QEXPECT_FAIL("", "QScriptValue::ResolveScope is not implemented", Continue);
+    QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveScope)
+             .strictlyEquals(num2), false);
+    QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveFull)
+             .strictlyEquals(num2), true);
+
+    // test property removal (setProperty(QScriptValue()))
+    QScriptValue object3 = eng.newObject();
+    object3.setProperty("foo", num);
+    QCOMPARE(object3.property("foo").strictlyEquals(num), true);
+    object3.setProperty("bar", str);
+    QCOMPARE(object3.property("bar").strictlyEquals(str), true);
+    object3.setProperty("foo", QScriptValue());
+    QCOMPARE(object3.property("foo").isValid(), false);
+    QCOMPARE(object3.property("bar").strictlyEquals(str), true);
+    object3.setProperty("foo", num);
+    QCOMPARE(object3.property("foo").strictlyEquals(num), true);
+    QCOMPARE(object3.property("bar").strictlyEquals(str), true);
+    object3.setProperty("bar", QScriptValue());
+    QCOMPARE(object3.property("bar").isValid(), false);
+    QCOMPARE(object3.property("foo").strictlyEquals(num), true);
+    object3.setProperty("foo", QScriptValue());
+    object3.setProperty("foo", QScriptValue());
+
+    eng.globalObject().setProperty("object3", object3);
+    QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
+             .strictlyEquals(QScriptValue(&eng, false)), true);
+    object3.setProperty("foo", num);
+    QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
+             .strictlyEquals(QScriptValue(&eng, true)), true);
+    eng.globalObject().setProperty("object3", QScriptValue());
+    QCOMPARE(eng.evaluate("this.hasOwnProperty('object3')")
+             .strictlyEquals(QScriptValue(&eng, false)), true);
+
+    eng.globalObject().setProperty("object", object);
+
+    // ReadOnly
+    object.setProperty("readOnlyProperty", num, QScriptValue::ReadOnly);
+    // QCOMPARE(object.propertyFlags("readOnlyProperty"), QScriptValue::ReadOnly);
+    QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
+    eng.evaluate("object.readOnlyProperty = !object.readOnlyProperty");
+    QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
+    // Should still be part of enumeration.
+    {
+        QScriptValue ret = eng.evaluate(
+            "found = false;"
+            "for (var p in object) {"
+            "  if (p == 'readOnlyProperty') {"
+            "    found = true; break;"
+            "  }"
+            "} found");
+        QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+    }
+    // should still be deletable
+    {
+        QScriptValue ret = eng.evaluate("delete object.readOnlyProperty");
+        QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+        QCOMPARE(object.property("readOnlyProperty").isValid(), false);
+    }
+
+    // Undeletable
+    object.setProperty("undeletableProperty", num, QScriptValue::Undeletable);
+    // QCOMPARE(object.propertyFlags("undeletableProperty"), QScriptValue::Undeletable);
+    QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
+    {
+        QScriptValue ret = eng.evaluate("delete object.undeletableProperty");
+        QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), false);
+        QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
+    }
+    // should still be writable
+    eng.evaluate("object.undeletableProperty = object.undeletableProperty + 1");
+    QCOMPARE(object.property("undeletableProperty").toNumber(), num.toNumber() + 1);
+    // should still be part of enumeration
+    {
+        QScriptValue ret = eng.evaluate(
+            "found = false;"
+            "for (var p in object) {"
+            "  if (p == 'undeletableProperty') {"
+            "    found = true; break;"
+            "  }"
+            "} found");
+        QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+    }
+    // should still be deletable from C++
+    object.setProperty("undeletableProperty", QScriptValue());
+    QEXPECT_FAIL("", "With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
+    QVERIFY(!object.property("undeletableProperty").isValid());
+    // QEXPECT_FAIL("", "With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
+    // QCOMPARE(object.propertyFlags("undeletableProperty"), 0);
+
+    // SkipInEnumeration
+    object.setProperty("dontEnumProperty", num, QScriptValue::SkipInEnumeration);
+    // QCOMPARE(object.propertyFlags("dontEnumProperty"), QScriptValue::SkipInEnumeration);
+    QCOMPARE(object.property("dontEnumProperty").strictlyEquals(num), true);
+    // should not be part of enumeration
+    {
+        QScriptValue ret = eng.evaluate(
+            "found = false;"
+            "for (var p in object) {"
+            "  if (p == 'dontEnumProperty') {"
+            "    found = true; break;"
+            "  }"
+            "} found");
+        QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, false)), true);
+    }
+    // should still be writable
+    eng.evaluate("object.dontEnumProperty = object.dontEnumProperty + 1");
+    QCOMPARE(object.property("dontEnumProperty").toNumber(), num.toNumber() + 1);
+    // should still be deletable
+    {
+        QScriptValue ret = eng.evaluate("delete object.dontEnumProperty");
+        QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
+        QCOMPARE(object.property("dontEnumProperty").isValid(), false);
+    }
+
+    // change flags
+    object.setProperty("flagProperty", str);
+    // QCOMPARE(object.propertyFlags("flagProperty"), static_cast<QScriptValue::PropertyFlags>(0));
+
+    object.setProperty("flagProperty", str, QScriptValue::ReadOnly);
+    // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly);
+
+    // object.setProperty("flagProperty", str, object.propertyFlags("flagProperty") | QScriptValue::SkipInEnumeration);
+    // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
+
+    object.setProperty("flagProperty", str, QScriptValue::KeepExistingFlags);
+    // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
+
+    object.setProperty("flagProperty", str, QScriptValue::UserRange);
+    // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::UserRange);
+
+    // flags of property in the prototype
+    {
+        QScriptValue object2 = eng.newObject();
+        object2.setPrototype(object);
+        // QCOMPARE(object2.propertyFlags("flagProperty", QScriptValue::ResolveLocal), 0);
+        // QCOMPARE(object2.propertyFlags("flagProperty"), QScriptValue::UserRange);
+    }
+
+    // using interned strings
+    QScriptString foo = eng.toStringHandle("foo");
+
+    object.setProperty(foo, QScriptValue());
+    QVERIFY(!object.property(foo).isValid());
+
+    object.setProperty(foo, num);
+    QVERIFY(object.property(foo).strictlyEquals(num));
+    QVERIFY(object.property("foo").strictlyEquals(num));
+    // QVERIFY(object.propertyFlags(foo) == 0);
+}
+
 void tst_QScriptValue::toStringSimple_data()
 {
     QTest::addColumn<QString>("code");
@@ -431,5 +792,505 @@ void tst_QScriptValue::call()
     QVERIFY(incr.call().isValid()); // Exception.
 }
 
+void tst_QScriptValue::getSetPrototype()
+{
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate("new Object()");
+    QScriptValue object2 = engine.evaluate("new Object()");
+    object2.setPrototype(object);
+    QCOMPARE(object2.prototype().strictlyEquals(object), true);
+
+    QScriptValue inv;
+    inv.setPrototype(object);
+    QCOMPARE(inv.prototype().isValid(), false);
+
+    QScriptEngine otherEngine;
+    QScriptValue object3 = otherEngine.evaluate("new Object()");
+    QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine");
+    object2.setPrototype(object3);
+    QCOMPARE(object2.prototype().strictlyEquals(object), true);
+
+    // cyclic prototypes
+    {
+        QScriptValue ret = engine.evaluate("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
+        QCOMPARE(ret.isError(), true);
+        QCOMPARE(ret.toString(), QLatin1String("Error: cyclic __proto__ value"));
+    }
+    {
+        QScriptValue ret = engine.evaluate("p.__proto__ = { }");
+        QCOMPARE(ret.isError(), false);
+    }
+
+    QScriptValue old = object.prototype();
+    QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cyclic prototype value");
+    object.setPrototype(object);
+    QCOMPARE(object.prototype().strictlyEquals(old), true);
+
+    object2.setPrototype(object);
+    QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cyclic prototype value");
+    object.setPrototype(object2);
+    QCOMPARE(object.prototype().strictlyEquals(old), true);
+}
+
+void tst_QScriptValue::toObjectSimple()
+{
+    QScriptEngine eng;
+
+    QScriptValue undefined = eng.undefinedValue();
+    QCOMPARE(undefined.toObject().isValid(), false);
+    QScriptValue null = eng.nullValue();
+    QCOMPARE(null.toObject().isValid(), false);
+    QCOMPARE(QScriptValue().toObject().isValid(), false);
+
+    QScriptValue falskt = QScriptValue(&eng, false);
+    {
+        QScriptValue tmp = falskt.toObject();
+        QCOMPARE(tmp.isObject(), true);
+        QCOMPARE(falskt.isObject(), false);
+        QCOMPARE(tmp.toNumber(), falskt.toNumber());
+    }
+
+    QScriptValue sant = QScriptValue(&eng, true);
+    {
+        QScriptValue tmp = sant.toObject();
+        QCOMPARE(tmp.isObject(), true);
+        QCOMPARE(sant.isObject(), false);
+        QCOMPARE(tmp.toNumber(), sant.toNumber());
+    }
+
+    QScriptValue number = QScriptValue(&eng, 123.0);
+    {
+        QScriptValue tmp = number.toObject();
+        QCOMPARE(tmp.isObject(), true);
+        QCOMPARE(number.isObject(), false);
+        QCOMPARE(tmp.toNumber(), number.toNumber());
+    }
+
+    QScriptValue str = QScriptValue(&eng, QString("ciao"));
+    {
+        QScriptValue tmp = str.toObject();
+        QCOMPARE(tmp.isObject(), true);
+        QCOMPARE(str.isObject(), false);
+        QCOMPARE(tmp.toString(), str.toString());
+    }
+
+
+    QScriptValue object = eng.evaluate("new Object");
+    {
+        QScriptValue tmp = object.toObject();
+        QVERIFY(tmp.strictlyEquals(object));
+        QCOMPARE(tmp.isObject(), true);
+    }
+
+
+    // V2 constructors: in this case, you have to use QScriptEngine::toObject()
+    {
+        QScriptValue undefined = QScriptValue(QScriptValue::UndefinedValue);
+        QVERIFY(!undefined.toObject().isValid());
+        QVERIFY(!eng.toObject(undefined).isValid());
+        QVERIFY(!undefined.engine());
+
+        QScriptValue null = QScriptValue(QScriptValue::NullValue);
+        QVERIFY(!null.toObject().isValid());
+        QVERIFY(!eng.toObject(null).isValid());
+        QVERIFY(!null.engine());
+
+        QScriptValue falskt = QScriptValue(false);
+        QVERIFY(!falskt.toObject().isValid());
+        QCOMPARE(falskt.isObject(), false);
+        QVERIFY(!falskt.engine());
+        {
+            QScriptValue tmp = eng.toObject(falskt);
+            QVERIFY(tmp.isObject());
+            QVERIFY(tmp.toBool());
+            QVERIFY(!falskt.isObject());
+        }
+
+        QScriptValue sant = QScriptValue(true);
+        QVERIFY(!sant.toObject().isValid());
+        QCOMPARE(sant.isObject(), false);
+        QVERIFY(!sant.engine());
+        {
+            QScriptValue tmp = eng.toObject(sant);
+            QVERIFY(tmp.isObject());
+            QVERIFY(tmp.toBool());
+            QVERIFY(!sant.isObject());
+        }
+
+        QScriptValue number = QScriptValue(123.0);
+        QVERIFY(!number.toObject().isValid());
+        QVERIFY(!number.engine());
+        QCOMPARE(number.isObject(), false);
+        {
+            QScriptValue tmp = eng.toObject(number);
+            QVERIFY(tmp.isObject());
+            QCOMPARE(tmp.toInt32(), number.toInt32());
+            QVERIFY(!number.isObject());
+        }
+
+        QScriptValue str = QScriptValue(QString::fromLatin1("ciao"));
+        QVERIFY(!str.toObject().isValid());
+        QVERIFY(!str.engine());
+        QCOMPARE(str.isObject(), false);
+        {
+            QScriptValue tmp = eng.toObject(str);
+            QVERIFY(tmp.isObject());
+            QCOMPARE(tmp.toString(), QString::fromLatin1("ciao"));
+            QVERIFY(!str.isObject());
+        }
+    }
+}
+
+void tst_QScriptValue::setProperty_data()
+{
+    QTest::addColumn<QScriptValue>("property");
+    QTest::addColumn<int>("flag");
+
+    QTest::newRow("int + keepExistingFlags") << QScriptValue(123456) << static_cast<int>(QScriptValue::KeepExistingFlags);
+    QTest::newRow("int + undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::Undeletable);
+    QTest::newRow("int + readOnly") << QScriptValue(123456) << static_cast<int>(QScriptValue::ReadOnly);
+    QTest::newRow("int + readOnly|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable);
+    QTest::newRow("int + skipInEnumeration") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration);
+    QTest::newRow("int + skipInEnumeration|readOnly") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly);
+    QTest::newRow("int + skipInEnumeration|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
+    QTest::newRow("int + skipInEnumeration|readOnly|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly | QScriptValue::Undeletable);
+}
+
+void tst_QScriptValue::setProperty()
+{
+    QFETCH(QScriptValue, property);
+    QFETCH(int, flag);
+    QScriptValue::PropertyFlags flags = static_cast<QScriptValue::PropertyFlag>(flag);
+
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate("o = new Object; o");
+    QScriptValue proto = engine.evaluate("p = new Object; o.__proto__ = p; p");
+    engine.evaluate("o.defined1 = 1");
+    engine.evaluate("o.defined2 = 1");
+    engine.evaluate("o[5] = 1");
+    engine.evaluate("p.overloaded1 = 1");
+    engine.evaluate("o.overloaded1 = 2");
+    engine.evaluate("p[6] = 1");
+    engine.evaluate("o[6] = 2");
+    engine.evaluate("p.overloaded2 = 1");
+    engine.evaluate("o.overloaded2 = 2");
+    engine.evaluate("p.overloaded3 = 1");
+    engine.evaluate("o.overloaded3 = 2");
+    engine.evaluate("p[7] = 1");
+    engine.evaluate("o[7] = 2");
+    engine.evaluate("p.overloaded4 = 1");
+    engine.evaluate("o.overloaded4 = 2");
+
+    // tries to set undefined property directly on object.
+    object.setProperty(QString::fromAscii("undefined1"), property, flags);
+    QVERIFY(engine.evaluate("o.undefined1").strictlyEquals(property));
+    object.setProperty(engine.toStringHandle("undefined2"), property, flags);
+    QVERIFY(object.property("undefined2").strictlyEquals(property));
+    object.setProperty(4, property, flags);
+    QVERIFY(object.property(4).strictlyEquals(property));
+
+    // tries to set defined property directly on object
+    object.setProperty("defined1", property, flags);
+    QVERIFY(engine.evaluate("o.defined1").strictlyEquals(property));
+    object.setProperty(engine.toStringHandle("defined2"), property, flags);
+    QVERIFY(object.property("defined2").strictlyEquals(property));
+    object.setProperty(5, property, flags);
+    QVERIFY(object.property(5).strictlyEquals(property));
+
+    // tries to set overloaded property directly on object
+    object.setProperty("overloaded1", property, flags);
+    QVERIFY(engine.evaluate("o.overloaded1").strictlyEquals(property));
+    object.setProperty(engine.toStringHandle("overloaded2"), property, flags);
+    QVERIFY(object.property("overloaded2").strictlyEquals(property));
+    object.setProperty(6, property, flags);
+    QVERIFY(object.property(6).strictlyEquals(property));
+
+    // tries to set overloaded property directly on prototype
+    proto.setProperty("overloaded3", property, flags);
+    QVERIFY(!engine.evaluate("o.overloaded3").strictlyEquals(property));
+    proto.setProperty(engine.toStringHandle("overloaded4"), property, flags);
+    QVERIFY(!object.property("overloaded4").strictlyEquals(property));
+    proto.setProperty(7, property, flags);
+    QVERIFY(!object.property(7).strictlyEquals(property));
+
+    // tries to set undefined property directly on prototype
+    proto.setProperty("undefined3", property, flags);
+    QVERIFY(engine.evaluate("o.undefined3").strictlyEquals(property));
+    proto.setProperty(engine.toStringHandle("undefined4"), property, flags);
+    QVERIFY(object.property("undefined4").strictlyEquals(property));
+    proto.setProperty(8, property, flags);
+    QVERIFY(object.property(8).strictlyEquals(property));
+
+    bool readOnly = flags & QScriptValue::ReadOnly;
+    bool skipInEnumeration = flags & QScriptValue::SkipInEnumeration;
+    bool undeletable = flags & QScriptValue::Undeletable;
+
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '4').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '5').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '6').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '7').writable").toBool());
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '8').writable").toBool());
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined1').writable").toBool());
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined2').writable").toBool());
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined3').writable").toBool());
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined4').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined1').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined2').writable").toBool());
+    QVERIFY(engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined1').writable").toBool());
+    QVERIFY(engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined1').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded3').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded4').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded1').writable").toBool());
+    QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded2').writable").toBool());
+    QVERIFY(!engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded3').writable").toBool());
+    QVERIFY(!engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded4').writable").toBool());
+
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '4').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '5').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '6').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '7').configurable").toBool());
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '8').configurable").toBool());
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined1').configurable").toBool());
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined2').configurable").toBool());
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined3').configurable").toBool());
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined4').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined1').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined2').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded1').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded2').configurable").toBool());
+    QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(p, 'overloaded1').configurable").toBool());
+    QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(p, 'overloaded2').configurable").toBool());
+    QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded3').configurable").toBool());
+    QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded4').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded3').configurable").toBool());
+    QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded4').configurable").toBool());
+
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '4').enumerable").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '5').enumerable").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '6').enumerable").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, '7').enumerable").toBool());
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, '8').enumerable").toBool());
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'undefined1').enumerable").toBool());
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'undefined2').enumerable").toBool());
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, 'undefined3').enumerable").toBool());
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, 'undefined4').enumerable").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded1').enumerable").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded2').enumerable").toBool());
+    QVERIFY(engine.evaluate("p.propertyIsEnumerable('overloaded1')").toBool());
+    QVERIFY(engine.evaluate("p.propertyIsEnumerable('overloaded2')").toBool());
+    QVERIFY(engine.evaluate("o.propertyIsEnumerable('overloaded3')").toBool());
+    QVERIFY(engine.evaluate("o.propertyIsEnumerable('overloaded4')").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("p.propertyIsEnumerable('overloaded3')").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("p.propertyIsEnumerable('overloaded4')").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("o.propertyIsEnumerable('defined1')").toBool());
+    QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
+    QVERIFY(skipInEnumeration != engine.evaluate("o.propertyIsEnumerable('defined2')").toBool());
+}
+
+void tst_QScriptValue::propertyFlag_data()
+{
+    QTest::addColumn<QString>("name");
+    QTest::addColumn<int>("flag");
+
+    QTest::newRow("?Cr@jzi!%$") << "?Cr@jzi!%$" << static_cast<int>(0);
+    QTest::newRow("ReadOnly") << "ReadOnly" << static_cast<int>(QScriptValue::ReadOnly);
+    QTest::newRow("Undeletable") << "Undeletable" << static_cast<int>(QScriptValue::Undeletable);
+    QTest::newRow("SkipInEnumeration") << "SkipInEnumeration" << static_cast<int>(QScriptValue::SkipInEnumeration);
+    QTest::newRow("ReadOnly | Undeletable") << "ReadOnly_Undeletable" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable);
+    QTest::newRow("ReadOnly | SkipInEnumeration") << "ReadOnly_SkipInEnumeration" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
+    QTest::newRow("Undeletable | SkipInEnumeration") << "Undeletable_SkipInEnumeration" << static_cast<int>(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+    QTest::newRow("ReadOnly | Undeletable | SkipInEnumeration") << "ReadOnly_Undeletable_SkipInEnumeration" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+}
+
+void tst_QScriptValue::propertyFlag()
+{
+    QScriptEngine engine;
+    QFETCH(QString, name);
+    QFETCH(int, flag);
+    const QScriptString nameHandle = engine.toStringHandle(name);
+    const QString protoName = "proto" + name;
+    const QScriptString protoNameHandle = engine.toStringHandle(protoName);
+
+    QScriptValue proto = engine.newObject();
+    QScriptValue object = engine.newObject();
+    object.setPrototype(proto);
+
+    proto.setProperty(protoName, QScriptValue(124816), QScriptValue::PropertyFlag(flag));
+    object.setProperty(name, QScriptValue(124816), QScriptValue::PropertyFlag(flag));
+
+    // Check using QString name
+    QCOMPARE(object.propertyFlags(name), QScriptValue::PropertyFlag(flag));
+    QCOMPARE(object.propertyFlags(protoName, QScriptValue::ResolvePrototype), QScriptValue::PropertyFlag(flag));
+    QVERIFY(!object.propertyFlags(protoName, QScriptValue::ResolveLocal));
+
+    // Check using QScriptString name
+    QCOMPARE(object.propertyFlags(nameHandle), QScriptValue::PropertyFlag(flag));
+    QCOMPARE(object.propertyFlags(protoNameHandle, QScriptValue::ResolvePrototype), QScriptValue::PropertyFlag(flag));
+    QVERIFY(!object.propertyFlags(protoNameHandle, QScriptValue::ResolveLocal));
+}
+
+void tst_QScriptValue::globalObjectChanges()
+{
+    // API functionality shouldn't depend on Global Object.
+    QScriptEngine engine;
+    QScriptValue array = engine.newArray();
+    QScriptValue error = engine.evaluate("new Error");
+    QScriptValue object = engine.newObject();
+
+    object.setProperty("foo", 512);
+
+    // Remove properties form global object.
+    engine.evaluate("delete Object; delete Error; delete Array;");
+
+    QVERIFY(array.isArray());
+    QVERIFY(error.isError());
+    QVERIFY(object.isObject());
+
+    QVERIFY(object.property("foo").isValid());
+    QVERIFY(object.property("foo", QScriptValue::ResolveLocal).isValid());
+    object.setProperty("foo", QScriptValue());
+    QVERIFY(!object.property("foo").isValid());
+    QVERIFY(!object.property("foo", QScriptValue::ResolveLocal).isValid());
+}
+
+void tst_QScriptValue::assignAndCopyConstruct_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine;
+    // Copy & assign code is the same for all types, so it is enough to check only a few value.
+    for (unsigned i = 0; i < 10; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second;
+    }
+}
+
+void tst_QScriptValue::assignAndCopyConstruct()
+{
+    QFETCH(QScriptValue, value);
+    QScriptValue copy(value);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Abort);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Abort);
+    QCOMPARE(copy.strictlyEquals(value), !value.isNumber() || !qIsNaN(value.toNumber()));
+    QCOMPARE(copy.engine(), value.engine());
+
+    QScriptValue assigned = copy;
+    QCOMPARE(assigned.strictlyEquals(value), !copy.isNumber() || !qIsNaN(copy.toNumber()));
+    QCOMPARE(assigned.engine(), assigned.engine());
+
+    QScriptValue other(!value.toBool());
+    assigned = other;
+    QVERIFY(!assigned.strictlyEquals(copy));
+    QVERIFY(assigned.strictlyEquals(other));
+    QCOMPARE(assigned.engine(), other.engine());
+}
 
 QTEST_MAIN(tst_QScriptValue)
index 28154a98238472b4cb51b0594d3839a9ec104059..7b7d9bcecfd2e5ad606944c58af7a1313b096b47 100644 (file)
 #include <QtCore/qnumeric.h>
 #include <QtTest/qtest.h>
 
+#define DEFINE_TEST_VALUE(expr) m_values.insert(QString::fromLatin1(#expr), expr)
+
 Q_DECLARE_METATYPE(QScriptValue*);
 Q_DECLARE_METATYPE(QScriptValue);
+typedef QPair<QString, QScriptValue> QPairQStringAndQScriptValue;
+Q_DECLARE_METATYPE(QPairQStringAndQScriptValue);
 
 class tst_QScriptValue : public QObject {
     Q_OBJECT
@@ -45,16 +49,36 @@ private slots:
     void dataSharing();
     void constructors_data();
     void constructors();
+    void getSetPrototype();
     void call();
     void ctor();
+    void toObjectSimple();
+    void getPropertySimple_data();
+    void getPropertySimple();
+    void setPropertySimple();
+    void setProperty_data();
+    void setProperty();
+    void getSetProperty();
+    void getPropertyResolveFlag();
+    void propertyFlag_data();
+    void propertyFlag();
+    void globalObjectChanges();
+    void assignAndCopyConstruct_data();
+    void assignAndCopyConstruct();
 
     // Generated test functions.
+    void isArray_data();
+    void isArray();
+
     void isBool_data();
     void isBool();
 
     void isBoolean_data();
     void isBoolean();
 
+    void isError_data();
+    void isError();
+
     void isNumber_data();
     void isNumber();
 
@@ -100,97 +124,20 @@ private slots:
     void toUInt16_data();
     void toUInt16();
 
-private:
-    typedef void (tst_QScriptValue::*InitDataFunction)();
-    typedef void (tst_QScriptValue::*DefineDataFunction)(const char*);
-    void dataHelper(InitDataFunction init, DefineDataFunction define);
-    QTestData& newRow(const char* tag);
-
-    typedef void (tst_QScriptValue::*TestFunction)(const char*, const QScriptValue&);
-    void testHelper(TestFunction fun);
-
-    // Generated functions
-
-    void initScriptValues();
-
-    void isBool_initData();
-    void isBool_makeData(const char* expr);
-    void isBool_test(const char* expr, const QScriptValue& value);
-
-    void isBoolean_initData();
-    void isBoolean_makeData(const char* expr);
-    void isBoolean_test(const char* expr, const QScriptValue& value);
-
-    void isNumber_initData();
-    void isNumber_makeData(const char* expr);
-    void isNumber_test(const char* expr, const QScriptValue&);
-
-    void isFunction_initData();
-    void isFunction_makeData(const char* expr);
-    void isFunction_test(const char* expr, const QScriptValue& value);
-
-    void isNull_initData();
-    void isNull_makeData(const char* expr);
-    void isNull_test(const char* expr, const QScriptValue& value);
-
-    void isObject_initData();
-    void isObject_makeData(const char* expr);
-    void isObject_test(const char* expr, const QScriptValue& value);
+    void equals_data();
+    void equals();
 
-    void isString_initData();
-    void isString_makeData(const char* expr);
-    void isString_test(const char* expr, const QScriptValue& value);
+    void strictlyEquals_data();
+    void strictlyEquals();
 
-    void isUndefined_initData();
-    void isUndefined_makeData(const char* expr);
-    void isUndefined_test(const char* expr, const QScriptValue& value);
-
-    void isValid_initData();
-    void isValid_makeData(const char* expr);
-    void isValid_test(const char* expr, const QScriptValue& value);
-
-    void toString_initData();
-    void toString_makeData(const char*);
-    void toString_test(const char*, const QScriptValue&);
-
-    void toNumber_initData();
-    void toNumber_makeData(const char*);
-    void toNumber_test(const char*, const QScriptValue&);
-
-    void toBool_initData();
-    void toBool_makeData(const char*);
-    void toBool_test(const char*, const QScriptValue&);
-
-    void toBoolean_initData();
-    void toBoolean_makeData(const char*);
-    void toBoolean_test(const char*, const QScriptValue&);
-
-    void toInteger_initData();
-    void toInteger_makeData(const char*);
-    void toInteger_test(const char*, const QScriptValue&);
-
-    void toInt32_initData();
-    void toInt32_makeData(const char*);
-    void toInt32_test(const char*, const QScriptValue&);
-
-    void toUInt32_initData();
-    void toUInt32_makeData(const char*);
-    void toUInt32_test(const char*, const QScriptValue&);
-
-    void toUInt16_initData();
-    void toUInt16_makeData(const char*);
-    void toUInt16_test(const char*, const QScriptValue&);
+    void instanceOf_data();
+    void instanceOf();
 
 private:
-    QScriptEngine* engine;
-    QHash<QString, QScriptValue> m_values;
-    QString m_currentExpression;
-};
-
-#define DEFINE_TEST_FUNCTION(name) \
-void tst_QScriptValue::name##_data() { dataHelper(&tst_QScriptValue::name##_initData, &tst_QScriptValue::name##_makeData); } \
-void tst_QScriptValue::name() { testHelper(&tst_QScriptValue::name##_test); }
-
+    // Generated function
+    QPair<QString, QScriptValue> initScriptValues(uint idx);
 
+    QScriptEngine* m_engine;
+};
 
 #endif // tst_qscriptvalue_h
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp
deleted file mode 100644 (file)
index 970c960..0000000
+++ /dev/null
@@ -1,1922 +0,0 @@
-/*
-    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public License
-    along with this library; see the file COPYING.LIB.  If not, write to
-    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-    Boston, MA 02110-1301, USA.
-*/
-
-#include "tst_qscriptvalue.h"
-
-#define DEFINE_TEST_VALUE(expr) m_values.insert(QString::fromLatin1(#expr), expr)
-
-void tst_QScriptValue::initScriptValues()
-{
-    m_values.clear();
-    if (engine)
-        delete engine;
-    engine = new QScriptEngine;
-    DEFINE_TEST_VALUE(QScriptValue());
-    DEFINE_TEST_VALUE(QScriptValue(QScriptValue::UndefinedValue));
-    DEFINE_TEST_VALUE(QScriptValue(QScriptValue::NullValue));
-    DEFINE_TEST_VALUE(QScriptValue(true));
-    DEFINE_TEST_VALUE(QScriptValue(false));
-    DEFINE_TEST_VALUE(QScriptValue(int(122)));
-    DEFINE_TEST_VALUE(QScriptValue(uint(124)));
-    DEFINE_TEST_VALUE(QScriptValue(0));
-    DEFINE_TEST_VALUE(QScriptValue(0.0));
-    DEFINE_TEST_VALUE(QScriptValue(123.0));
-    DEFINE_TEST_VALUE(QScriptValue(6.37e-8));
-    DEFINE_TEST_VALUE(QScriptValue(-6.37e-8));
-    DEFINE_TEST_VALUE(QScriptValue(0x43211234));
-    DEFINE_TEST_VALUE(QScriptValue(0x10000));
-    DEFINE_TEST_VALUE(QScriptValue(0x10001));
-    DEFINE_TEST_VALUE(QScriptValue(qSNaN()));
-    DEFINE_TEST_VALUE(QScriptValue(qQNaN()));
-    DEFINE_TEST_VALUE(QScriptValue(qInf()));
-    DEFINE_TEST_VALUE(QScriptValue(-qInf()));
-    DEFINE_TEST_VALUE(QScriptValue("NaN"));
-    DEFINE_TEST_VALUE(QScriptValue("Infinity"));
-    DEFINE_TEST_VALUE(QScriptValue("-Infinity"));
-    DEFINE_TEST_VALUE(QScriptValue("ciao"));
-    DEFINE_TEST_VALUE(QScriptValue(QString::fromLatin1("ciao")));
-    DEFINE_TEST_VALUE(QScriptValue(QString("")));
-    DEFINE_TEST_VALUE(QScriptValue(QString()));
-    DEFINE_TEST_VALUE(QScriptValue(QString("0")));
-    DEFINE_TEST_VALUE(QScriptValue(QString("123")));
-    DEFINE_TEST_VALUE(QScriptValue(QString("12.4")));
-    DEFINE_TEST_VALUE(QScriptValue(0, QScriptValue::UndefinedValue));
-    DEFINE_TEST_VALUE(QScriptValue(0, QScriptValue::NullValue));
-    DEFINE_TEST_VALUE(QScriptValue(0, true));
-    DEFINE_TEST_VALUE(QScriptValue(0, false));
-    DEFINE_TEST_VALUE(QScriptValue(0, int(122)));
-    DEFINE_TEST_VALUE(QScriptValue(0, uint(124)));
-    DEFINE_TEST_VALUE(QScriptValue(0, 0));
-    DEFINE_TEST_VALUE(QScriptValue(0, 0.0));
-    DEFINE_TEST_VALUE(QScriptValue(0, 123.0));
-    DEFINE_TEST_VALUE(QScriptValue(0, 6.37e-8));
-    DEFINE_TEST_VALUE(QScriptValue(0, -6.37e-8));
-    DEFINE_TEST_VALUE(QScriptValue(0, 0x43211234));
-    DEFINE_TEST_VALUE(QScriptValue(0, 0x10000));
-    DEFINE_TEST_VALUE(QScriptValue(0, 0x10001));
-    DEFINE_TEST_VALUE(QScriptValue(0, qSNaN()));
-    DEFINE_TEST_VALUE(QScriptValue(0, qQNaN()));
-    DEFINE_TEST_VALUE(QScriptValue(0, qInf()));
-    DEFINE_TEST_VALUE(QScriptValue(0, -qInf()));
-    DEFINE_TEST_VALUE(QScriptValue(0, "NaN"));
-    DEFINE_TEST_VALUE(QScriptValue(0, "Infinity"));
-    DEFINE_TEST_VALUE(QScriptValue(0, "-Infinity"));
-    DEFINE_TEST_VALUE(QScriptValue(0, "ciao"));
-    DEFINE_TEST_VALUE(QScriptValue(0, QString::fromLatin1("ciao")));
-    DEFINE_TEST_VALUE(QScriptValue(0, QString("")));
-    DEFINE_TEST_VALUE(QScriptValue(0, QString()));
-    DEFINE_TEST_VALUE(QScriptValue(0, QString("0")));
-    DEFINE_TEST_VALUE(QScriptValue(0, QString("123")));
-    DEFINE_TEST_VALUE(QScriptValue(0, QString("12.3")));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QScriptValue::UndefinedValue));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QScriptValue::NullValue));
-    DEFINE_TEST_VALUE(QScriptValue(engine, true));
-    DEFINE_TEST_VALUE(QScriptValue(engine, false));
-    DEFINE_TEST_VALUE(QScriptValue(engine, int(122)));
-    DEFINE_TEST_VALUE(QScriptValue(engine, uint(124)));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 0));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 0.0));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 123.0));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 6.37e-8));
-    DEFINE_TEST_VALUE(QScriptValue(engine, -6.37e-8));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 0x43211234));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 0x10000));
-    DEFINE_TEST_VALUE(QScriptValue(engine, 0x10001));
-    DEFINE_TEST_VALUE(QScriptValue(engine, qSNaN()));
-    DEFINE_TEST_VALUE(QScriptValue(engine, qQNaN()));
-    DEFINE_TEST_VALUE(QScriptValue(engine, qInf()));
-    DEFINE_TEST_VALUE(QScriptValue(engine, -qInf()));
-    DEFINE_TEST_VALUE(QScriptValue(engine, "NaN"));
-    DEFINE_TEST_VALUE(QScriptValue(engine, "Infinity"));
-    DEFINE_TEST_VALUE(QScriptValue(engine, "-Infinity"));
-    DEFINE_TEST_VALUE(QScriptValue(engine, "ciao"));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QString::fromLatin1("ciao")));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QString("")));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QString()));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QString("0")));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QString("123")));
-    DEFINE_TEST_VALUE(QScriptValue(engine, QString("1.23")));
-    DEFINE_TEST_VALUE(engine->evaluate("[]"));
-    DEFINE_TEST_VALUE(engine->evaluate("{}"));
-    DEFINE_TEST_VALUE(engine->evaluate("Object.prototype"));
-    DEFINE_TEST_VALUE(engine->evaluate("Date.prototype"));
-    DEFINE_TEST_VALUE(engine->evaluate("Array.prototype"));
-    DEFINE_TEST_VALUE(engine->evaluate("Function.prototype"));
-    DEFINE_TEST_VALUE(engine->evaluate("Error.prototype"));
-    DEFINE_TEST_VALUE(engine->evaluate("Object"));
-    DEFINE_TEST_VALUE(engine->evaluate("Array"));
-    DEFINE_TEST_VALUE(engine->evaluate("Number"));
-    DEFINE_TEST_VALUE(engine->evaluate("Function"));
-    DEFINE_TEST_VALUE(engine->evaluate("(function() { return 1; })"));
-    DEFINE_TEST_VALUE(engine->evaluate("(function() { return 'ciao'; })"));
-    DEFINE_TEST_VALUE(engine->evaluate("(function() { throw new Error('foo'); })"));
-    DEFINE_TEST_VALUE(engine->evaluate("/foo/"));
-    DEFINE_TEST_VALUE(engine->evaluate("new Object()"));
-    DEFINE_TEST_VALUE(engine->evaluate("new Array()"));
-    DEFINE_TEST_VALUE(engine->evaluate("new Error()"));
-    DEFINE_TEST_VALUE(engine->evaluate("a = new Object(); a.foo = 22; a.foo"));
-    DEFINE_TEST_VALUE(engine->evaluate("Undefined"));
-    DEFINE_TEST_VALUE(engine->evaluate("Null"));
-    DEFINE_TEST_VALUE(engine->evaluate("True"));
-    DEFINE_TEST_VALUE(engine->evaluate("False"));
-    DEFINE_TEST_VALUE(engine->evaluate("undefined"));
-    DEFINE_TEST_VALUE(engine->evaluate("null"));
-    DEFINE_TEST_VALUE(engine->evaluate("true"));
-    DEFINE_TEST_VALUE(engine->evaluate("false"));
-    DEFINE_TEST_VALUE(engine->evaluate("122"));
-    DEFINE_TEST_VALUE(engine->evaluate("124"));
-    DEFINE_TEST_VALUE(engine->evaluate("0"));
-    DEFINE_TEST_VALUE(engine->evaluate("0.0"));
-    DEFINE_TEST_VALUE(engine->evaluate("123.0"));
-    DEFINE_TEST_VALUE(engine->evaluate("6.37e-8"));
-    DEFINE_TEST_VALUE(engine->evaluate("-6.37e-8"));
-    DEFINE_TEST_VALUE(engine->evaluate("0x43211234"));
-    DEFINE_TEST_VALUE(engine->evaluate("0x10000"));
-    DEFINE_TEST_VALUE(engine->evaluate("0x10001"));
-    DEFINE_TEST_VALUE(engine->evaluate("NaN"));
-    DEFINE_TEST_VALUE(engine->evaluate("Infinity"));
-    DEFINE_TEST_VALUE(engine->evaluate("-Infinity"));
-    DEFINE_TEST_VALUE(engine->evaluate("'ciao'"));
-    DEFINE_TEST_VALUE(engine->evaluate("''"));
-    DEFINE_TEST_VALUE(engine->evaluate("'0'"));
-    DEFINE_TEST_VALUE(engine->evaluate("'123'"));
-    DEFINE_TEST_VALUE(engine->evaluate("'12.4'"));
-    DEFINE_TEST_VALUE(engine->nullValue());
-    DEFINE_TEST_VALUE(engine->undefinedValue());
-}
-
-
-void tst_QScriptValue::isValid_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isValid_makeData(const char* expr)
-{
-    static QSet<QString> isValid;
-    if (isValid.isEmpty()) {
-        isValid << "QScriptValue(QScriptValue::UndefinedValue)"
-                << "QScriptValue(QScriptValue::NullValue)"
-                << "QScriptValue(true)"
-                << "QScriptValue(false)"
-                << "QScriptValue(int(122))"
-                << "QScriptValue(uint(124))"
-                << "QScriptValue(0)"
-                << "QScriptValue(0.0)"
-                << "QScriptValue(123.0)"
-                << "QScriptValue(6.37e-8)"
-                << "QScriptValue(-6.37e-8)"
-                << "QScriptValue(0x43211234)"
-                << "QScriptValue(0x10000)"
-                << "QScriptValue(0x10001)"
-                << "QScriptValue(qSNaN())"
-                << "QScriptValue(qQNaN())"
-                << "QScriptValue(qInf())"
-                << "QScriptValue(-qInf())"
-                << "QScriptValue(\"NaN\")"
-                << "QScriptValue(\"Infinity\")"
-                << "QScriptValue(\"-Infinity\")"
-                << "QScriptValue(\"ciao\")"
-                << "QScriptValue(QString::fromLatin1(\"ciao\"))"
-                << "QScriptValue(QString(\"\"))"
-                << "QScriptValue(QString())"
-                << "QScriptValue(QString(\"0\"))"
-                << "QScriptValue(QString(\"123\"))"
-                << "QScriptValue(QString(\"12.4\"))"
-                << "QScriptValue(0, QScriptValue::UndefinedValue)"
-                << "QScriptValue(0, QScriptValue::NullValue)"
-                << "QScriptValue(0, true)"
-                << "QScriptValue(0, false)"
-                << "QScriptValue(0, int(122))"
-                << "QScriptValue(0, uint(124))"
-                << "QScriptValue(0, 0)"
-                << "QScriptValue(0, 0.0)"
-                << "QScriptValue(0, 123.0)"
-                << "QScriptValue(0, 6.37e-8)"
-                << "QScriptValue(0, -6.37e-8)"
-                << "QScriptValue(0, 0x43211234)"
-                << "QScriptValue(0, 0x10000)"
-                << "QScriptValue(0, 0x10001)"
-                << "QScriptValue(0, qSNaN())"
-                << "QScriptValue(0, qQNaN())"
-                << "QScriptValue(0, qInf())"
-                << "QScriptValue(0, -qInf())"
-                << "QScriptValue(0, \"NaN\")"
-                << "QScriptValue(0, \"Infinity\")"
-                << "QScriptValue(0, \"-Infinity\")"
-                << "QScriptValue(0, \"ciao\")"
-                << "QScriptValue(0, QString::fromLatin1(\"ciao\"))"
-                << "QScriptValue(0, QString(\"\"))"
-                << "QScriptValue(0, QString())"
-                << "QScriptValue(0, QString(\"0\"))"
-                << "QScriptValue(0, QString(\"123\"))"
-                << "QScriptValue(0, QString(\"12.3\"))"
-                << "QScriptValue(engine, QScriptValue::UndefinedValue)"
-                << "QScriptValue(engine, QScriptValue::NullValue)"
-                << "QScriptValue(engine, true)"
-                << "QScriptValue(engine, false)"
-                << "QScriptValue(engine, int(122))"
-                << "QScriptValue(engine, uint(124))"
-                << "QScriptValue(engine, 0)"
-                << "QScriptValue(engine, 0.0)"
-                << "QScriptValue(engine, 123.0)"
-                << "QScriptValue(engine, 6.37e-8)"
-                << "QScriptValue(engine, -6.37e-8)"
-                << "QScriptValue(engine, 0x43211234)"
-                << "QScriptValue(engine, 0x10000)"
-                << "QScriptValue(engine, 0x10001)"
-                << "QScriptValue(engine, qSNaN())"
-                << "QScriptValue(engine, qQNaN())"
-                << "QScriptValue(engine, qInf())"
-                << "QScriptValue(engine, -qInf())"
-                << "QScriptValue(engine, \"NaN\")"
-                << "QScriptValue(engine, \"Infinity\")"
-                << "QScriptValue(engine, \"-Infinity\")"
-                << "QScriptValue(engine, \"ciao\")"
-                << "QScriptValue(engine, QString::fromLatin1(\"ciao\"))"
-                << "QScriptValue(engine, QString(\"\"))"
-                << "QScriptValue(engine, QString())"
-                << "QScriptValue(engine, QString(\"0\"))"
-                << "QScriptValue(engine, QString(\"123\"))"
-                << "QScriptValue(engine, QString(\"1.23\"))"
-                << "engine->evaluate(\"[]\")"
-                << "engine->evaluate(\"{}\")"
-                << "engine->evaluate(\"Object.prototype\")"
-                << "engine->evaluate(\"Date.prototype\")"
-                << "engine->evaluate(\"Array.prototype\")"
-                << "engine->evaluate(\"Function.prototype\")"
-                << "engine->evaluate(\"Error.prototype\")"
-                << "engine->evaluate(\"Object\")"
-                << "engine->evaluate(\"Array\")"
-                << "engine->evaluate(\"Number\")"
-                << "engine->evaluate(\"Function\")"
-                << "engine->evaluate(\"(function() { return 1; })\")"
-                << "engine->evaluate(\"(function() { return 'ciao'; })\")"
-                << "engine->evaluate(\"(function() { throw new Error('foo'); })\")"
-                << "engine->evaluate(\"/foo/\")"
-                << "engine->evaluate(\"new Object()\")"
-                << "engine->evaluate(\"new Array()\")"
-                << "engine->evaluate(\"new Error()\")"
-                << "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")"
-                << "engine->evaluate(\"Undefined\")"
-                << "engine->evaluate(\"Null\")"
-                << "engine->evaluate(\"True\")"
-                << "engine->evaluate(\"False\")"
-                << "engine->evaluate(\"undefined\")"
-                << "engine->evaluate(\"null\")"
-                << "engine->evaluate(\"true\")"
-                << "engine->evaluate(\"false\")"
-                << "engine->evaluate(\"122\")"
-                << "engine->evaluate(\"124\")"
-                << "engine->evaluate(\"0\")"
-                << "engine->evaluate(\"0.0\")"
-                << "engine->evaluate(\"123.0\")"
-                << "engine->evaluate(\"6.37e-8\")"
-                << "engine->evaluate(\"-6.37e-8\")"
-                << "engine->evaluate(\"0x43211234\")"
-                << "engine->evaluate(\"0x10000\")"
-                << "engine->evaluate(\"0x10001\")"
-                << "engine->evaluate(\"NaN\")"
-                << "engine->evaluate(\"Infinity\")"
-                << "engine->evaluate(\"-Infinity\")"
-                << "engine->evaluate(\"'ciao'\")"
-                << "engine->evaluate(\"''\")"
-                << "engine->evaluate(\"'0'\")"
-                << "engine->evaluate(\"'123'\")"
-                << "engine->evaluate(\"'12.4'\")"
-                << "engine->nullValue()"
-                << "engine->undefinedValue()";
-    }
-    newRow(expr) << isValid.contains(expr);
-}
-
-void tst_QScriptValue::isValid_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isValid(), expected);
-    QCOMPARE(value.isValid(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isValid)
-
-
-void tst_QScriptValue::isBool_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isBool_makeData(const char* expr)
-{
-    static QSet<QString> isBool;
-    if (isBool.isEmpty()) {
-        isBool << "QScriptValue(true)"
-                << "QScriptValue(false)"
-                << "QScriptValue(0, true)"
-                << "QScriptValue(0, false)"
-                << "QScriptValue(engine, true)"
-                << "QScriptValue(engine, false)"
-                << "engine->evaluate(\"true\")"
-                << "engine->evaluate(\"false\")";
-    }
-    newRow(expr) << isBool.contains(expr);
-}
-
-void tst_QScriptValue::isBool_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isBool(), expected);
-    QCOMPARE(value.isBool(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isBool)
-
-
-void tst_QScriptValue::isBoolean_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isBoolean_makeData(const char* expr)
-{
-    static QSet<QString> isBoolean;
-    if (isBoolean.isEmpty()) {
-        isBoolean << "QScriptValue(true)"
-                << "QScriptValue(false)"
-                << "QScriptValue(0, true)"
-                << "QScriptValue(0, false)"
-                << "QScriptValue(engine, true)"
-                << "QScriptValue(engine, false)"
-                << "engine->evaluate(\"true\")"
-                << "engine->evaluate(\"false\")";
-    }
-    newRow(expr) << isBoolean.contains(expr);
-}
-
-void tst_QScriptValue::isBoolean_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isBoolean(), expected);
-    QCOMPARE(value.isBoolean(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isBoolean)
-
-
-void tst_QScriptValue::isNumber_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isNumber_makeData(const char* expr)
-{
-    static QSet<QString> isNumber;
-    if (isNumber.isEmpty()) {
-        isNumber << "QScriptValue(int(122))"
-                << "QScriptValue(uint(124))"
-                << "QScriptValue(0)"
-                << "QScriptValue(0.0)"
-                << "QScriptValue(123.0)"
-                << "QScriptValue(6.37e-8)"
-                << "QScriptValue(-6.37e-8)"
-                << "QScriptValue(0x43211234)"
-                << "QScriptValue(0x10000)"
-                << "QScriptValue(0x10001)"
-                << "QScriptValue(qSNaN())"
-                << "QScriptValue(qQNaN())"
-                << "QScriptValue(qInf())"
-                << "QScriptValue(-qInf())"
-                << "QScriptValue(0, int(122))"
-                << "QScriptValue(0, uint(124))"
-                << "QScriptValue(0, 0)"
-                << "QScriptValue(0, 0.0)"
-                << "QScriptValue(0, 123.0)"
-                << "QScriptValue(0, 6.37e-8)"
-                << "QScriptValue(0, -6.37e-8)"
-                << "QScriptValue(0, 0x43211234)"
-                << "QScriptValue(0, 0x10000)"
-                << "QScriptValue(0, 0x10001)"
-                << "QScriptValue(0, qSNaN())"
-                << "QScriptValue(0, qQNaN())"
-                << "QScriptValue(0, qInf())"
-                << "QScriptValue(0, -qInf())"
-                << "QScriptValue(engine, int(122))"
-                << "QScriptValue(engine, uint(124))"
-                << "QScriptValue(engine, 0)"
-                << "QScriptValue(engine, 0.0)"
-                << "QScriptValue(engine, 123.0)"
-                << "QScriptValue(engine, 6.37e-8)"
-                << "QScriptValue(engine, -6.37e-8)"
-                << "QScriptValue(engine, 0x43211234)"
-                << "QScriptValue(engine, 0x10000)"
-                << "QScriptValue(engine, 0x10001)"
-                << "QScriptValue(engine, qSNaN())"
-                << "QScriptValue(engine, qQNaN())"
-                << "QScriptValue(engine, qInf())"
-                << "QScriptValue(engine, -qInf())"
-                << "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")"
-                << "engine->evaluate(\"122\")"
-                << "engine->evaluate(\"124\")"
-                << "engine->evaluate(\"0\")"
-                << "engine->evaluate(\"0.0\")"
-                << "engine->evaluate(\"123.0\")"
-                << "engine->evaluate(\"6.37e-8\")"
-                << "engine->evaluate(\"-6.37e-8\")"
-                << "engine->evaluate(\"0x43211234\")"
-                << "engine->evaluate(\"0x10000\")"
-                << "engine->evaluate(\"0x10001\")"
-                << "engine->evaluate(\"NaN\")"
-                << "engine->evaluate(\"Infinity\")"
-                << "engine->evaluate(\"-Infinity\")";
-    }
-    newRow(expr) << isNumber.contains(expr);
-}
-
-void tst_QScriptValue::isNumber_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isNumber(), expected);
-    QCOMPARE(value.isNumber(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isNumber)
-
-
-void tst_QScriptValue::isFunction_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isFunction_makeData(const char* expr)
-{
-    static QSet<QString> isFunction;
-    if (isFunction.isEmpty()) {
-        isFunction << "engine->evaluate(\"Function.prototype\")"
-                << "engine->evaluate(\"Object\")"
-                << "engine->evaluate(\"Array\")"
-                << "engine->evaluate(\"Number\")"
-                << "engine->evaluate(\"Function\")"
-                << "engine->evaluate(\"(function() { return 1; })\")"
-                << "engine->evaluate(\"(function() { return 'ciao'; })\")"
-                << "engine->evaluate(\"(function() { throw new Error('foo'); })\")"
-                << "engine->evaluate(\"/foo/\")";
-    }
-    newRow(expr) << isFunction.contains(expr);
-}
-
-void tst_QScriptValue::isFunction_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isFunction(), expected);
-    QCOMPARE(value.isFunction(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isFunction)
-
-
-void tst_QScriptValue::isNull_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isNull_makeData(const char* expr)
-{
-    static QSet<QString> isNull;
-    if (isNull.isEmpty()) {
-        isNull << "QScriptValue(QScriptValue::NullValue)"
-                << "QScriptValue(0, QScriptValue::NullValue)"
-                << "QScriptValue(engine, QScriptValue::NullValue)"
-                << "engine->evaluate(\"null\")"
-                << "engine->nullValue()";
-    }
-    newRow(expr) << isNull.contains(expr);
-}
-
-void tst_QScriptValue::isNull_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isNull(), expected);
-    QCOMPARE(value.isNull(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isNull)
-
-
-void tst_QScriptValue::isString_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isString_makeData(const char* expr)
-{
-    static QSet<QString> isString;
-    if (isString.isEmpty()) {
-        isString << "QScriptValue(\"NaN\")"
-                << "QScriptValue(\"Infinity\")"
-                << "QScriptValue(\"-Infinity\")"
-                << "QScriptValue(\"ciao\")"
-                << "QScriptValue(QString::fromLatin1(\"ciao\"))"
-                << "QScriptValue(QString(\"\"))"
-                << "QScriptValue(QString())"
-                << "QScriptValue(QString(\"0\"))"
-                << "QScriptValue(QString(\"123\"))"
-                << "QScriptValue(QString(\"12.4\"))"
-                << "QScriptValue(0, \"NaN\")"
-                << "QScriptValue(0, \"Infinity\")"
-                << "QScriptValue(0, \"-Infinity\")"
-                << "QScriptValue(0, \"ciao\")"
-                << "QScriptValue(0, QString::fromLatin1(\"ciao\"))"
-                << "QScriptValue(0, QString(\"\"))"
-                << "QScriptValue(0, QString())"
-                << "QScriptValue(0, QString(\"0\"))"
-                << "QScriptValue(0, QString(\"123\"))"
-                << "QScriptValue(0, QString(\"12.3\"))"
-                << "QScriptValue(engine, \"NaN\")"
-                << "QScriptValue(engine, \"Infinity\")"
-                << "QScriptValue(engine, \"-Infinity\")"
-                << "QScriptValue(engine, \"ciao\")"
-                << "QScriptValue(engine, QString::fromLatin1(\"ciao\"))"
-                << "QScriptValue(engine, QString(\"\"))"
-                << "QScriptValue(engine, QString())"
-                << "QScriptValue(engine, QString(\"0\"))"
-                << "QScriptValue(engine, QString(\"123\"))"
-                << "QScriptValue(engine, QString(\"1.23\"))"
-                << "engine->evaluate(\"'ciao'\")"
-                << "engine->evaluate(\"''\")"
-                << "engine->evaluate(\"'0'\")"
-                << "engine->evaluate(\"'123'\")"
-                << "engine->evaluate(\"'12.4'\")";
-    }
-    newRow(expr) << isString.contains(expr);
-}
-
-void tst_QScriptValue::isString_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isString(), expected);
-    QCOMPARE(value.isString(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isString)
-
-
-void tst_QScriptValue::isUndefined_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isUndefined_makeData(const char* expr)
-{
-    static QSet<QString> isUndefined;
-    if (isUndefined.isEmpty()) {
-        isUndefined << "QScriptValue(QScriptValue::UndefinedValue)"
-                << "QScriptValue(0, QScriptValue::UndefinedValue)"
-                << "QScriptValue(engine, QScriptValue::UndefinedValue)"
-                << "engine->evaluate(\"{}\")"
-                << "engine->evaluate(\"undefined\")"
-                << "engine->undefinedValue()";
-    }
-    newRow(expr) << isUndefined.contains(expr);
-}
-
-void tst_QScriptValue::isUndefined_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isUndefined(), expected);
-    QCOMPARE(value.isUndefined(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isUndefined)
-
-
-
-
-
-void tst_QScriptValue::isObject_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::isObject_makeData(const char* expr)
-{
-    static QSet<QString> isObject;
-    if (isObject.isEmpty()) {
-        isObject << "engine->evaluate(\"[]\")"
-                << "engine->evaluate(\"Object.prototype\")"
-                << "engine->evaluate(\"Date.prototype\")"
-                << "engine->evaluate(\"Array.prototype\")"
-                << "engine->evaluate(\"Function.prototype\")"
-                << "engine->evaluate(\"Error.prototype\")"
-                << "engine->evaluate(\"Object\")"
-                << "engine->evaluate(\"Array\")"
-                << "engine->evaluate(\"Number\")"
-                << "engine->evaluate(\"Function\")"
-                << "engine->evaluate(\"(function() { return 1; })\")"
-                << "engine->evaluate(\"(function() { return 'ciao'; })\")"
-                << "engine->evaluate(\"(function() { throw new Error('foo'); })\")"
-                << "engine->evaluate(\"/foo/\")"
-                << "engine->evaluate(\"new Object()\")"
-                << "engine->evaluate(\"new Array()\")"
-                << "engine->evaluate(\"new Error()\")"
-                << "engine->evaluate(\"Undefined\")"
-                << "engine->evaluate(\"Null\")"
-                << "engine->evaluate(\"True\")"
-                << "engine->evaluate(\"False\")";
-    }
-    newRow(expr) << isObject.contains(expr);
-}
-
-void tst_QScriptValue::isObject_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.isObject(), expected);
-    QCOMPARE(value.isObject(), expected);
-}
-
-DEFINE_TEST_FUNCTION(isObject)
-
-
-void tst_QScriptValue::toString_initData()
-{
-    QTest::addColumn<QString>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toString_makeData(const char* expr)
-{
-    static QHash<QString, QString> toString;
-    if (toString.isEmpty()) {
-        toString.insert("QScriptValue()", "");
-        toString.insert("QScriptValue(QScriptValue::UndefinedValue)", "undefined");
-        toString.insert("QScriptValue(QScriptValue::NullValue)", "null");
-        toString.insert("QScriptValue(true)", "true");
-        toString.insert("QScriptValue(false)", "false");
-        toString.insert("QScriptValue(int(122))", "122");
-        toString.insert("QScriptValue(uint(124))", "124");
-        toString.insert("QScriptValue(0)", "0");
-        toString.insert("QScriptValue(0.0)", "0");
-        toString.insert("QScriptValue(123.0)", "123");
-        toString.insert("QScriptValue(6.37e-8)", "6.37e-8");
-        toString.insert("QScriptValue(-6.37e-8)", "-6.37e-8");
-        toString.insert("QScriptValue(0x43211234)", "1126240820");
-        toString.insert("QScriptValue(0x10000)", "65536");
-        toString.insert("QScriptValue(0x10001)", "65537");
-        toString.insert("QScriptValue(qSNaN())", "NaN");
-        toString.insert("QScriptValue(qQNaN())", "NaN");
-        toString.insert("QScriptValue(qInf())", "Infinity");
-        toString.insert("QScriptValue(-qInf())", "-Infinity");
-        toString.insert("QScriptValue(\"NaN\")", "NaN");
-        toString.insert("QScriptValue(\"Infinity\")", "Infinity");
-        toString.insert("QScriptValue(\"-Infinity\")", "-Infinity");
-        toString.insert("QScriptValue(\"ciao\")", "ciao");
-        toString.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", "ciao");
-        toString.insert("QScriptValue(QString(\"\"))", "");
-        toString.insert("QScriptValue(QString())", "");
-        toString.insert("QScriptValue(QString(\"0\"))", "0");
-        toString.insert("QScriptValue(QString(\"123\"))", "123");
-        toString.insert("QScriptValue(QString(\"12.4\"))", "12.4");
-        toString.insert("QScriptValue(0, QScriptValue::UndefinedValue)", "undefined");
-        toString.insert("QScriptValue(0, QScriptValue::NullValue)", "null");
-        toString.insert("QScriptValue(0, true)", "true");
-        toString.insert("QScriptValue(0, false)", "false");
-        toString.insert("QScriptValue(0, int(122))", "122");
-        toString.insert("QScriptValue(0, uint(124))", "124");
-        toString.insert("QScriptValue(0, 0)", "0");
-        toString.insert("QScriptValue(0, 0.0)", "0");
-        toString.insert("QScriptValue(0, 123.0)", "123");
-        toString.insert("QScriptValue(0, 6.37e-8)", "6.37e-8");
-        toString.insert("QScriptValue(0, -6.37e-8)", "-6.37e-8");
-        toString.insert("QScriptValue(0, 0x43211234)", "1126240820");
-        toString.insert("QScriptValue(0, 0x10000)", "65536");
-        toString.insert("QScriptValue(0, 0x10001)", "65537");
-        toString.insert("QScriptValue(0, qSNaN())", "NaN");
-        toString.insert("QScriptValue(0, qQNaN())", "NaN");
-        toString.insert("QScriptValue(0, qInf())", "Infinity");
-        toString.insert("QScriptValue(0, -qInf())", "-Infinity");
-        toString.insert("QScriptValue(0, \"NaN\")", "NaN");
-        toString.insert("QScriptValue(0, \"Infinity\")", "Infinity");
-        toString.insert("QScriptValue(0, \"-Infinity\")", "-Infinity");
-        toString.insert("QScriptValue(0, \"ciao\")", "ciao");
-        toString.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", "ciao");
-        toString.insert("QScriptValue(0, QString(\"\"))", "");
-        toString.insert("QScriptValue(0, QString())", "");
-        toString.insert("QScriptValue(0, QString(\"0\"))", "0");
-        toString.insert("QScriptValue(0, QString(\"123\"))", "123");
-        toString.insert("QScriptValue(0, QString(\"12.3\"))", "12.3");
-        toString.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", "undefined");
-        toString.insert("QScriptValue(engine, QScriptValue::NullValue)", "null");
-        toString.insert("QScriptValue(engine, true)", "true");
-        toString.insert("QScriptValue(engine, false)", "false");
-        toString.insert("QScriptValue(engine, int(122))", "122");
-        toString.insert("QScriptValue(engine, uint(124))", "124");
-        toString.insert("QScriptValue(engine, 0)", "0");
-        toString.insert("QScriptValue(engine, 0.0)", "0");
-        toString.insert("QScriptValue(engine, 123.0)", "123");
-        toString.insert("QScriptValue(engine, 6.37e-8)", "6.37e-8");
-        toString.insert("QScriptValue(engine, -6.37e-8)", "-6.37e-8");
-        toString.insert("QScriptValue(engine, 0x43211234)", "1126240820");
-        toString.insert("QScriptValue(engine, 0x10000)", "65536");
-        toString.insert("QScriptValue(engine, 0x10001)", "65537");
-        toString.insert("QScriptValue(engine, qSNaN())", "NaN");
-        toString.insert("QScriptValue(engine, qQNaN())", "NaN");
-        toString.insert("QScriptValue(engine, qInf())", "Infinity");
-        toString.insert("QScriptValue(engine, -qInf())", "-Infinity");
-        toString.insert("QScriptValue(engine, \"NaN\")", "NaN");
-        toString.insert("QScriptValue(engine, \"Infinity\")", "Infinity");
-        toString.insert("QScriptValue(engine, \"-Infinity\")", "-Infinity");
-        toString.insert("QScriptValue(engine, \"ciao\")", "ciao");
-        toString.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", "ciao");
-        toString.insert("QScriptValue(engine, QString(\"\"))", "");
-        toString.insert("QScriptValue(engine, QString())", "");
-        toString.insert("QScriptValue(engine, QString(\"0\"))", "0");
-        toString.insert("QScriptValue(engine, QString(\"123\"))", "123");
-        toString.insert("QScriptValue(engine, QString(\"1.23\"))", "1.23");
-        toString.insert("engine->evaluate(\"[]\")", "");
-        toString.insert("engine->evaluate(\"{}\")", "undefined");
-        toString.insert("engine->evaluate(\"Object.prototype\")", "[object Object]");
-        toString.insert("engine->evaluate(\"Date.prototype\")", "Invalid Date");
-        toString.insert("engine->evaluate(\"Array.prototype\")", "");
-        toString.insert("engine->evaluate(\"Function.prototype\")", "function () {\n    [native code]\n}");
-        toString.insert("engine->evaluate(\"Error.prototype\")", "Error: Unknown error");
-        toString.insert("engine->evaluate(\"Object\")", "function Object() {\n    [native code]\n}");
-        toString.insert("engine->evaluate(\"Array\")", "function Array() {\n    [native code]\n}");
-        toString.insert("engine->evaluate(\"Number\")", "function Number() {\n    [native code]\n}");
-        toString.insert("engine->evaluate(\"Function\")", "function Function() {\n    [native code]\n}");
-        toString.insert("engine->evaluate(\"(function() { return 1; })\")", "function () { return 1; }");
-        toString.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", "function () { return 'ciao'; }");
-        toString.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", "function () { throw new Error('foo'); }");
-        toString.insert("engine->evaluate(\"/foo/\")", "/foo/");
-        toString.insert("engine->evaluate(\"new Object()\")", "[object Object]");
-        toString.insert("engine->evaluate(\"new Array()\")", "");
-        toString.insert("engine->evaluate(\"new Error()\")", "Error: Unknown error");
-        toString.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", "22");
-        toString.insert("engine->evaluate(\"Undefined\")", "ReferenceError: Can't find variable: Undefined");
-        toString.insert("engine->evaluate(\"Null\")", "ReferenceError: Can't find variable: Null");
-        toString.insert("engine->evaluate(\"True\")", "ReferenceError: Can't find variable: True");
-        toString.insert("engine->evaluate(\"False\")", "ReferenceError: Can't find variable: False");
-        toString.insert("engine->evaluate(\"undefined\")", "undefined");
-        toString.insert("engine->evaluate(\"null\")", "null");
-        toString.insert("engine->evaluate(\"true\")", "true");
-        toString.insert("engine->evaluate(\"false\")", "false");
-        toString.insert("engine->evaluate(\"122\")", "122");
-        toString.insert("engine->evaluate(\"124\")", "124");
-        toString.insert("engine->evaluate(\"0\")", "0");
-        toString.insert("engine->evaluate(\"0.0\")", "0");
-        toString.insert("engine->evaluate(\"123.0\")", "123");
-        toString.insert("engine->evaluate(\"6.37e-8\")", "6.37e-8");
-        toString.insert("engine->evaluate(\"-6.37e-8\")", "-6.37e-8");
-        toString.insert("engine->evaluate(\"0x43211234\")", "1126240820");
-        toString.insert("engine->evaluate(\"0x10000\")", "65536");
-        toString.insert("engine->evaluate(\"0x10001\")", "65537");
-        toString.insert("engine->evaluate(\"NaN\")", "NaN");
-        toString.insert("engine->evaluate(\"Infinity\")", "Infinity");
-        toString.insert("engine->evaluate(\"-Infinity\")", "-Infinity");
-        toString.insert("engine->evaluate(\"'ciao'\")", "ciao");
-        toString.insert("engine->evaluate(\"''\")", "");
-        toString.insert("engine->evaluate(\"'0'\")", "0");
-        toString.insert("engine->evaluate(\"'123'\")", "123");
-        toString.insert("engine->evaluate(\"'12.4'\")", "12.4");
-        toString.insert("engine->nullValue()", "null");
-        toString.insert("engine->undefinedValue()", "undefined");
-    }
-    newRow(expr) << toString.value(expr);
-}
-
-void tst_QScriptValue::toString_test(const char*, const QScriptValue& value)
-{
-    QFETCH(QString, expected);
-    QCOMPARE(value.toString(), expected);
-    QCOMPARE(value.toString(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toString)
-
-
-void tst_QScriptValue::toNumber_initData()
-{
-    QTest::addColumn<qsreal>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toNumber_makeData(const char* expr)
-{
-    static QHash<QString, qsreal> toNumber;
-    if (toNumber.isEmpty()) {
-        toNumber.insert("QScriptValue()", 0);
-        toNumber.insert("QScriptValue(QScriptValue::UndefinedValue)", qQNaN());
-        toNumber.insert("QScriptValue(QScriptValue::NullValue)", 0);
-        toNumber.insert("QScriptValue(true)", 1);
-        toNumber.insert("QScriptValue(false)", 0);
-        toNumber.insert("QScriptValue(int(122))", 122);
-        toNumber.insert("QScriptValue(uint(124))", 124);
-        toNumber.insert("QScriptValue(0)", 0);
-        toNumber.insert("QScriptValue(0.0)", 0);
-        toNumber.insert("QScriptValue(123.0)", 123);
-        toNumber.insert("QScriptValue(6.37e-8)", 6.369999999999999e-08);
-        toNumber.insert("QScriptValue(-6.37e-8)", -6.369999999999999e-08);
-        toNumber.insert("QScriptValue(0x43211234)", 1126240820);
-        toNumber.insert("QScriptValue(0x10000)", 65536);
-        toNumber.insert("QScriptValue(0x10001)", 65537);
-        toNumber.insert("QScriptValue(qSNaN())", qQNaN());
-        toNumber.insert("QScriptValue(qQNaN())", qQNaN());
-        toNumber.insert("QScriptValue(qInf())", qInf());
-        toNumber.insert("QScriptValue(-qInf())", qInf());
-        toNumber.insert("QScriptValue(\"NaN\")", qQNaN());
-        toNumber.insert("QScriptValue(\"Infinity\")", qInf());
-        toNumber.insert("QScriptValue(\"-Infinity\")", qInf());
-        toNumber.insert("QScriptValue(\"ciao\")", qQNaN());
-        toNumber.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", qQNaN());
-        toNumber.insert("QScriptValue(QString(\"\"))", 0);
-        toNumber.insert("QScriptValue(QString())", 0);
-        toNumber.insert("QScriptValue(QString(\"0\"))", 0);
-        toNumber.insert("QScriptValue(QString(\"123\"))", 123);
-        toNumber.insert("QScriptValue(QString(\"12.4\"))", 12.4);
-        toNumber.insert("QScriptValue(0, QScriptValue::UndefinedValue)", qQNaN());
-        toNumber.insert("QScriptValue(0, QScriptValue::NullValue)", 0);
-        toNumber.insert("QScriptValue(0, true)", 1);
-        toNumber.insert("QScriptValue(0, false)", 0);
-        toNumber.insert("QScriptValue(0, int(122))", 122);
-        toNumber.insert("QScriptValue(0, uint(124))", 124);
-        toNumber.insert("QScriptValue(0, 0)", 0);
-        toNumber.insert("QScriptValue(0, 0.0)", 0);
-        toNumber.insert("QScriptValue(0, 123.0)", 123);
-        toNumber.insert("QScriptValue(0, 6.37e-8)", 6.369999999999999e-08);
-        toNumber.insert("QScriptValue(0, -6.37e-8)", -6.369999999999999e-08);
-        toNumber.insert("QScriptValue(0, 0x43211234)", 1126240820);
-        toNumber.insert("QScriptValue(0, 0x10000)", 65536);
-        toNumber.insert("QScriptValue(0, 0x10001)", 65537);
-        toNumber.insert("QScriptValue(0, qSNaN())", qQNaN());
-        toNumber.insert("QScriptValue(0, qQNaN())", qQNaN());
-        toNumber.insert("QScriptValue(0, qInf())", qInf());
-        toNumber.insert("QScriptValue(0, -qInf())", qInf());
-        toNumber.insert("QScriptValue(0, \"NaN\")", qQNaN());
-        toNumber.insert("QScriptValue(0, \"Infinity\")", qInf());
-        toNumber.insert("QScriptValue(0, \"-Infinity\")", qInf());
-        toNumber.insert("QScriptValue(0, \"ciao\")", qQNaN());
-        toNumber.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", qQNaN());
-        toNumber.insert("QScriptValue(0, QString(\"\"))", 0);
-        toNumber.insert("QScriptValue(0, QString())", 0);
-        toNumber.insert("QScriptValue(0, QString(\"0\"))", 0);
-        toNumber.insert("QScriptValue(0, QString(\"123\"))", 123);
-        toNumber.insert("QScriptValue(0, QString(\"12.3\"))", 12.3);
-        toNumber.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", qQNaN());
-        toNumber.insert("QScriptValue(engine, QScriptValue::NullValue)", 0);
-        toNumber.insert("QScriptValue(engine, true)", 1);
-        toNumber.insert("QScriptValue(engine, false)", 0);
-        toNumber.insert("QScriptValue(engine, int(122))", 122);
-        toNumber.insert("QScriptValue(engine, uint(124))", 124);
-        toNumber.insert("QScriptValue(engine, 0)", 0);
-        toNumber.insert("QScriptValue(engine, 0.0)", 0);
-        toNumber.insert("QScriptValue(engine, 123.0)", 123);
-        toNumber.insert("QScriptValue(engine, 6.37e-8)", 6.369999999999999e-08);
-        toNumber.insert("QScriptValue(engine, -6.37e-8)", -6.369999999999999e-08);
-        toNumber.insert("QScriptValue(engine, 0x43211234)", 1126240820);
-        toNumber.insert("QScriptValue(engine, 0x10000)", 65536);
-        toNumber.insert("QScriptValue(engine, 0x10001)", 65537);
-        toNumber.insert("QScriptValue(engine, qSNaN())", qQNaN());
-        toNumber.insert("QScriptValue(engine, qQNaN())", qQNaN());
-        toNumber.insert("QScriptValue(engine, qInf())", qInf());
-        toNumber.insert("QScriptValue(engine, -qInf())", qInf());
-        toNumber.insert("QScriptValue(engine, \"NaN\")", qQNaN());
-        toNumber.insert("QScriptValue(engine, \"Infinity\")", qInf());
-        toNumber.insert("QScriptValue(engine, \"-Infinity\")", qInf());
-        toNumber.insert("QScriptValue(engine, \"ciao\")", qQNaN());
-        toNumber.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", qQNaN());
-        toNumber.insert("QScriptValue(engine, QString(\"\"))", 0);
-        toNumber.insert("QScriptValue(engine, QString())", 0);
-        toNumber.insert("QScriptValue(engine, QString(\"0\"))", 0);
-        toNumber.insert("QScriptValue(engine, QString(\"123\"))", 123);
-        toNumber.insert("QScriptValue(engine, QString(\"1.23\"))", 1.23);
-        toNumber.insert("engine->evaluate(\"[]\")", 0);
-        toNumber.insert("engine->evaluate(\"{}\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Object.prototype\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Date.prototype\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Array.prototype\")", 0);
-        toNumber.insert("engine->evaluate(\"Function.prototype\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Error.prototype\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Object\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Array\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Number\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Function\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"(function() { return 1; })\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"/foo/\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"new Object()\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"new Array()\")", 0);
-        toNumber.insert("engine->evaluate(\"new Error()\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22);
-        toNumber.insert("engine->evaluate(\"Undefined\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Null\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"True\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"False\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"undefined\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"null\")", 0);
-        toNumber.insert("engine->evaluate(\"true\")", 1);
-        toNumber.insert("engine->evaluate(\"false\")", 0);
-        toNumber.insert("engine->evaluate(\"122\")", 122);
-        toNumber.insert("engine->evaluate(\"124\")", 124);
-        toNumber.insert("engine->evaluate(\"0\")", 0);
-        toNumber.insert("engine->evaluate(\"0.0\")", 0);
-        toNumber.insert("engine->evaluate(\"123.0\")", 123);
-        toNumber.insert("engine->evaluate(\"6.37e-8\")", 6.369999999999999e-08);
-        toNumber.insert("engine->evaluate(\"-6.37e-8\")", -6.369999999999999e-08);
-        toNumber.insert("engine->evaluate(\"0x43211234\")", 1126240820);
-        toNumber.insert("engine->evaluate(\"0x10000\")", 65536);
-        toNumber.insert("engine->evaluate(\"0x10001\")", 65537);
-        toNumber.insert("engine->evaluate(\"NaN\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"Infinity\")", qInf());
-        toNumber.insert("engine->evaluate(\"-Infinity\")", qInf());
-        toNumber.insert("engine->evaluate(\"'ciao'\")", qQNaN());
-        toNumber.insert("engine->evaluate(\"''\")", 0);
-        toNumber.insert("engine->evaluate(\"'0'\")", 0);
-        toNumber.insert("engine->evaluate(\"'123'\")", 123);
-        toNumber.insert("engine->evaluate(\"'12.4'\")", 12.4);
-        toNumber.insert("engine->nullValue()", 0);
-        toNumber.insert("engine->undefinedValue()", qQNaN());
-    }
-    newRow(expr) << toNumber.value(expr);
-}
-
-void tst_QScriptValue::toNumber_test(const char*, const QScriptValue& value)
-{
-    QFETCH(qsreal, expected);
-    if (qIsNaN(expected)) {
-        QVERIFY(qIsNaN(value.toNumber()));
-        return;
-    }
-    if (qIsInf(expected)) {
-        QVERIFY(qIsInf(value.toNumber()));
-        QVERIFY(qIsInf(value.toNumber()));
-        return;
-    }
-    QCOMPARE(value.toNumber(), expected);
-    QCOMPARE(value.toNumber(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toNumber)
-
-
-void tst_QScriptValue::toBool_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toBool_makeData(const char* expr)
-{
-    static QHash<QString, bool> toBool;
-    if (toBool.isEmpty()) {
-        toBool.insert("QScriptValue()", false);
-        toBool.insert("QScriptValue(QScriptValue::UndefinedValue)", false);
-        toBool.insert("QScriptValue(QScriptValue::NullValue)", false);
-        toBool.insert("QScriptValue(true)", true);
-        toBool.insert("QScriptValue(false)", false);
-        toBool.insert("QScriptValue(int(122))", true);
-        toBool.insert("QScriptValue(uint(124))", true);
-        toBool.insert("QScriptValue(0)", false);
-        toBool.insert("QScriptValue(0.0)", false);
-        toBool.insert("QScriptValue(123.0)", true);
-        toBool.insert("QScriptValue(6.37e-8)", true);
-        toBool.insert("QScriptValue(-6.37e-8)", true);
-        toBool.insert("QScriptValue(0x43211234)", true);
-        toBool.insert("QScriptValue(0x10000)", true);
-        toBool.insert("QScriptValue(0x10001)", true);
-        toBool.insert("QScriptValue(qSNaN())", false);
-        toBool.insert("QScriptValue(qQNaN())", false);
-        toBool.insert("QScriptValue(qInf())", true);
-        toBool.insert("QScriptValue(-qInf())", true);
-        toBool.insert("QScriptValue(\"NaN\")", true);
-        toBool.insert("QScriptValue(\"Infinity\")", true);
-        toBool.insert("QScriptValue(\"-Infinity\")", true);
-        toBool.insert("QScriptValue(\"ciao\")", true);
-        toBool.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", true);
-        toBool.insert("QScriptValue(QString(\"\"))", false);
-        toBool.insert("QScriptValue(QString())", false);
-        toBool.insert("QScriptValue(QString(\"0\"))", true);
-        toBool.insert("QScriptValue(QString(\"123\"))", true);
-        toBool.insert("QScriptValue(QString(\"12.4\"))", true);
-        toBool.insert("QScriptValue(0, QScriptValue::UndefinedValue)", false);
-        toBool.insert("QScriptValue(0, QScriptValue::NullValue)", false);
-        toBool.insert("QScriptValue(0, true)", true);
-        toBool.insert("QScriptValue(0, false)", false);
-        toBool.insert("QScriptValue(0, int(122))", true);
-        toBool.insert("QScriptValue(0, uint(124))", true);
-        toBool.insert("QScriptValue(0, 0)", false);
-        toBool.insert("QScriptValue(0, 0.0)", false);
-        toBool.insert("QScriptValue(0, 123.0)", true);
-        toBool.insert("QScriptValue(0, 6.37e-8)", true);
-        toBool.insert("QScriptValue(0, -6.37e-8)", true);
-        toBool.insert("QScriptValue(0, 0x43211234)", true);
-        toBool.insert("QScriptValue(0, 0x10000)", true);
-        toBool.insert("QScriptValue(0, 0x10001)", true);
-        toBool.insert("QScriptValue(0, qSNaN())", false);
-        toBool.insert("QScriptValue(0, qQNaN())", false);
-        toBool.insert("QScriptValue(0, qInf())", true);
-        toBool.insert("QScriptValue(0, -qInf())", true);
-        toBool.insert("QScriptValue(0, \"NaN\")", true);
-        toBool.insert("QScriptValue(0, \"Infinity\")", true);
-        toBool.insert("QScriptValue(0, \"-Infinity\")", true);
-        toBool.insert("QScriptValue(0, \"ciao\")", true);
-        toBool.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", true);
-        toBool.insert("QScriptValue(0, QString(\"\"))", false);
-        toBool.insert("QScriptValue(0, QString())", false);
-        toBool.insert("QScriptValue(0, QString(\"0\"))", true);
-        toBool.insert("QScriptValue(0, QString(\"123\"))", true);
-        toBool.insert("QScriptValue(0, QString(\"12.3\"))", true);
-        toBool.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", false);
-        toBool.insert("QScriptValue(engine, QScriptValue::NullValue)", false);
-        toBool.insert("QScriptValue(engine, true)", true);
-        toBool.insert("QScriptValue(engine, false)", false);
-        toBool.insert("QScriptValue(engine, int(122))", true);
-        toBool.insert("QScriptValue(engine, uint(124))", true);
-        toBool.insert("QScriptValue(engine, 0)", false);
-        toBool.insert("QScriptValue(engine, 0.0)", false);
-        toBool.insert("QScriptValue(engine, 123.0)", true);
-        toBool.insert("QScriptValue(engine, 6.37e-8)", true);
-        toBool.insert("QScriptValue(engine, -6.37e-8)", true);
-        toBool.insert("QScriptValue(engine, 0x43211234)", true);
-        toBool.insert("QScriptValue(engine, 0x10000)", true);
-        toBool.insert("QScriptValue(engine, 0x10001)", true);
-        toBool.insert("QScriptValue(engine, qSNaN())", false);
-        toBool.insert("QScriptValue(engine, qQNaN())", false);
-        toBool.insert("QScriptValue(engine, qInf())", true);
-        toBool.insert("QScriptValue(engine, -qInf())", true);
-        toBool.insert("QScriptValue(engine, \"NaN\")", true);
-        toBool.insert("QScriptValue(engine, \"Infinity\")", true);
-        toBool.insert("QScriptValue(engine, \"-Infinity\")", true);
-        toBool.insert("QScriptValue(engine, \"ciao\")", true);
-        toBool.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", true);
-        toBool.insert("QScriptValue(engine, QString(\"\"))", false);
-        toBool.insert("QScriptValue(engine, QString())", false);
-        toBool.insert("QScriptValue(engine, QString(\"0\"))", true);
-        toBool.insert("QScriptValue(engine, QString(\"123\"))", true);
-        toBool.insert("QScriptValue(engine, QString(\"1.23\"))", true);
-        toBool.insert("engine->evaluate(\"[]\")", true);
-        toBool.insert("engine->evaluate(\"{}\")", false);
-        toBool.insert("engine->evaluate(\"Object.prototype\")", true);
-        toBool.insert("engine->evaluate(\"Date.prototype\")", true);
-        toBool.insert("engine->evaluate(\"Array.prototype\")", true);
-        toBool.insert("engine->evaluate(\"Function.prototype\")", true);
-        toBool.insert("engine->evaluate(\"Error.prototype\")", true);
-        toBool.insert("engine->evaluate(\"Object\")", true);
-        toBool.insert("engine->evaluate(\"Array\")", true);
-        toBool.insert("engine->evaluate(\"Number\")", true);
-        toBool.insert("engine->evaluate(\"Function\")", true);
-        toBool.insert("engine->evaluate(\"(function() { return 1; })\")", true);
-        toBool.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", true);
-        toBool.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", true);
-        toBool.insert("engine->evaluate(\"/foo/\")", true);
-        toBool.insert("engine->evaluate(\"new Object()\")", true);
-        toBool.insert("engine->evaluate(\"new Array()\")", true);
-        toBool.insert("engine->evaluate(\"new Error()\")", true);
-        toBool.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", true);
-        toBool.insert("engine->evaluate(\"Undefined\")", true);
-        toBool.insert("engine->evaluate(\"Null\")", true);
-        toBool.insert("engine->evaluate(\"True\")", true);
-        toBool.insert("engine->evaluate(\"False\")", true);
-        toBool.insert("engine->evaluate(\"undefined\")", false);
-        toBool.insert("engine->evaluate(\"null\")", false);
-        toBool.insert("engine->evaluate(\"true\")", true);
-        toBool.insert("engine->evaluate(\"false\")", false);
-        toBool.insert("engine->evaluate(\"122\")", true);
-        toBool.insert("engine->evaluate(\"124\")", true);
-        toBool.insert("engine->evaluate(\"0\")", false);
-        toBool.insert("engine->evaluate(\"0.0\")", false);
-        toBool.insert("engine->evaluate(\"123.0\")", true);
-        toBool.insert("engine->evaluate(\"6.37e-8\")", true);
-        toBool.insert("engine->evaluate(\"-6.37e-8\")", true);
-        toBool.insert("engine->evaluate(\"0x43211234\")", true);
-        toBool.insert("engine->evaluate(\"0x10000\")", true);
-        toBool.insert("engine->evaluate(\"0x10001\")", true);
-        toBool.insert("engine->evaluate(\"NaN\")", false);
-        toBool.insert("engine->evaluate(\"Infinity\")", true);
-        toBool.insert("engine->evaluate(\"-Infinity\")", true);
-        toBool.insert("engine->evaluate(\"'ciao'\")", true);
-        toBool.insert("engine->evaluate(\"''\")", false);
-        toBool.insert("engine->evaluate(\"'0'\")", true);
-        toBool.insert("engine->evaluate(\"'123'\")", true);
-        toBool.insert("engine->evaluate(\"'12.4'\")", true);
-        toBool.insert("engine->nullValue()", false);
-        toBool.insert("engine->undefinedValue()", false);
-    }
-    newRow(expr) << toBool.value(expr);
-}
-
-void tst_QScriptValue::toBool_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.toBool(), expected);
-    QCOMPARE(value.toBool(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toBool)
-
-
-void tst_QScriptValue::toBoolean_initData()
-{
-    QTest::addColumn<bool>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toBoolean_makeData(const char* expr)
-{
-    static QHash<QString, bool> toBoolean;
-    if (toBoolean.isEmpty()) {
-        toBoolean.insert("QScriptValue()", false);
-        toBoolean.insert("QScriptValue(QScriptValue::UndefinedValue)", false);
-        toBoolean.insert("QScriptValue(QScriptValue::NullValue)", false);
-        toBoolean.insert("QScriptValue(true)", true);
-        toBoolean.insert("QScriptValue(false)", false);
-        toBoolean.insert("QScriptValue(int(122))", true);
-        toBoolean.insert("QScriptValue(uint(124))", true);
-        toBoolean.insert("QScriptValue(0)", false);
-        toBoolean.insert("QScriptValue(0.0)", false);
-        toBoolean.insert("QScriptValue(123.0)", true);
-        toBoolean.insert("QScriptValue(6.37e-8)", true);
-        toBoolean.insert("QScriptValue(-6.37e-8)", true);
-        toBoolean.insert("QScriptValue(0x43211234)", true);
-        toBoolean.insert("QScriptValue(0x10000)", true);
-        toBoolean.insert("QScriptValue(0x10001)", true);
-        toBoolean.insert("QScriptValue(qSNaN())", false);
-        toBoolean.insert("QScriptValue(qQNaN())", false);
-        toBoolean.insert("QScriptValue(qInf())", true);
-        toBoolean.insert("QScriptValue(-qInf())", true);
-        toBoolean.insert("QScriptValue(\"NaN\")", true);
-        toBoolean.insert("QScriptValue(\"Infinity\")", true);
-        toBoolean.insert("QScriptValue(\"-Infinity\")", true);
-        toBoolean.insert("QScriptValue(\"ciao\")", true);
-        toBoolean.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", true);
-        toBoolean.insert("QScriptValue(QString(\"\"))", false);
-        toBoolean.insert("QScriptValue(QString())", false);
-        toBoolean.insert("QScriptValue(QString(\"0\"))", true);
-        toBoolean.insert("QScriptValue(QString(\"123\"))", true);
-        toBoolean.insert("QScriptValue(QString(\"12.4\"))", true);
-        toBoolean.insert("QScriptValue(0, QScriptValue::UndefinedValue)", false);
-        toBoolean.insert("QScriptValue(0, QScriptValue::NullValue)", false);
-        toBoolean.insert("QScriptValue(0, true)", true);
-        toBoolean.insert("QScriptValue(0, false)", false);
-        toBoolean.insert("QScriptValue(0, int(122))", true);
-        toBoolean.insert("QScriptValue(0, uint(124))", true);
-        toBoolean.insert("QScriptValue(0, 0)", false);
-        toBoolean.insert("QScriptValue(0, 0.0)", false);
-        toBoolean.insert("QScriptValue(0, 123.0)", true);
-        toBoolean.insert("QScriptValue(0, 6.37e-8)", true);
-        toBoolean.insert("QScriptValue(0, -6.37e-8)", true);
-        toBoolean.insert("QScriptValue(0, 0x43211234)", true);
-        toBoolean.insert("QScriptValue(0, 0x10000)", true);
-        toBoolean.insert("QScriptValue(0, 0x10001)", true);
-        toBoolean.insert("QScriptValue(0, qSNaN())", false);
-        toBoolean.insert("QScriptValue(0, qQNaN())", false);
-        toBoolean.insert("QScriptValue(0, qInf())", true);
-        toBoolean.insert("QScriptValue(0, -qInf())", true);
-        toBoolean.insert("QScriptValue(0, \"NaN\")", true);
-        toBoolean.insert("QScriptValue(0, \"Infinity\")", true);
-        toBoolean.insert("QScriptValue(0, \"-Infinity\")", true);
-        toBoolean.insert("QScriptValue(0, \"ciao\")", true);
-        toBoolean.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", true);
-        toBoolean.insert("QScriptValue(0, QString(\"\"))", false);
-        toBoolean.insert("QScriptValue(0, QString())", false);
-        toBoolean.insert("QScriptValue(0, QString(\"0\"))", true);
-        toBoolean.insert("QScriptValue(0, QString(\"123\"))", true);
-        toBoolean.insert("QScriptValue(0, QString(\"12.3\"))", true);
-        toBoolean.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", false);
-        toBoolean.insert("QScriptValue(engine, QScriptValue::NullValue)", false);
-        toBoolean.insert("QScriptValue(engine, true)", true);
-        toBoolean.insert("QScriptValue(engine, false)", false);
-        toBoolean.insert("QScriptValue(engine, int(122))", true);
-        toBoolean.insert("QScriptValue(engine, uint(124))", true);
-        toBoolean.insert("QScriptValue(engine, 0)", false);
-        toBoolean.insert("QScriptValue(engine, 0.0)", false);
-        toBoolean.insert("QScriptValue(engine, 123.0)", true);
-        toBoolean.insert("QScriptValue(engine, 6.37e-8)", true);
-        toBoolean.insert("QScriptValue(engine, -6.37e-8)", true);
-        toBoolean.insert("QScriptValue(engine, 0x43211234)", true);
-        toBoolean.insert("QScriptValue(engine, 0x10000)", true);
-        toBoolean.insert("QScriptValue(engine, 0x10001)", true);
-        toBoolean.insert("QScriptValue(engine, qSNaN())", false);
-        toBoolean.insert("QScriptValue(engine, qQNaN())", false);
-        toBoolean.insert("QScriptValue(engine, qInf())", true);
-        toBoolean.insert("QScriptValue(engine, -qInf())", true);
-        toBoolean.insert("QScriptValue(engine, \"NaN\")", true);
-        toBoolean.insert("QScriptValue(engine, \"Infinity\")", true);
-        toBoolean.insert("QScriptValue(engine, \"-Infinity\")", true);
-        toBoolean.insert("QScriptValue(engine, \"ciao\")", true);
-        toBoolean.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", true);
-        toBoolean.insert("QScriptValue(engine, QString(\"\"))", false);
-        toBoolean.insert("QScriptValue(engine, QString())", false);
-        toBoolean.insert("QScriptValue(engine, QString(\"0\"))", true);
-        toBoolean.insert("QScriptValue(engine, QString(\"123\"))", true);
-        toBoolean.insert("QScriptValue(engine, QString(\"1.23\"))", true);
-        toBoolean.insert("engine->evaluate(\"[]\")", true);
-        toBoolean.insert("engine->evaluate(\"{}\")", false);
-        toBoolean.insert("engine->evaluate(\"Object.prototype\")", true);
-        toBoolean.insert("engine->evaluate(\"Date.prototype\")", true);
-        toBoolean.insert("engine->evaluate(\"Array.prototype\")", true);
-        toBoolean.insert("engine->evaluate(\"Function.prototype\")", true);
-        toBoolean.insert("engine->evaluate(\"Error.prototype\")", true);
-        toBoolean.insert("engine->evaluate(\"Object\")", true);
-        toBoolean.insert("engine->evaluate(\"Array\")", true);
-        toBoolean.insert("engine->evaluate(\"Number\")", true);
-        toBoolean.insert("engine->evaluate(\"Function\")", true);
-        toBoolean.insert("engine->evaluate(\"(function() { return 1; })\")", true);
-        toBoolean.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", true);
-        toBoolean.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", true);
-        toBoolean.insert("engine->evaluate(\"/foo/\")", true);
-        toBoolean.insert("engine->evaluate(\"new Object()\")", true);
-        toBoolean.insert("engine->evaluate(\"new Array()\")", true);
-        toBoolean.insert("engine->evaluate(\"new Error()\")", true);
-        toBoolean.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", true);
-        toBoolean.insert("engine->evaluate(\"Undefined\")", true);
-        toBoolean.insert("engine->evaluate(\"Null\")", true);
-        toBoolean.insert("engine->evaluate(\"True\")", true);
-        toBoolean.insert("engine->evaluate(\"False\")", true);
-        toBoolean.insert("engine->evaluate(\"undefined\")", false);
-        toBoolean.insert("engine->evaluate(\"null\")", false);
-        toBoolean.insert("engine->evaluate(\"true\")", true);
-        toBoolean.insert("engine->evaluate(\"false\")", false);
-        toBoolean.insert("engine->evaluate(\"122\")", true);
-        toBoolean.insert("engine->evaluate(\"124\")", true);
-        toBoolean.insert("engine->evaluate(\"0\")", false);
-        toBoolean.insert("engine->evaluate(\"0.0\")", false);
-        toBoolean.insert("engine->evaluate(\"123.0\")", true);
-        toBoolean.insert("engine->evaluate(\"6.37e-8\")", true);
-        toBoolean.insert("engine->evaluate(\"-6.37e-8\")", true);
-        toBoolean.insert("engine->evaluate(\"0x43211234\")", true);
-        toBoolean.insert("engine->evaluate(\"0x10000\")", true);
-        toBoolean.insert("engine->evaluate(\"0x10001\")", true);
-        toBoolean.insert("engine->evaluate(\"NaN\")", false);
-        toBoolean.insert("engine->evaluate(\"Infinity\")", true);
-        toBoolean.insert("engine->evaluate(\"-Infinity\")", true);
-        toBoolean.insert("engine->evaluate(\"'ciao'\")", true);
-        toBoolean.insert("engine->evaluate(\"''\")", false);
-        toBoolean.insert("engine->evaluate(\"'0'\")", true);
-        toBoolean.insert("engine->evaluate(\"'123'\")", true);
-        toBoolean.insert("engine->evaluate(\"'12.4'\")", true);
-        toBoolean.insert("engine->nullValue()", false);
-        toBoolean.insert("engine->undefinedValue()", false);
-    }
-    newRow(expr) << toBoolean.value(expr);
-}
-
-void tst_QScriptValue::toBoolean_test(const char*, const QScriptValue& value)
-{
-    QFETCH(bool, expected);
-    QCOMPARE(value.toBoolean(), expected);
-    QCOMPARE(value.toBoolean(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toBoolean)
-
-
-void tst_QScriptValue::toInteger_initData()
-{
-    QTest::addColumn<qsreal>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toInteger_makeData(const char* expr)
-{
-    static QHash<QString, qsreal> toInteger;
-    if (toInteger.isEmpty()) {
-        toInteger.insert("QScriptValue()", 0);
-        toInteger.insert("QScriptValue(QScriptValue::UndefinedValue)", 0);
-        toInteger.insert("QScriptValue(QScriptValue::NullValue)", 0);
-        toInteger.insert("QScriptValue(true)", 1);
-        toInteger.insert("QScriptValue(false)", 0);
-        toInteger.insert("QScriptValue(int(122))", 122);
-        toInteger.insert("QScriptValue(uint(124))", 124);
-        toInteger.insert("QScriptValue(0)", 0);
-        toInteger.insert("QScriptValue(0.0)", 0);
-        toInteger.insert("QScriptValue(123.0)", 123);
-        toInteger.insert("QScriptValue(6.37e-8)", 0);
-        toInteger.insert("QScriptValue(-6.37e-8)", 0);
-        toInteger.insert("QScriptValue(0x43211234)", 1126240820);
-        toInteger.insert("QScriptValue(0x10000)", 65536);
-        toInteger.insert("QScriptValue(0x10001)", 65537);
-        toInteger.insert("QScriptValue(qSNaN())", 0);
-        toInteger.insert("QScriptValue(qQNaN())", 0);
-        toInteger.insert("QScriptValue(qInf())", qInf());
-        toInteger.insert("QScriptValue(-qInf())", qInf());
-        toInteger.insert("QScriptValue(\"NaN\")", 0);
-        toInteger.insert("QScriptValue(\"Infinity\")", qInf());
-        toInteger.insert("QScriptValue(\"-Infinity\")", qInf());
-        toInteger.insert("QScriptValue(\"ciao\")", 0);
-        toInteger.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", 0);
-        toInteger.insert("QScriptValue(QString(\"\"))", 0);
-        toInteger.insert("QScriptValue(QString())", 0);
-        toInteger.insert("QScriptValue(QString(\"0\"))", 0);
-        toInteger.insert("QScriptValue(QString(\"123\"))", 123);
-        toInteger.insert("QScriptValue(QString(\"12.4\"))", 12);
-        toInteger.insert("QScriptValue(0, QScriptValue::UndefinedValue)", 0);
-        toInteger.insert("QScriptValue(0, QScriptValue::NullValue)", 0);
-        toInteger.insert("QScriptValue(0, true)", 1);
-        toInteger.insert("QScriptValue(0, false)", 0);
-        toInteger.insert("QScriptValue(0, int(122))", 122);
-        toInteger.insert("QScriptValue(0, uint(124))", 124);
-        toInteger.insert("QScriptValue(0, 0)", 0);
-        toInteger.insert("QScriptValue(0, 0.0)", 0);
-        toInteger.insert("QScriptValue(0, 123.0)", 123);
-        toInteger.insert("QScriptValue(0, 6.37e-8)", 0);
-        toInteger.insert("QScriptValue(0, -6.37e-8)", 0);
-        toInteger.insert("QScriptValue(0, 0x43211234)", 1126240820);
-        toInteger.insert("QScriptValue(0, 0x10000)", 65536);
-        toInteger.insert("QScriptValue(0, 0x10001)", 65537);
-        toInteger.insert("QScriptValue(0, qSNaN())", 0);
-        toInteger.insert("QScriptValue(0, qQNaN())", 0);
-        toInteger.insert("QScriptValue(0, qInf())", qInf());
-        toInteger.insert("QScriptValue(0, -qInf())", qInf());
-        toInteger.insert("QScriptValue(0, \"NaN\")", 0);
-        toInteger.insert("QScriptValue(0, \"Infinity\")", qInf());
-        toInteger.insert("QScriptValue(0, \"-Infinity\")", qInf());
-        toInteger.insert("QScriptValue(0, \"ciao\")", 0);
-        toInteger.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", 0);
-        toInteger.insert("QScriptValue(0, QString(\"\"))", 0);
-        toInteger.insert("QScriptValue(0, QString())", 0);
-        toInteger.insert("QScriptValue(0, QString(\"0\"))", 0);
-        toInteger.insert("QScriptValue(0, QString(\"123\"))", 123);
-        toInteger.insert("QScriptValue(0, QString(\"12.3\"))", 12);
-        toInteger.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", 0);
-        toInteger.insert("QScriptValue(engine, QScriptValue::NullValue)", 0);
-        toInteger.insert("QScriptValue(engine, true)", 1);
-        toInteger.insert("QScriptValue(engine, false)", 0);
-        toInteger.insert("QScriptValue(engine, int(122))", 122);
-        toInteger.insert("QScriptValue(engine, uint(124))", 124);
-        toInteger.insert("QScriptValue(engine, 0)", 0);
-        toInteger.insert("QScriptValue(engine, 0.0)", 0);
-        toInteger.insert("QScriptValue(engine, 123.0)", 123);
-        toInteger.insert("QScriptValue(engine, 6.37e-8)", 0);
-        toInteger.insert("QScriptValue(engine, -6.37e-8)", 0);
-        toInteger.insert("QScriptValue(engine, 0x43211234)", 1126240820);
-        toInteger.insert("QScriptValue(engine, 0x10000)", 65536);
-        toInteger.insert("QScriptValue(engine, 0x10001)", 65537);
-        toInteger.insert("QScriptValue(engine, qSNaN())", 0);
-        toInteger.insert("QScriptValue(engine, qQNaN())", 0);
-        toInteger.insert("QScriptValue(engine, qInf())", qInf());
-        toInteger.insert("QScriptValue(engine, -qInf())", qInf());
-        toInteger.insert("QScriptValue(engine, \"NaN\")", 0);
-        toInteger.insert("QScriptValue(engine, \"Infinity\")", qInf());
-        toInteger.insert("QScriptValue(engine, \"-Infinity\")", qInf());
-        toInteger.insert("QScriptValue(engine, \"ciao\")", 0);
-        toInteger.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", 0);
-        toInteger.insert("QScriptValue(engine, QString(\"\"))", 0);
-        toInteger.insert("QScriptValue(engine, QString())", 0);
-        toInteger.insert("QScriptValue(engine, QString(\"0\"))", 0);
-        toInteger.insert("QScriptValue(engine, QString(\"123\"))", 123);
-        toInteger.insert("QScriptValue(engine, QString(\"1.23\"))", 1);
-        toInteger.insert("engine->evaluate(\"[]\")", 0);
-        toInteger.insert("engine->evaluate(\"{}\")", 0);
-        toInteger.insert("engine->evaluate(\"Object.prototype\")", 0);
-        toInteger.insert("engine->evaluate(\"Date.prototype\")", 0);
-        toInteger.insert("engine->evaluate(\"Array.prototype\")", 0);
-        toInteger.insert("engine->evaluate(\"Function.prototype\")", 0);
-        toInteger.insert("engine->evaluate(\"Error.prototype\")", 0);
-        toInteger.insert("engine->evaluate(\"Object\")", 0);
-        toInteger.insert("engine->evaluate(\"Array\")", 0);
-        toInteger.insert("engine->evaluate(\"Number\")", 0);
-        toInteger.insert("engine->evaluate(\"Function\")", 0);
-        toInteger.insert("engine->evaluate(\"(function() { return 1; })\")", 0);
-        toInteger.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", 0);
-        toInteger.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", 0);
-        toInteger.insert("engine->evaluate(\"/foo/\")", 0);
-        toInteger.insert("engine->evaluate(\"new Object()\")", 0);
-        toInteger.insert("engine->evaluate(\"new Array()\")", 0);
-        toInteger.insert("engine->evaluate(\"new Error()\")", 0);
-        toInteger.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22);
-        toInteger.insert("engine->evaluate(\"Undefined\")", 0);
-        toInteger.insert("engine->evaluate(\"Null\")", 0);
-        toInteger.insert("engine->evaluate(\"True\")", 0);
-        toInteger.insert("engine->evaluate(\"False\")", 0);
-        toInteger.insert("engine->evaluate(\"undefined\")", 0);
-        toInteger.insert("engine->evaluate(\"null\")", 0);
-        toInteger.insert("engine->evaluate(\"true\")", 1);
-        toInteger.insert("engine->evaluate(\"false\")", 0);
-        toInteger.insert("engine->evaluate(\"122\")", 122);
-        toInteger.insert("engine->evaluate(\"124\")", 124);
-        toInteger.insert("engine->evaluate(\"0\")", 0);
-        toInteger.insert("engine->evaluate(\"0.0\")", 0);
-        toInteger.insert("engine->evaluate(\"123.0\")", 123);
-        toInteger.insert("engine->evaluate(\"6.37e-8\")", 0);
-        toInteger.insert("engine->evaluate(\"-6.37e-8\")", 0);
-        toInteger.insert("engine->evaluate(\"0x43211234\")", 1126240820);
-        toInteger.insert("engine->evaluate(\"0x10000\")", 65536);
-        toInteger.insert("engine->evaluate(\"0x10001\")", 65537);
-        toInteger.insert("engine->evaluate(\"NaN\")", 0);
-        toInteger.insert("engine->evaluate(\"Infinity\")", qInf());
-        toInteger.insert("engine->evaluate(\"-Infinity\")", qInf());
-        toInteger.insert("engine->evaluate(\"'ciao'\")", 0);
-        toInteger.insert("engine->evaluate(\"''\")", 0);
-        toInteger.insert("engine->evaluate(\"'0'\")", 0);
-        toInteger.insert("engine->evaluate(\"'123'\")", 123);
-        toInteger.insert("engine->evaluate(\"'12.4'\")", 12);
-        toInteger.insert("engine->nullValue()", 0);
-        toInteger.insert("engine->undefinedValue()", 0);
-    }
-    newRow(expr) << toInteger.value(expr);
-}
-
-void tst_QScriptValue::toInteger_test(const char*, const QScriptValue& value)
-{
-    QFETCH(qsreal, expected);
-    if (qIsInf(expected)) {
-        QVERIFY(qIsInf(value.toInteger()));
-        QVERIFY(qIsInf(value.toInteger()));
-        return;
-    }
-    QCOMPARE(value.toInteger(), expected);
-    QCOMPARE(value.toInteger(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toInteger)
-
-
-void tst_QScriptValue::toInt32_initData()
-{
-    QTest::addColumn<qint32>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toInt32_makeData(const char* expr)
-{
-    static QHash<QString, qint32> toInt32;
-    if (toInt32.isEmpty()) {
-        toInt32.insert("QScriptValue()", 0);
-        toInt32.insert("QScriptValue(QScriptValue::UndefinedValue)", 0);
-        toInt32.insert("QScriptValue(QScriptValue::NullValue)", 0);
-        toInt32.insert("QScriptValue(true)", 1);
-        toInt32.insert("QScriptValue(false)", 0);
-        toInt32.insert("QScriptValue(int(122))", 122);
-        toInt32.insert("QScriptValue(uint(124))", 124);
-        toInt32.insert("QScriptValue(0)", 0);
-        toInt32.insert("QScriptValue(0.0)", 0);
-        toInt32.insert("QScriptValue(123.0)", 123);
-        toInt32.insert("QScriptValue(6.37e-8)", 0);
-        toInt32.insert("QScriptValue(-6.37e-8)", 0);
-        toInt32.insert("QScriptValue(0x43211234)", 1126240820);
-        toInt32.insert("QScriptValue(0x10000)", 65536);
-        toInt32.insert("QScriptValue(0x10001)", 65537);
-        toInt32.insert("QScriptValue(qSNaN())", 0);
-        toInt32.insert("QScriptValue(qQNaN())", 0);
-        toInt32.insert("QScriptValue(qInf())", 0);
-        toInt32.insert("QScriptValue(-qInf())", 0);
-        toInt32.insert("QScriptValue(\"NaN\")", 0);
-        toInt32.insert("QScriptValue(\"Infinity\")", 0);
-        toInt32.insert("QScriptValue(\"-Infinity\")", 0);
-        toInt32.insert("QScriptValue(\"ciao\")", 0);
-        toInt32.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", 0);
-        toInt32.insert("QScriptValue(QString(\"\"))", 0);
-        toInt32.insert("QScriptValue(QString())", 0);
-        toInt32.insert("QScriptValue(QString(\"0\"))", 0);
-        toInt32.insert("QScriptValue(QString(\"123\"))", 123);
-        toInt32.insert("QScriptValue(QString(\"12.4\"))", 12);
-        toInt32.insert("QScriptValue(0, QScriptValue::UndefinedValue)", 0);
-        toInt32.insert("QScriptValue(0, QScriptValue::NullValue)", 0);
-        toInt32.insert("QScriptValue(0, true)", 1);
-        toInt32.insert("QScriptValue(0, false)", 0);
-        toInt32.insert("QScriptValue(0, int(122))", 122);
-        toInt32.insert("QScriptValue(0, uint(124))", 124);
-        toInt32.insert("QScriptValue(0, 0)", 0);
-        toInt32.insert("QScriptValue(0, 0.0)", 0);
-        toInt32.insert("QScriptValue(0, 123.0)", 123);
-        toInt32.insert("QScriptValue(0, 6.37e-8)", 0);
-        toInt32.insert("QScriptValue(0, -6.37e-8)", 0);
-        toInt32.insert("QScriptValue(0, 0x43211234)", 1126240820);
-        toInt32.insert("QScriptValue(0, 0x10000)", 65536);
-        toInt32.insert("QScriptValue(0, 0x10001)", 65537);
-        toInt32.insert("QScriptValue(0, qSNaN())", 0);
-        toInt32.insert("QScriptValue(0, qQNaN())", 0);
-        toInt32.insert("QScriptValue(0, qInf())", 0);
-        toInt32.insert("QScriptValue(0, -qInf())", 0);
-        toInt32.insert("QScriptValue(0, \"NaN\")", 0);
-        toInt32.insert("QScriptValue(0, \"Infinity\")", 0);
-        toInt32.insert("QScriptValue(0, \"-Infinity\")", 0);
-        toInt32.insert("QScriptValue(0, \"ciao\")", 0);
-        toInt32.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", 0);
-        toInt32.insert("QScriptValue(0, QString(\"\"))", 0);
-        toInt32.insert("QScriptValue(0, QString())", 0);
-        toInt32.insert("QScriptValue(0, QString(\"0\"))", 0);
-        toInt32.insert("QScriptValue(0, QString(\"123\"))", 123);
-        toInt32.insert("QScriptValue(0, QString(\"12.3\"))", 12);
-        toInt32.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", 0);
-        toInt32.insert("QScriptValue(engine, QScriptValue::NullValue)", 0);
-        toInt32.insert("QScriptValue(engine, true)", 1);
-        toInt32.insert("QScriptValue(engine, false)", 0);
-        toInt32.insert("QScriptValue(engine, int(122))", 122);
-        toInt32.insert("QScriptValue(engine, uint(124))", 124);
-        toInt32.insert("QScriptValue(engine, 0)", 0);
-        toInt32.insert("QScriptValue(engine, 0.0)", 0);
-        toInt32.insert("QScriptValue(engine, 123.0)", 123);
-        toInt32.insert("QScriptValue(engine, 6.37e-8)", 0);
-        toInt32.insert("QScriptValue(engine, -6.37e-8)", 0);
-        toInt32.insert("QScriptValue(engine, 0x43211234)", 1126240820);
-        toInt32.insert("QScriptValue(engine, 0x10000)", 65536);
-        toInt32.insert("QScriptValue(engine, 0x10001)", 65537);
-        toInt32.insert("QScriptValue(engine, qSNaN())", 0);
-        toInt32.insert("QScriptValue(engine, qQNaN())", 0);
-        toInt32.insert("QScriptValue(engine, qInf())", 0);
-        toInt32.insert("QScriptValue(engine, -qInf())", 0);
-        toInt32.insert("QScriptValue(engine, \"NaN\")", 0);
-        toInt32.insert("QScriptValue(engine, \"Infinity\")", 0);
-        toInt32.insert("QScriptValue(engine, \"-Infinity\")", 0);
-        toInt32.insert("QScriptValue(engine, \"ciao\")", 0);
-        toInt32.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", 0);
-        toInt32.insert("QScriptValue(engine, QString(\"\"))", 0);
-        toInt32.insert("QScriptValue(engine, QString())", 0);
-        toInt32.insert("QScriptValue(engine, QString(\"0\"))", 0);
-        toInt32.insert("QScriptValue(engine, QString(\"123\"))", 123);
-        toInt32.insert("QScriptValue(engine, QString(\"1.23\"))", 1);
-        toInt32.insert("engine->evaluate(\"[]\")", 0);
-        toInt32.insert("engine->evaluate(\"{}\")", 0);
-        toInt32.insert("engine->evaluate(\"Object.prototype\")", 0);
-        toInt32.insert("engine->evaluate(\"Date.prototype\")", 0);
-        toInt32.insert("engine->evaluate(\"Array.prototype\")", 0);
-        toInt32.insert("engine->evaluate(\"Function.prototype\")", 0);
-        toInt32.insert("engine->evaluate(\"Error.prototype\")", 0);
-        toInt32.insert("engine->evaluate(\"Object\")", 0);
-        toInt32.insert("engine->evaluate(\"Array\")", 0);
-        toInt32.insert("engine->evaluate(\"Number\")", 0);
-        toInt32.insert("engine->evaluate(\"Function\")", 0);
-        toInt32.insert("engine->evaluate(\"(function() { return 1; })\")", 0);
-        toInt32.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", 0);
-        toInt32.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", 0);
-        toInt32.insert("engine->evaluate(\"/foo/\")", 0);
-        toInt32.insert("engine->evaluate(\"new Object()\")", 0);
-        toInt32.insert("engine->evaluate(\"new Array()\")", 0);
-        toInt32.insert("engine->evaluate(\"new Error()\")", 0);
-        toInt32.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22);
-        toInt32.insert("engine->evaluate(\"Undefined\")", 0);
-        toInt32.insert("engine->evaluate(\"Null\")", 0);
-        toInt32.insert("engine->evaluate(\"True\")", 0);
-        toInt32.insert("engine->evaluate(\"False\")", 0);
-        toInt32.insert("engine->evaluate(\"undefined\")", 0);
-        toInt32.insert("engine->evaluate(\"null\")", 0);
-        toInt32.insert("engine->evaluate(\"true\")", 1);
-        toInt32.insert("engine->evaluate(\"false\")", 0);
-        toInt32.insert("engine->evaluate(\"122\")", 122);
-        toInt32.insert("engine->evaluate(\"124\")", 124);
-        toInt32.insert("engine->evaluate(\"0\")", 0);
-        toInt32.insert("engine->evaluate(\"0.0\")", 0);
-        toInt32.insert("engine->evaluate(\"123.0\")", 123);
-        toInt32.insert("engine->evaluate(\"6.37e-8\")", 0);
-        toInt32.insert("engine->evaluate(\"-6.37e-8\")", 0);
-        toInt32.insert("engine->evaluate(\"0x43211234\")", 1126240820);
-        toInt32.insert("engine->evaluate(\"0x10000\")", 65536);
-        toInt32.insert("engine->evaluate(\"0x10001\")", 65537);
-        toInt32.insert("engine->evaluate(\"NaN\")", 0);
-        toInt32.insert("engine->evaluate(\"Infinity\")", 0);
-        toInt32.insert("engine->evaluate(\"-Infinity\")", 0);
-        toInt32.insert("engine->evaluate(\"'ciao'\")", 0);
-        toInt32.insert("engine->evaluate(\"''\")", 0);
-        toInt32.insert("engine->evaluate(\"'0'\")", 0);
-        toInt32.insert("engine->evaluate(\"'123'\")", 123);
-        toInt32.insert("engine->evaluate(\"'12.4'\")", 12);
-        toInt32.insert("engine->nullValue()", 0);
-        toInt32.insert("engine->undefinedValue()", 0);
-    }
-    newRow(expr) << toInt32.value(expr);
-}
-
-void tst_QScriptValue::toInt32_test(const char*, const QScriptValue& value)
-{
-    QFETCH(qint32, expected);
-    QCOMPARE(value.toInt32(), expected);
-    QCOMPARE(value.toInt32(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toInt32)
-
-
-void tst_QScriptValue::toUInt32_initData()
-{
-    QTest::addColumn<quint32>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toUInt32_makeData(const char* expr)
-{
-    static QHash<QString, quint32> toUInt32;
-    if (toUInt32.isEmpty()) {
-        toUInt32.insert("QScriptValue()", 0);
-        toUInt32.insert("QScriptValue(QScriptValue::UndefinedValue)", 0);
-        toUInt32.insert("QScriptValue(QScriptValue::NullValue)", 0);
-        toUInt32.insert("QScriptValue(true)", 1);
-        toUInt32.insert("QScriptValue(false)", 0);
-        toUInt32.insert("QScriptValue(int(122))", 122);
-        toUInt32.insert("QScriptValue(uint(124))", 124);
-        toUInt32.insert("QScriptValue(0)", 0);
-        toUInt32.insert("QScriptValue(0.0)", 0);
-        toUInt32.insert("QScriptValue(123.0)", 123);
-        toUInt32.insert("QScriptValue(6.37e-8)", 0);
-        toUInt32.insert("QScriptValue(-6.37e-8)", 0);
-        toUInt32.insert("QScriptValue(0x43211234)", 1126240820);
-        toUInt32.insert("QScriptValue(0x10000)", 65536);
-        toUInt32.insert("QScriptValue(0x10001)", 65537);
-        toUInt32.insert("QScriptValue(qSNaN())", 0);
-        toUInt32.insert("QScriptValue(qQNaN())", 0);
-        toUInt32.insert("QScriptValue(qInf())", 0);
-        toUInt32.insert("QScriptValue(-qInf())", 0);
-        toUInt32.insert("QScriptValue(\"NaN\")", 0);
-        toUInt32.insert("QScriptValue(\"Infinity\")", 0);
-        toUInt32.insert("QScriptValue(\"-Infinity\")", 0);
-        toUInt32.insert("QScriptValue(\"ciao\")", 0);
-        toUInt32.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", 0);
-        toUInt32.insert("QScriptValue(QString(\"\"))", 0);
-        toUInt32.insert("QScriptValue(QString())", 0);
-        toUInt32.insert("QScriptValue(QString(\"0\"))", 0);
-        toUInt32.insert("QScriptValue(QString(\"123\"))", 123);
-        toUInt32.insert("QScriptValue(QString(\"12.4\"))", 12);
-        toUInt32.insert("QScriptValue(0, QScriptValue::UndefinedValue)", 0);
-        toUInt32.insert("QScriptValue(0, QScriptValue::NullValue)", 0);
-        toUInt32.insert("QScriptValue(0, true)", 1);
-        toUInt32.insert("QScriptValue(0, false)", 0);
-        toUInt32.insert("QScriptValue(0, int(122))", 122);
-        toUInt32.insert("QScriptValue(0, uint(124))", 124);
-        toUInt32.insert("QScriptValue(0, 0)", 0);
-        toUInt32.insert("QScriptValue(0, 0.0)", 0);
-        toUInt32.insert("QScriptValue(0, 123.0)", 123);
-        toUInt32.insert("QScriptValue(0, 6.37e-8)", 0);
-        toUInt32.insert("QScriptValue(0, -6.37e-8)", 0);
-        toUInt32.insert("QScriptValue(0, 0x43211234)", 1126240820);
-        toUInt32.insert("QScriptValue(0, 0x10000)", 65536);
-        toUInt32.insert("QScriptValue(0, 0x10001)", 65537);
-        toUInt32.insert("QScriptValue(0, qSNaN())", 0);
-        toUInt32.insert("QScriptValue(0, qQNaN())", 0);
-        toUInt32.insert("QScriptValue(0, qInf())", 0);
-        toUInt32.insert("QScriptValue(0, -qInf())", 0);
-        toUInt32.insert("QScriptValue(0, \"NaN\")", 0);
-        toUInt32.insert("QScriptValue(0, \"Infinity\")", 0);
-        toUInt32.insert("QScriptValue(0, \"-Infinity\")", 0);
-        toUInt32.insert("QScriptValue(0, \"ciao\")", 0);
-        toUInt32.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", 0);
-        toUInt32.insert("QScriptValue(0, QString(\"\"))", 0);
-        toUInt32.insert("QScriptValue(0, QString())", 0);
-        toUInt32.insert("QScriptValue(0, QString(\"0\"))", 0);
-        toUInt32.insert("QScriptValue(0, QString(\"123\"))", 123);
-        toUInt32.insert("QScriptValue(0, QString(\"12.3\"))", 12);
-        toUInt32.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", 0);
-        toUInt32.insert("QScriptValue(engine, QScriptValue::NullValue)", 0);
-        toUInt32.insert("QScriptValue(engine, true)", 1);
-        toUInt32.insert("QScriptValue(engine, false)", 0);
-        toUInt32.insert("QScriptValue(engine, int(122))", 122);
-        toUInt32.insert("QScriptValue(engine, uint(124))", 124);
-        toUInt32.insert("QScriptValue(engine, 0)", 0);
-        toUInt32.insert("QScriptValue(engine, 0.0)", 0);
-        toUInt32.insert("QScriptValue(engine, 123.0)", 123);
-        toUInt32.insert("QScriptValue(engine, 6.37e-8)", 0);
-        toUInt32.insert("QScriptValue(engine, -6.37e-8)", 0);
-        toUInt32.insert("QScriptValue(engine, 0x43211234)", 1126240820);
-        toUInt32.insert("QScriptValue(engine, 0x10000)", 65536);
-        toUInt32.insert("QScriptValue(engine, 0x10001)", 65537);
-        toUInt32.insert("QScriptValue(engine, qSNaN())", 0);
-        toUInt32.insert("QScriptValue(engine, qQNaN())", 0);
-        toUInt32.insert("QScriptValue(engine, qInf())", 0);
-        toUInt32.insert("QScriptValue(engine, -qInf())", 0);
-        toUInt32.insert("QScriptValue(engine, \"NaN\")", 0);
-        toUInt32.insert("QScriptValue(engine, \"Infinity\")", 0);
-        toUInt32.insert("QScriptValue(engine, \"-Infinity\")", 0);
-        toUInt32.insert("QScriptValue(engine, \"ciao\")", 0);
-        toUInt32.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", 0);
-        toUInt32.insert("QScriptValue(engine, QString(\"\"))", 0);
-        toUInt32.insert("QScriptValue(engine, QString())", 0);
-        toUInt32.insert("QScriptValue(engine, QString(\"0\"))", 0);
-        toUInt32.insert("QScriptValue(engine, QString(\"123\"))", 123);
-        toUInt32.insert("QScriptValue(engine, QString(\"1.23\"))", 1);
-        toUInt32.insert("engine->evaluate(\"[]\")", 0);
-        toUInt32.insert("engine->evaluate(\"{}\")", 0);
-        toUInt32.insert("engine->evaluate(\"Object.prototype\")", 0);
-        toUInt32.insert("engine->evaluate(\"Date.prototype\")", 0);
-        toUInt32.insert("engine->evaluate(\"Array.prototype\")", 0);
-        toUInt32.insert("engine->evaluate(\"Function.prototype\")", 0);
-        toUInt32.insert("engine->evaluate(\"Error.prototype\")", 0);
-        toUInt32.insert("engine->evaluate(\"Object\")", 0);
-        toUInt32.insert("engine->evaluate(\"Array\")", 0);
-        toUInt32.insert("engine->evaluate(\"Number\")", 0);
-        toUInt32.insert("engine->evaluate(\"Function\")", 0);
-        toUInt32.insert("engine->evaluate(\"(function() { return 1; })\")", 0);
-        toUInt32.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", 0);
-        toUInt32.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", 0);
-        toUInt32.insert("engine->evaluate(\"/foo/\")", 0);
-        toUInt32.insert("engine->evaluate(\"new Object()\")", 0);
-        toUInt32.insert("engine->evaluate(\"new Array()\")", 0);
-        toUInt32.insert("engine->evaluate(\"new Error()\")", 0);
-        toUInt32.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22);
-        toUInt32.insert("engine->evaluate(\"Undefined\")", 0);
-        toUInt32.insert("engine->evaluate(\"Null\")", 0);
-        toUInt32.insert("engine->evaluate(\"True\")", 0);
-        toUInt32.insert("engine->evaluate(\"False\")", 0);
-        toUInt32.insert("engine->evaluate(\"undefined\")", 0);
-        toUInt32.insert("engine->evaluate(\"null\")", 0);
-        toUInt32.insert("engine->evaluate(\"true\")", 1);
-        toUInt32.insert("engine->evaluate(\"false\")", 0);
-        toUInt32.insert("engine->evaluate(\"122\")", 122);
-        toUInt32.insert("engine->evaluate(\"124\")", 124);
-        toUInt32.insert("engine->evaluate(\"0\")", 0);
-        toUInt32.insert("engine->evaluate(\"0.0\")", 0);
-        toUInt32.insert("engine->evaluate(\"123.0\")", 123);
-        toUInt32.insert("engine->evaluate(\"6.37e-8\")", 0);
-        toUInt32.insert("engine->evaluate(\"-6.37e-8\")", 0);
-        toUInt32.insert("engine->evaluate(\"0x43211234\")", 1126240820);
-        toUInt32.insert("engine->evaluate(\"0x10000\")", 65536);
-        toUInt32.insert("engine->evaluate(\"0x10001\")", 65537);
-        toUInt32.insert("engine->evaluate(\"NaN\")", 0);
-        toUInt32.insert("engine->evaluate(\"Infinity\")", 0);
-        toUInt32.insert("engine->evaluate(\"-Infinity\")", 0);
-        toUInt32.insert("engine->evaluate(\"'ciao'\")", 0);
-        toUInt32.insert("engine->evaluate(\"''\")", 0);
-        toUInt32.insert("engine->evaluate(\"'0'\")", 0);
-        toUInt32.insert("engine->evaluate(\"'123'\")", 123);
-        toUInt32.insert("engine->evaluate(\"'12.4'\")", 12);
-        toUInt32.insert("engine->nullValue()", 0);
-        toUInt32.insert("engine->undefinedValue()", 0);
-    }
-    newRow(expr) << toUInt32.value(expr);
-}
-
-void tst_QScriptValue::toUInt32_test(const char*, const QScriptValue& value)
-{
-    QFETCH(quint32, expected);
-    QCOMPARE(value.toUInt32(), expected);
-    QCOMPARE(value.toUInt32(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toUInt32)
-
-
-void tst_QScriptValue::toUInt16_initData()
-{
-    QTest::addColumn<quint16>("expected");
-    initScriptValues();
-}
-
-void tst_QScriptValue::toUInt16_makeData(const char* expr)
-{
-    static QHash<QString, quint16> toUInt16;
-    if (toUInt16.isEmpty()) {
-        toUInt16.insert("QScriptValue()", 0);
-        toUInt16.insert("QScriptValue(QScriptValue::UndefinedValue)", 0);
-        toUInt16.insert("QScriptValue(QScriptValue::NullValue)", 0);
-        toUInt16.insert("QScriptValue(true)", 1);
-        toUInt16.insert("QScriptValue(false)", 0);
-        toUInt16.insert("QScriptValue(int(122))", 122);
-        toUInt16.insert("QScriptValue(uint(124))", 124);
-        toUInt16.insert("QScriptValue(0)", 0);
-        toUInt16.insert("QScriptValue(0.0)", 0);
-        toUInt16.insert("QScriptValue(123.0)", 123);
-        toUInt16.insert("QScriptValue(6.37e-8)", 0);
-        toUInt16.insert("QScriptValue(-6.37e-8)", 0);
-        toUInt16.insert("QScriptValue(0x43211234)", 4660);
-        toUInt16.insert("QScriptValue(0x10000)", 0);
-        toUInt16.insert("QScriptValue(0x10001)", 1);
-        toUInt16.insert("QScriptValue(qSNaN())", 0);
-        toUInt16.insert("QScriptValue(qQNaN())", 0);
-        toUInt16.insert("QScriptValue(qInf())", 0);
-        toUInt16.insert("QScriptValue(-qInf())", 0);
-        toUInt16.insert("QScriptValue(\"NaN\")", 0);
-        toUInt16.insert("QScriptValue(\"Infinity\")", 0);
-        toUInt16.insert("QScriptValue(\"-Infinity\")", 0);
-        toUInt16.insert("QScriptValue(\"ciao\")", 0);
-        toUInt16.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", 0);
-        toUInt16.insert("QScriptValue(QString(\"\"))", 0);
-        toUInt16.insert("QScriptValue(QString())", 0);
-        toUInt16.insert("QScriptValue(QString(\"0\"))", 0);
-        toUInt16.insert("QScriptValue(QString(\"123\"))", 123);
-        toUInt16.insert("QScriptValue(QString(\"12.4\"))", 12);
-        toUInt16.insert("QScriptValue(0, QScriptValue::UndefinedValue)", 0);
-        toUInt16.insert("QScriptValue(0, QScriptValue::NullValue)", 0);
-        toUInt16.insert("QScriptValue(0, true)", 1);
-        toUInt16.insert("QScriptValue(0, false)", 0);
-        toUInt16.insert("QScriptValue(0, int(122))", 122);
-        toUInt16.insert("QScriptValue(0, uint(124))", 124);
-        toUInt16.insert("QScriptValue(0, 0)", 0);
-        toUInt16.insert("QScriptValue(0, 0.0)", 0);
-        toUInt16.insert("QScriptValue(0, 123.0)", 123);
-        toUInt16.insert("QScriptValue(0, 6.37e-8)", 0);
-        toUInt16.insert("QScriptValue(0, -6.37e-8)", 0);
-        toUInt16.insert("QScriptValue(0, 0x43211234)", 4660);
-        toUInt16.insert("QScriptValue(0, 0x10000)", 0);
-        toUInt16.insert("QScriptValue(0, 0x10001)", 1);
-        toUInt16.insert("QScriptValue(0, qSNaN())", 0);
-        toUInt16.insert("QScriptValue(0, qQNaN())", 0);
-        toUInt16.insert("QScriptValue(0, qInf())", 0);
-        toUInt16.insert("QScriptValue(0, -qInf())", 0);
-        toUInt16.insert("QScriptValue(0, \"NaN\")", 0);
-        toUInt16.insert("QScriptValue(0, \"Infinity\")", 0);
-        toUInt16.insert("QScriptValue(0, \"-Infinity\")", 0);
-        toUInt16.insert("QScriptValue(0, \"ciao\")", 0);
-        toUInt16.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", 0);
-        toUInt16.insert("QScriptValue(0, QString(\"\"))", 0);
-        toUInt16.insert("QScriptValue(0, QString())", 0);
-        toUInt16.insert("QScriptValue(0, QString(\"0\"))", 0);
-        toUInt16.insert("QScriptValue(0, QString(\"123\"))", 123);
-        toUInt16.insert("QScriptValue(0, QString(\"12.3\"))", 12);
-        toUInt16.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", 0);
-        toUInt16.insert("QScriptValue(engine, QScriptValue::NullValue)", 0);
-        toUInt16.insert("QScriptValue(engine, true)", 1);
-        toUInt16.insert("QScriptValue(engine, false)", 0);
-        toUInt16.insert("QScriptValue(engine, int(122))", 122);
-        toUInt16.insert("QScriptValue(engine, uint(124))", 124);
-        toUInt16.insert("QScriptValue(engine, 0)", 0);
-        toUInt16.insert("QScriptValue(engine, 0.0)", 0);
-        toUInt16.insert("QScriptValue(engine, 123.0)", 123);
-        toUInt16.insert("QScriptValue(engine, 6.37e-8)", 0);
-        toUInt16.insert("QScriptValue(engine, -6.37e-8)", 0);
-        toUInt16.insert("QScriptValue(engine, 0x43211234)", 4660);
-        toUInt16.insert("QScriptValue(engine, 0x10000)", 0);
-        toUInt16.insert("QScriptValue(engine, 0x10001)", 1);
-        toUInt16.insert("QScriptValue(engine, qSNaN())", 0);
-        toUInt16.insert("QScriptValue(engine, qQNaN())", 0);
-        toUInt16.insert("QScriptValue(engine, qInf())", 0);
-        toUInt16.insert("QScriptValue(engine, -qInf())", 0);
-        toUInt16.insert("QScriptValue(engine, \"NaN\")", 0);
-        toUInt16.insert("QScriptValue(engine, \"Infinity\")", 0);
-        toUInt16.insert("QScriptValue(engine, \"-Infinity\")", 0);
-        toUInt16.insert("QScriptValue(engine, \"ciao\")", 0);
-        toUInt16.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", 0);
-        toUInt16.insert("QScriptValue(engine, QString(\"\"))", 0);
-        toUInt16.insert("QScriptValue(engine, QString())", 0);
-        toUInt16.insert("QScriptValue(engine, QString(\"0\"))", 0);
-        toUInt16.insert("QScriptValue(engine, QString(\"123\"))", 123);
-        toUInt16.insert("QScriptValue(engine, QString(\"1.23\"))", 1);
-        toUInt16.insert("engine->evaluate(\"[]\")", 0);
-        toUInt16.insert("engine->evaluate(\"{}\")", 0);
-        toUInt16.insert("engine->evaluate(\"Object.prototype\")", 0);
-        toUInt16.insert("engine->evaluate(\"Date.prototype\")", 0);
-        toUInt16.insert("engine->evaluate(\"Array.prototype\")", 0);
-        toUInt16.insert("engine->evaluate(\"Function.prototype\")", 0);
-        toUInt16.insert("engine->evaluate(\"Error.prototype\")", 0);
-        toUInt16.insert("engine->evaluate(\"Object\")", 0);
-        toUInt16.insert("engine->evaluate(\"Array\")", 0);
-        toUInt16.insert("engine->evaluate(\"Number\")", 0);
-        toUInt16.insert("engine->evaluate(\"Function\")", 0);
-        toUInt16.insert("engine->evaluate(\"(function() { return 1; })\")", 0);
-        toUInt16.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", 0);
-        toUInt16.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", 0);
-        toUInt16.insert("engine->evaluate(\"/foo/\")", 0);
-        toUInt16.insert("engine->evaluate(\"new Object()\")", 0);
-        toUInt16.insert("engine->evaluate(\"new Array()\")", 0);
-        toUInt16.insert("engine->evaluate(\"new Error()\")", 0);
-        toUInt16.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22);
-        toUInt16.insert("engine->evaluate(\"Undefined\")", 0);
-        toUInt16.insert("engine->evaluate(\"Null\")", 0);
-        toUInt16.insert("engine->evaluate(\"True\")", 0);
-        toUInt16.insert("engine->evaluate(\"False\")", 0);
-        toUInt16.insert("engine->evaluate(\"undefined\")", 0);
-        toUInt16.insert("engine->evaluate(\"null\")", 0);
-        toUInt16.insert("engine->evaluate(\"true\")", 1);
-        toUInt16.insert("engine->evaluate(\"false\")", 0);
-        toUInt16.insert("engine->evaluate(\"122\")", 122);
-        toUInt16.insert("engine->evaluate(\"124\")", 124);
-        toUInt16.insert("engine->evaluate(\"0\")", 0);
-        toUInt16.insert("engine->evaluate(\"0.0\")", 0);
-        toUInt16.insert("engine->evaluate(\"123.0\")", 123);
-        toUInt16.insert("engine->evaluate(\"6.37e-8\")", 0);
-        toUInt16.insert("engine->evaluate(\"-6.37e-8\")", 0);
-        toUInt16.insert("engine->evaluate(\"0x43211234\")", 4660);
-        toUInt16.insert("engine->evaluate(\"0x10000\")", 0);
-        toUInt16.insert("engine->evaluate(\"0x10001\")", 1);
-        toUInt16.insert("engine->evaluate(\"NaN\")", 0);
-        toUInt16.insert("engine->evaluate(\"Infinity\")", 0);
-        toUInt16.insert("engine->evaluate(\"-Infinity\")", 0);
-        toUInt16.insert("engine->evaluate(\"'ciao'\")", 0);
-        toUInt16.insert("engine->evaluate(\"''\")", 0);
-        toUInt16.insert("engine->evaluate(\"'0'\")", 0);
-        toUInt16.insert("engine->evaluate(\"'123'\")", 123);
-        toUInt16.insert("engine->evaluate(\"'12.4'\")", 12);
-        toUInt16.insert("engine->nullValue()", 0);
-        toUInt16.insert("engine->undefinedValue()", 0);
-    }
-    newRow(expr) << toUInt16.value(expr);
-}
-
-void tst_QScriptValue::toUInt16_test(const char*, const QScriptValue& value)
-{
-    QFETCH(quint16, expected);
-    QCOMPARE(value.toUInt16(), expected);
-    QCOMPARE(value.toUInt16(), expected);
-}
-
-DEFINE_TEST_FUNCTION(toUInt16)
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue_generated_comparison.cpp
new file mode 100644 (file)
index 0000000..3209530
--- /dev/null
@@ -0,0 +1,1799 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+/****************************************************************************
+*************** This file has been generated. DO NOT MODIFY! ****************
+****************************************************************************/
+
+#include "tst_qscriptvalue.h"
+
+static const QString equals_array[] = {
+    "QScriptValue() <=> QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->nullValue()",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->undefinedValue()",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->nullValue()",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->undefinedValue()",
+    "QScriptValue(true) <=> QScriptValue(true)",
+    "QScriptValue(true) <=> QScriptValue(0, true)",
+    "QScriptValue(true) <=> QScriptValue(engine, true)",
+    "QScriptValue(true) <=> engine->evaluate(\"true\")",
+    "QScriptValue(false) <=> QScriptValue(false)",
+    "QScriptValue(false) <=> QScriptValue(0)",
+    "QScriptValue(false) <=> QScriptValue(0.0)",
+    "QScriptValue(false) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(false) <=> QScriptValue(QString())",
+    "QScriptValue(false) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(false) <=> QScriptValue(0, false)",
+    "QScriptValue(false) <=> QScriptValue(0, 0)",
+    "QScriptValue(false) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(false) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(false) <=> QScriptValue(0, QString())",
+    "QScriptValue(false) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(false) <=> QScriptValue(engine, false)",
+    "QScriptValue(false) <=> QScriptValue(engine, 0)",
+    "QScriptValue(false) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(false) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(false) <=> QScriptValue(engine, QString())",
+    "QScriptValue(false) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(false) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(false) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(false) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(false) <=> engine->evaluate(\"false\")",
+    "QScriptValue(false) <=> engine->evaluate(\"0\")",
+    "QScriptValue(false) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(false) <=> engine->evaluate(\"''\")",
+    "QScriptValue(false) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(false) <=> engine->newArray()",
+    "QScriptValue(int(122)) <=> QScriptValue(int(122))",
+    "QScriptValue(int(122)) <=> QScriptValue(0, int(122))",
+    "QScriptValue(int(122)) <=> QScriptValue(engine, int(122))",
+    "QScriptValue(int(122)) <=> engine->evaluate(\"122\")",
+    "QScriptValue(uint(124)) <=> QScriptValue(uint(124))",
+    "QScriptValue(uint(124)) <=> QScriptValue(0, uint(124))",
+    "QScriptValue(uint(124)) <=> QScriptValue(engine, uint(124))",
+    "QScriptValue(uint(124)) <=> engine->evaluate(\"124\")",
+    "QScriptValue(0) <=> QScriptValue(false)",
+    "QScriptValue(0) <=> QScriptValue(0)",
+    "QScriptValue(0) <=> QScriptValue(0.0)",
+    "QScriptValue(0) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0) <=> QScriptValue(QString())",
+    "QScriptValue(0) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0) <=> QScriptValue(0, false)",
+    "QScriptValue(0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0) <=> QScriptValue(0, QString())",
+    "QScriptValue(0) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0) <=> QScriptValue(engine, false)",
+    "QScriptValue(0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0) <=> engine->newArray()",
+    "QScriptValue(0.0) <=> QScriptValue(false)",
+    "QScriptValue(0.0) <=> QScriptValue(0)",
+    "QScriptValue(0.0) <=> QScriptValue(0.0)",
+    "QScriptValue(0.0) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0.0) <=> QScriptValue(QString())",
+    "QScriptValue(0.0) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0.0) <=> QScriptValue(0, false)",
+    "QScriptValue(0.0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0.0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0.0) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0.0) <=> QScriptValue(0, QString())",
+    "QScriptValue(0.0) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0.0) <=> QScriptValue(engine, false)",
+    "QScriptValue(0.0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0.0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0.0) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0.0) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0.0) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0.0) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0.0) <=> engine->newArray()",
+    "QScriptValue(123.0) <=> QScriptValue(123.0)",
+    "QScriptValue(123.0) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(123.0) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(123.0) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(123.0) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(123.0) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(123.0) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(123.0) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(6.37e-8) <=> QScriptValue(6.37e-8)",
+    "QScriptValue(6.37e-8) <=> QScriptValue(0, 6.37e-8)",
+    "QScriptValue(6.37e-8) <=> QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(6.37e-8) <=> engine->evaluate(\"6.37e-8\")",
+    "QScriptValue(-6.37e-8) <=> QScriptValue(-6.37e-8)",
+    "QScriptValue(-6.37e-8) <=> QScriptValue(0, -6.37e-8)",
+    "QScriptValue(-6.37e-8) <=> QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(-6.37e-8) <=> engine->evaluate(\"-6.37e-8\")",
+    "QScriptValue(0x43211234) <=> QScriptValue(0x43211234)",
+    "QScriptValue(0x43211234) <=> QScriptValue(0, 0x43211234)",
+    "QScriptValue(0x43211234) <=> QScriptValue(engine, 0x43211234)",
+    "QScriptValue(0x43211234) <=> engine->evaluate(\"0x43211234\")",
+    "QScriptValue(0x10000) <=> QScriptValue(0x10000)",
+    "QScriptValue(0x10000) <=> QScriptValue(0, 0x10000)",
+    "QScriptValue(0x10000) <=> QScriptValue(engine, 0x10000)",
+    "QScriptValue(0x10000) <=> engine->evaluate(\"0x10000\")",
+    "QScriptValue(0x10001) <=> QScriptValue(0x10001)",
+    "QScriptValue(0x10001) <=> QScriptValue(0, 0x10001)",
+    "QScriptValue(0x10001) <=> QScriptValue(engine, 0x10001)",
+    "QScriptValue(0x10001) <=> engine->evaluate(\"0x10001\")",
+    "QScriptValue(qInf()) <=> QScriptValue(qInf())",
+    "QScriptValue(qInf()) <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(qInf()) <=> QScriptValue(0, qInf())",
+    "QScriptValue(qInf()) <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(qInf()) <=> QScriptValue(engine, qInf())",
+    "QScriptValue(qInf()) <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(qInf()) <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(-qInf()) <=> QScriptValue(-qInf())",
+    "QScriptValue(-qInf()) <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(-qInf()) <=> QScriptValue(0, -qInf())",
+    "QScriptValue(-qInf()) <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(-qInf()) <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(-qInf()) <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(-qInf()) <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(\"NaN\") <=> QScriptValue(\"NaN\")",
+    "QScriptValue(\"NaN\") <=> QScriptValue(0, \"NaN\")",
+    "QScriptValue(\"NaN\") <=> QScriptValue(engine, \"NaN\")",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(qInf())",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(0, qInf())",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(engine, qInf())",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(\"Infinity\") <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(-qInf())",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(0, -qInf())",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(\"ciao\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(\"ciao\") <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(\"ciao\") <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(\"ciao\") <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(false)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0.0)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(QString())",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, false)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, 0)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, QString())",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, false)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, 0)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, QString())",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"false\")",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"0\")",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"''\")",
+    "QScriptValue(QString(\"\")) <=> engine->newArray()",
+    "QScriptValue(QString()) <=> QScriptValue(false)",
+    "QScriptValue(QString()) <=> QScriptValue(0)",
+    "QScriptValue(QString()) <=> QScriptValue(0.0)",
+    "QScriptValue(QString()) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(QString()) <=> QScriptValue(QString())",
+    "QScriptValue(QString()) <=> QScriptValue(0, false)",
+    "QScriptValue(QString()) <=> QScriptValue(0, 0)",
+    "QScriptValue(QString()) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(QString()) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(QString()) <=> QScriptValue(0, QString())",
+    "QScriptValue(QString()) <=> QScriptValue(engine, false)",
+    "QScriptValue(QString()) <=> QScriptValue(engine, 0)",
+    "QScriptValue(QString()) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(QString()) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(QString()) <=> QScriptValue(engine, QString())",
+    "QScriptValue(QString()) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(QString()) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(QString()) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(QString()) <=> engine->evaluate(\"false\")",
+    "QScriptValue(QString()) <=> engine->evaluate(\"0\")",
+    "QScriptValue(QString()) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(QString()) <=> engine->evaluate(\"''\")",
+    "QScriptValue(QString()) <=> engine->newArray()",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(false)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0.0)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0, false)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0, 0)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(engine, false)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(engine, 0)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(QString(\"0\")) <=> engine->evaluate(\"false\")",
+    "QScriptValue(QString(\"0\")) <=> engine->evaluate(\"0\")",
+    "QScriptValue(QString(\"0\")) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(QString(\"0\")) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(123.0)",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(QString(\"123\")) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(QString(\"123\")) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(QString(\"12.4\")) <=> QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(QString(\"12.4\")) <=> engine->evaluate(\"'12.4'\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->nullValue()",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->undefinedValue()",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->nullValue()",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->undefinedValue()",
+    "QScriptValue(0, true) <=> QScriptValue(true)",
+    "QScriptValue(0, true) <=> QScriptValue(0, true)",
+    "QScriptValue(0, true) <=> QScriptValue(engine, true)",
+    "QScriptValue(0, true) <=> engine->evaluate(\"true\")",
+    "QScriptValue(0, false) <=> QScriptValue(false)",
+    "QScriptValue(0, false) <=> QScriptValue(0)",
+    "QScriptValue(0, false) <=> QScriptValue(0.0)",
+    "QScriptValue(0, false) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, false) <=> QScriptValue(QString())",
+    "QScriptValue(0, false) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0, false) <=> QScriptValue(0, false)",
+    "QScriptValue(0, false) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, false) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, false) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, false) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, false) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, false) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, false) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, false) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, false) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, false) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, false) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0, false) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, false) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0, false) <=> engine->newArray()",
+    "QScriptValue(0, int(122)) <=> QScriptValue(int(122))",
+    "QScriptValue(0, int(122)) <=> QScriptValue(0, int(122))",
+    "QScriptValue(0, int(122)) <=> QScriptValue(engine, int(122))",
+    "QScriptValue(0, int(122)) <=> engine->evaluate(\"122\")",
+    "QScriptValue(0, uint(124)) <=> QScriptValue(uint(124))",
+    "QScriptValue(0, uint(124)) <=> QScriptValue(0, uint(124))",
+    "QScriptValue(0, uint(124)) <=> QScriptValue(engine, uint(124))",
+    "QScriptValue(0, uint(124)) <=> engine->evaluate(\"124\")",
+    "QScriptValue(0, 0) <=> QScriptValue(false)",
+    "QScriptValue(0, 0) <=> QScriptValue(0)",
+    "QScriptValue(0, 0) <=> QScriptValue(0.0)",
+    "QScriptValue(0, 0) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, 0) <=> QScriptValue(QString())",
+    "QScriptValue(0, 0) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0, 0) <=> QScriptValue(0, false)",
+    "QScriptValue(0, 0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, 0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, 0) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, 0) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, 0) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0, 0) <=> engine->newArray()",
+    "QScriptValue(0, 0.0) <=> QScriptValue(false)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0.0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, 0.0) <=> QScriptValue(QString())",
+    "QScriptValue(0, 0.0) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, false)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0, 0.0) <=> engine->newArray()",
+    "QScriptValue(0, 123.0) <=> QScriptValue(123.0)",
+    "QScriptValue(0, 123.0) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(0, 123.0) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(0, 123.0) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, 123.0) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(0, 123.0) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(0, 123.0) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(0, 123.0) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(0, 6.37e-8) <=> QScriptValue(6.37e-8)",
+    "QScriptValue(0, 6.37e-8) <=> QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, 6.37e-8) <=> QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(0, 6.37e-8) <=> engine->evaluate(\"6.37e-8\")",
+    "QScriptValue(0, -6.37e-8) <=> QScriptValue(-6.37e-8)",
+    "QScriptValue(0, -6.37e-8) <=> QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, -6.37e-8) <=> QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(0, -6.37e-8) <=> engine->evaluate(\"-6.37e-8\")",
+    "QScriptValue(0, 0x43211234) <=> QScriptValue(0x43211234)",
+    "QScriptValue(0, 0x43211234) <=> QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x43211234) <=> QScriptValue(engine, 0x43211234)",
+    "QScriptValue(0, 0x43211234) <=> engine->evaluate(\"0x43211234\")",
+    "QScriptValue(0, 0x10000) <=> QScriptValue(0x10000)",
+    "QScriptValue(0, 0x10000) <=> QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10000) <=> QScriptValue(engine, 0x10000)",
+    "QScriptValue(0, 0x10000) <=> engine->evaluate(\"0x10000\")",
+    "QScriptValue(0, 0x10001) <=> QScriptValue(0x10001)",
+    "QScriptValue(0, 0x10001) <=> QScriptValue(0, 0x10001)",
+    "QScriptValue(0, 0x10001) <=> QScriptValue(engine, 0x10001)",
+    "QScriptValue(0, 0x10001) <=> engine->evaluate(\"0x10001\")",
+    "QScriptValue(0, qInf()) <=> QScriptValue(qInf())",
+    "QScriptValue(0, qInf()) <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(0, qInf()) <=> QScriptValue(0, qInf())",
+    "QScriptValue(0, qInf()) <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, qInf()) <=> QScriptValue(engine, qInf())",
+    "QScriptValue(0, qInf()) <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(0, qInf()) <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(-qInf())",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(0, -qInf())",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(0, -qInf()) <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(0, \"NaN\") <=> QScriptValue(\"NaN\")",
+    "QScriptValue(0, \"NaN\") <=> QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"NaN\") <=> QScriptValue(engine, \"NaN\")",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(qInf())",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(0, qInf())",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(engine, qInf())",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(0, \"Infinity\") <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(-qInf())",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(\"ciao\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, \"ciao\") <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(\"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(false)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0.0)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(QString())",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, false)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, QString(\"\")) <=> engine->newArray()",
+    "QScriptValue(0, QString()) <=> QScriptValue(false)",
+    "QScriptValue(0, QString()) <=> QScriptValue(0)",
+    "QScriptValue(0, QString()) <=> QScriptValue(0.0)",
+    "QScriptValue(0, QString()) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, QString()) <=> QScriptValue(QString())",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, false)",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, QString()) <=> engine->newArray()",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(false)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0.0)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0, false)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0, QString(\"0\")) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, QString(\"0\")) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, QString(\"0\")) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, QString(\"0\")) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(123.0)",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(0, QString(\"123\")) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(0, QString(\"123\")) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(0, QString(\"12.3\")) <=> QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->nullValue()",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->undefinedValue()",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->nullValue()",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->undefinedValue()",
+    "QScriptValue(engine, true) <=> QScriptValue(true)",
+    "QScriptValue(engine, true) <=> QScriptValue(0, true)",
+    "QScriptValue(engine, true) <=> QScriptValue(engine, true)",
+    "QScriptValue(engine, true) <=> engine->evaluate(\"true\")",
+    "QScriptValue(engine, false) <=> QScriptValue(false)",
+    "QScriptValue(engine, false) <=> QScriptValue(0)",
+    "QScriptValue(engine, false) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, false) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, false) <=> QScriptValue(QString())",
+    "QScriptValue(engine, false) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(engine, false) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, false) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, false) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, false) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, false) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, false) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(engine, false) <=> engine->newArray()",
+    "QScriptValue(engine, int(122)) <=> QScriptValue(int(122))",
+    "QScriptValue(engine, int(122)) <=> QScriptValue(0, int(122))",
+    "QScriptValue(engine, int(122)) <=> QScriptValue(engine, int(122))",
+    "QScriptValue(engine, int(122)) <=> engine->evaluate(\"122\")",
+    "QScriptValue(engine, uint(124)) <=> QScriptValue(uint(124))",
+    "QScriptValue(engine, uint(124)) <=> QScriptValue(0, uint(124))",
+    "QScriptValue(engine, uint(124)) <=> QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, uint(124)) <=> engine->evaluate(\"124\")",
+    "QScriptValue(engine, 0) <=> QScriptValue(false)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, 0) <=> QScriptValue(QString())",
+    "QScriptValue(engine, 0) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(engine, 0) <=> engine->newArray()",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(false)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(QString())",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(engine, 0.0) <=> engine->newArray()",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(123.0)",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, 123.0) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(engine, 123.0) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(engine, 6.37e-8) <=> QScriptValue(6.37e-8)",
+    "QScriptValue(engine, 6.37e-8) <=> QScriptValue(0, 6.37e-8)",
+    "QScriptValue(engine, 6.37e-8) <=> QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, 6.37e-8) <=> engine->evaluate(\"6.37e-8\")",
+    "QScriptValue(engine, -6.37e-8) <=> QScriptValue(-6.37e-8)",
+    "QScriptValue(engine, -6.37e-8) <=> QScriptValue(0, -6.37e-8)",
+    "QScriptValue(engine, -6.37e-8) <=> QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, -6.37e-8) <=> engine->evaluate(\"-6.37e-8\")",
+    "QScriptValue(engine, 0x43211234) <=> QScriptValue(0x43211234)",
+    "QScriptValue(engine, 0x43211234) <=> QScriptValue(0, 0x43211234)",
+    "QScriptValue(engine, 0x43211234) <=> QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x43211234) <=> engine->evaluate(\"0x43211234\")",
+    "QScriptValue(engine, 0x10000) <=> QScriptValue(0x10000)",
+    "QScriptValue(engine, 0x10000) <=> QScriptValue(0, 0x10000)",
+    "QScriptValue(engine, 0x10000) <=> QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10000) <=> engine->evaluate(\"0x10000\")",
+    "QScriptValue(engine, 0x10001) <=> QScriptValue(0x10001)",
+    "QScriptValue(engine, 0x10001) <=> QScriptValue(0, 0x10001)",
+    "QScriptValue(engine, 0x10001) <=> QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, 0x10001) <=> engine->evaluate(\"0x10001\")",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(qInf())",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(0, qInf())",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(engine, qInf())",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, qInf()) <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(-qInf())",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(0, -qInf())",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, -qInf()) <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(engine, \"NaN\") <=> QScriptValue(\"NaN\")",
+    "QScriptValue(engine, \"NaN\") <=> QScriptValue(0, \"NaN\")",
+    "QScriptValue(engine, \"NaN\") <=> QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(qInf())",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(0, qInf())",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(engine, qInf())",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"Infinity\") <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(-qInf())",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(0, -qInf())",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(\"ciao\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, \"ciao\") <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(\"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(false)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(QString())",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, QString(\"\")) <=> engine->newArray()",
+    "QScriptValue(engine, QString()) <=> QScriptValue(false)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, QString()) <=> QScriptValue(QString())",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"[]\")",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"Array.prototype\")",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"new Array()\")",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, QString()) <=> engine->newArray()",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(false)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"0\")) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, QString(\"0\")) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, QString(\"0\")) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, QString(\"0\")) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(123.0)",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"123\")) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(engine, QString(\"123\")) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(engine, QString(\"1.23\")) <=> QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\") <=> QScriptValue(false)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"[]\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"[]\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"[]\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"[]\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"[]\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"[]\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"[]\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"[]\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"[]\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"{}\") <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->evaluate(\"{}\") <=> engine->evaluate(\"{}\")",
+    "engine->evaluate(\"{}\") <=> engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"{}\") <=> engine->evaluate(\"null\")",
+    "engine->evaluate(\"{}\") <=> engine->nullValue()",
+    "engine->evaluate(\"{}\") <=> engine->undefinedValue()",
+    "engine->evaluate(\"Object.prototype\") <=> engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\") <=> engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(false)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"Array.prototype\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"Function.prototype\") <=> engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\") <=> engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\") <=> engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\") <=> engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(false)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"new Array()\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"new Array()\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"new Array()\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"new Array()\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"new Array()\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\") <=> engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->evaluate(\"undefined\") <=> engine->evaluate(\"{}\")",
+    "engine->evaluate(\"undefined\") <=> engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"undefined\") <=> engine->evaluate(\"null\")",
+    "engine->evaluate(\"undefined\") <=> engine->nullValue()",
+    "engine->evaluate(\"undefined\") <=> engine->undefinedValue()",
+    "engine->evaluate(\"null\") <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->evaluate(\"null\") <=> engine->evaluate(\"{}\")",
+    "engine->evaluate(\"null\") <=> engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\") <=> engine->evaluate(\"null\")",
+    "engine->evaluate(\"null\") <=> engine->nullValue()",
+    "engine->evaluate(\"null\") <=> engine->undefinedValue()",
+    "engine->evaluate(\"true\") <=> QScriptValue(true)",
+    "engine->evaluate(\"true\") <=> QScriptValue(0, true)",
+    "engine->evaluate(\"true\") <=> QScriptValue(engine, true)",
+    "engine->evaluate(\"true\") <=> engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\") <=> QScriptValue(false)",
+    "engine->evaluate(\"false\") <=> QScriptValue(0)",
+    "engine->evaluate(\"false\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"false\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"false\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"false\") <=> QScriptValue(QString(\"0\"))",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, QString(\"0\"))",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, QString(\"0\"))",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"[]\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"false\") <=> engine->newArray()",
+    "engine->evaluate(\"122\") <=> QScriptValue(int(122))",
+    "engine->evaluate(\"122\") <=> QScriptValue(0, int(122))",
+    "engine->evaluate(\"122\") <=> QScriptValue(engine, int(122))",
+    "engine->evaluate(\"122\") <=> engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\") <=> QScriptValue(uint(124))",
+    "engine->evaluate(\"124\") <=> QScriptValue(0, uint(124))",
+    "engine->evaluate(\"124\") <=> QScriptValue(engine, uint(124))",
+    "engine->evaluate(\"124\") <=> engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\") <=> QScriptValue(false)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"0\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"0\") <=> QScriptValue(QString(\"0\"))",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, QString(\"0\"))",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, QString(\"0\"))",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"[]\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"0\") <=> engine->newArray()",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(false)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(QString(\"0\"))",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, QString(\"0\"))",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, QString(\"0\"))",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"[]\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"0.0\") <=> engine->newArray()",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(123.0)",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(QString(\"123\"))",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(0, 123.0)",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(0, QString(\"123\"))",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(engine, 123.0)",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(engine, QString(\"123\"))",
+    "engine->evaluate(\"123.0\") <=> engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"123.0\") <=> engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"6.37e-8\") <=> QScriptValue(6.37e-8)",
+    "engine->evaluate(\"6.37e-8\") <=> QScriptValue(0, 6.37e-8)",
+    "engine->evaluate(\"6.37e-8\") <=> QScriptValue(engine, 6.37e-8)",
+    "engine->evaluate(\"6.37e-8\") <=> engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\") <=> QScriptValue(-6.37e-8)",
+    "engine->evaluate(\"-6.37e-8\") <=> QScriptValue(0, -6.37e-8)",
+    "engine->evaluate(\"-6.37e-8\") <=> QScriptValue(engine, -6.37e-8)",
+    "engine->evaluate(\"-6.37e-8\") <=> engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\") <=> QScriptValue(0x43211234)",
+    "engine->evaluate(\"0x43211234\") <=> QScriptValue(0, 0x43211234)",
+    "engine->evaluate(\"0x43211234\") <=> QScriptValue(engine, 0x43211234)",
+    "engine->evaluate(\"0x43211234\") <=> engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\") <=> QScriptValue(0x10000)",
+    "engine->evaluate(\"0x10000\") <=> QScriptValue(0, 0x10000)",
+    "engine->evaluate(\"0x10000\") <=> QScriptValue(engine, 0x10000)",
+    "engine->evaluate(\"0x10000\") <=> engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\") <=> QScriptValue(0x10001)",
+    "engine->evaluate(\"0x10001\") <=> QScriptValue(0, 0x10001)",
+    "engine->evaluate(\"0x10001\") <=> QScriptValue(engine, 0x10001)",
+    "engine->evaluate(\"0x10001\") <=> engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(qInf())",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(0, qInf())",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(engine, qInf())",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "engine->evaluate(\"Infinity\") <=> engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(-qInf())",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(0, -qInf())",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(engine, -qInf())",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "engine->evaluate(\"-Infinity\") <=> engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(\"ciao\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(0, \"ciao\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(engine, \"ciao\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "engine->evaluate(\"'ciao'\") <=> engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\") <=> QScriptValue(false)",
+    "engine->evaluate(\"''\") <=> QScriptValue(0)",
+    "engine->evaluate(\"''\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"''\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"''\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"[]\")",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"''\") <=> engine->newArray()",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(false)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(QString(\"0\"))",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0, QString(\"0\"))",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(engine, QString(\"0\"))",
+    "engine->evaluate(\"'0'\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"'0'\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"'0'\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"'0'\") <=> engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(123.0)",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(QString(\"123\"))",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(0, 123.0)",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(0, QString(\"123\"))",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(engine, 123.0)",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(engine, QString(\"123\"))",
+    "engine->evaluate(\"'123'\") <=> engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"'123'\") <=> engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\") <=> QScriptValue(QString(\"12.4\"))",
+    "engine->evaluate(\"'12.4'\") <=> engine->evaluate(\"'12.4'\")",
+    "engine->nullValue() <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->nullValue() <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->nullValue() <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->nullValue() <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->nullValue() <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->nullValue() <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->nullValue() <=> engine->evaluate(\"{}\")",
+    "engine->nullValue() <=> engine->evaluate(\"undefined\")",
+    "engine->nullValue() <=> engine->evaluate(\"null\")",
+    "engine->nullValue() <=> engine->nullValue()",
+    "engine->nullValue() <=> engine->undefinedValue()",
+    "engine->undefinedValue() <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->undefinedValue() <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->undefinedValue() <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->undefinedValue() <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->undefinedValue() <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->undefinedValue() <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->undefinedValue() <=> engine->evaluate(\"{}\")",
+    "engine->undefinedValue() <=> engine->evaluate(\"undefined\")",
+    "engine->undefinedValue() <=> engine->evaluate(\"null\")",
+    "engine->undefinedValue() <=> engine->nullValue()",
+    "engine->undefinedValue() <=> engine->undefinedValue()",
+    "engine->newArray() <=> QScriptValue(false)",
+    "engine->newArray() <=> QScriptValue(0)",
+    "engine->newArray() <=> QScriptValue(0.0)",
+    "engine->newArray() <=> QScriptValue(QString(\"\"))",
+    "engine->newArray() <=> QScriptValue(QString())",
+    "engine->newArray() <=> QScriptValue(0, false)",
+    "engine->newArray() <=> QScriptValue(0, 0)",
+    "engine->newArray() <=> QScriptValue(0, 0.0)",
+    "engine->newArray() <=> QScriptValue(0, QString(\"\"))",
+    "engine->newArray() <=> QScriptValue(0, QString())",
+    "engine->newArray() <=> QScriptValue(engine, false)",
+    "engine->newArray() <=> QScriptValue(engine, 0)",
+    "engine->newArray() <=> QScriptValue(engine, 0.0)",
+    "engine->newArray() <=> QScriptValue(engine, QString(\"\"))",
+    "engine->newArray() <=> QScriptValue(engine, QString())",
+    "engine->newArray() <=> engine->evaluate(\"false\")",
+    "engine->newArray() <=> engine->evaluate(\"0\")",
+    "engine->newArray() <=> engine->evaluate(\"0.0\")",
+    "engine->newArray() <=> engine->evaluate(\"''\")"};
+
+void tst_QScriptValue::equals_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<QScriptValue>("other");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> equals;
+    equals.reserve(1111);
+    for (unsigned i = 0; i < 1111; ++i)
+        equals.insert(equals_array[i]);
+    for (unsigned i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> value1 = initScriptValues(i);
+        for (unsigned j = 0; j < 135; ++j) {
+            QPair<QString, QScriptValue> value2 = initScriptValues(j);
+            QString tag = QString::fromLatin1("%20 <=> %21").arg(value1.first, value2.first);
+            QTest::newRow(tag.toAscii().constData()) << value1.second << value2.second << equals.contains(tag);        }
+    }
+}
+
+void tst_QScriptValue::equals()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QScriptValue, other);
+    QFETCH(bool, expected);
+    QEXPECT_FAIL("QScriptValue(qInf()) <=> QScriptValue(\"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(qInf()) <=> QScriptValue(0, \"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(-qInf()) <=> QScriptValue(\"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(-qInf()) <=> QScriptValue(0, \"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(\"-Infinity\") <=> QScriptValue(qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(\"-Infinity\") <=> QScriptValue(-qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(\"-Infinity\") <=> QScriptValue(0, qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(\"-Infinity\") <=> QScriptValue(0, -qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, qInf()) <=> QScriptValue(\"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, qInf()) <=> QScriptValue(0, \"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, -qInf()) <=> QScriptValue(\"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, -qInf()) <=> QScriptValue(0, \"-Infinity\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, \"-Infinity\") <=> QScriptValue(qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, \"-Infinity\") <=> QScriptValue(-qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, \"-Infinity\") <=> QScriptValue(0, qInf())", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, \"-Infinity\") <=> QScriptValue(0, -qInf())", "FIXME: WebKit bug 43038", Continue);
+    QCOMPARE(value.equals(other), expected);
+}
+
+static const QString strictlyEquals_array[] = {
+    "QScriptValue() <=> QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(QScriptValue::UndefinedValue) <=> engine->undefinedValue()",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(QScriptValue::NullValue) <=> engine->nullValue()",
+    "QScriptValue(true) <=> QScriptValue(true)",
+    "QScriptValue(true) <=> QScriptValue(0, true)",
+    "QScriptValue(true) <=> QScriptValue(engine, true)",
+    "QScriptValue(true) <=> engine->evaluate(\"true\")",
+    "QScriptValue(false) <=> QScriptValue(false)",
+    "QScriptValue(false) <=> QScriptValue(0, false)",
+    "QScriptValue(false) <=> QScriptValue(engine, false)",
+    "QScriptValue(false) <=> engine->evaluate(\"false\")",
+    "QScriptValue(int(122)) <=> QScriptValue(int(122))",
+    "QScriptValue(int(122)) <=> QScriptValue(0, int(122))",
+    "QScriptValue(int(122)) <=> QScriptValue(engine, int(122))",
+    "QScriptValue(int(122)) <=> engine->evaluate(\"122\")",
+    "QScriptValue(uint(124)) <=> QScriptValue(uint(124))",
+    "QScriptValue(uint(124)) <=> QScriptValue(0, uint(124))",
+    "QScriptValue(uint(124)) <=> QScriptValue(engine, uint(124))",
+    "QScriptValue(uint(124)) <=> engine->evaluate(\"124\")",
+    "QScriptValue(0) <=> QScriptValue(0)",
+    "QScriptValue(0) <=> QScriptValue(0.0)",
+    "QScriptValue(0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0.0) <=> QScriptValue(0)",
+    "QScriptValue(0.0) <=> QScriptValue(0.0)",
+    "QScriptValue(0.0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0.0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0.0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0.0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0.0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0.0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(123.0) <=> QScriptValue(123.0)",
+    "QScriptValue(123.0) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(123.0) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(123.0) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(6.37e-8) <=> QScriptValue(6.37e-8)",
+    "QScriptValue(6.37e-8) <=> QScriptValue(0, 6.37e-8)",
+    "QScriptValue(6.37e-8) <=> QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(6.37e-8) <=> engine->evaluate(\"6.37e-8\")",
+    "QScriptValue(-6.37e-8) <=> QScriptValue(-6.37e-8)",
+    "QScriptValue(-6.37e-8) <=> QScriptValue(0, -6.37e-8)",
+    "QScriptValue(-6.37e-8) <=> QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(-6.37e-8) <=> engine->evaluate(\"-6.37e-8\")",
+    "QScriptValue(0x43211234) <=> QScriptValue(0x43211234)",
+    "QScriptValue(0x43211234) <=> QScriptValue(0, 0x43211234)",
+    "QScriptValue(0x43211234) <=> QScriptValue(engine, 0x43211234)",
+    "QScriptValue(0x43211234) <=> engine->evaluate(\"0x43211234\")",
+    "QScriptValue(0x10000) <=> QScriptValue(0x10000)",
+    "QScriptValue(0x10000) <=> QScriptValue(0, 0x10000)",
+    "QScriptValue(0x10000) <=> QScriptValue(engine, 0x10000)",
+    "QScriptValue(0x10000) <=> engine->evaluate(\"0x10000\")",
+    "QScriptValue(0x10001) <=> QScriptValue(0x10001)",
+    "QScriptValue(0x10001) <=> QScriptValue(0, 0x10001)",
+    "QScriptValue(0x10001) <=> QScriptValue(engine, 0x10001)",
+    "QScriptValue(0x10001) <=> engine->evaluate(\"0x10001\")",
+    "QScriptValue(qInf()) <=> QScriptValue(qInf())",
+    "QScriptValue(qInf()) <=> QScriptValue(0, qInf())",
+    "QScriptValue(qInf()) <=> QScriptValue(engine, qInf())",
+    "QScriptValue(qInf()) <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(-qInf()) <=> QScriptValue(-qInf())",
+    "QScriptValue(-qInf()) <=> QScriptValue(0, -qInf())",
+    "QScriptValue(-qInf()) <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(-qInf()) <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(\"NaN\") <=> QScriptValue(\"NaN\")",
+    "QScriptValue(\"NaN\") <=> QScriptValue(0, \"NaN\")",
+    "QScriptValue(\"NaN\") <=> QScriptValue(engine, \"NaN\")",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(\"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(\"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(\"ciao\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(\"ciao\") <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(\"ciao\") <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(\"ciao\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(\"ciao\") <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString::fromLatin1(\"ciao\")) <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(QString())",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(0, QString())",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(QString(\"\")) <=> QScriptValue(engine, QString())",
+    "QScriptValue(QString(\"\")) <=> engine->evaluate(\"''\")",
+    "QScriptValue(QString()) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(QString()) <=> QScriptValue(QString())",
+    "QScriptValue(QString()) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(QString()) <=> QScriptValue(0, QString())",
+    "QScriptValue(QString()) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(QString()) <=> QScriptValue(engine, QString())",
+    "QScriptValue(QString()) <=> engine->evaluate(\"''\")",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(QString(\"0\")) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(QString(\"0\")) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(QString(\"123\")) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(QString(\"123\")) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(QString(\"12.4\")) <=> QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(QString(\"12.4\")) <=> engine->evaluate(\"'12.4'\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->undefinedValue()",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(0, QScriptValue::NullValue) <=> engine->nullValue()",
+    "QScriptValue(0, true) <=> QScriptValue(true)",
+    "QScriptValue(0, true) <=> QScriptValue(0, true)",
+    "QScriptValue(0, true) <=> QScriptValue(engine, true)",
+    "QScriptValue(0, true) <=> engine->evaluate(\"true\")",
+    "QScriptValue(0, false) <=> QScriptValue(false)",
+    "QScriptValue(0, false) <=> QScriptValue(0, false)",
+    "QScriptValue(0, false) <=> QScriptValue(engine, false)",
+    "QScriptValue(0, false) <=> engine->evaluate(\"false\")",
+    "QScriptValue(0, int(122)) <=> QScriptValue(int(122))",
+    "QScriptValue(0, int(122)) <=> QScriptValue(0, int(122))",
+    "QScriptValue(0, int(122)) <=> QScriptValue(engine, int(122))",
+    "QScriptValue(0, int(122)) <=> engine->evaluate(\"122\")",
+    "QScriptValue(0, uint(124)) <=> QScriptValue(uint(124))",
+    "QScriptValue(0, uint(124)) <=> QScriptValue(0, uint(124))",
+    "QScriptValue(0, uint(124)) <=> QScriptValue(engine, uint(124))",
+    "QScriptValue(0, uint(124)) <=> engine->evaluate(\"124\")",
+    "QScriptValue(0, 0) <=> QScriptValue(0)",
+    "QScriptValue(0, 0) <=> QScriptValue(0.0)",
+    "QScriptValue(0, 0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, 0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, 0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, 0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0.0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(0, 0.0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(0, 0.0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(0, 123.0) <=> QScriptValue(123.0)",
+    "QScriptValue(0, 123.0) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(0, 123.0) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(0, 123.0) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(0, 6.37e-8) <=> QScriptValue(6.37e-8)",
+    "QScriptValue(0, 6.37e-8) <=> QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, 6.37e-8) <=> QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(0, 6.37e-8) <=> engine->evaluate(\"6.37e-8\")",
+    "QScriptValue(0, -6.37e-8) <=> QScriptValue(-6.37e-8)",
+    "QScriptValue(0, -6.37e-8) <=> QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, -6.37e-8) <=> QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(0, -6.37e-8) <=> engine->evaluate(\"-6.37e-8\")",
+    "QScriptValue(0, 0x43211234) <=> QScriptValue(0x43211234)",
+    "QScriptValue(0, 0x43211234) <=> QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x43211234) <=> QScriptValue(engine, 0x43211234)",
+    "QScriptValue(0, 0x43211234) <=> engine->evaluate(\"0x43211234\")",
+    "QScriptValue(0, 0x10000) <=> QScriptValue(0x10000)",
+    "QScriptValue(0, 0x10000) <=> QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10000) <=> QScriptValue(engine, 0x10000)",
+    "QScriptValue(0, 0x10000) <=> engine->evaluate(\"0x10000\")",
+    "QScriptValue(0, 0x10001) <=> QScriptValue(0x10001)",
+    "QScriptValue(0, 0x10001) <=> QScriptValue(0, 0x10001)",
+    "QScriptValue(0, 0x10001) <=> QScriptValue(engine, 0x10001)",
+    "QScriptValue(0, 0x10001) <=> engine->evaluate(\"0x10001\")",
+    "QScriptValue(0, qInf()) <=> QScriptValue(qInf())",
+    "QScriptValue(0, qInf()) <=> QScriptValue(0, qInf())",
+    "QScriptValue(0, qInf()) <=> QScriptValue(engine, qInf())",
+    "QScriptValue(0, qInf()) <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(-qInf())",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(0, -qInf())",
+    "QScriptValue(0, -qInf()) <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(0, -qInf()) <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(0, \"NaN\") <=> QScriptValue(\"NaN\")",
+    "QScriptValue(0, \"NaN\") <=> QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"NaN\") <=> QScriptValue(engine, \"NaN\")",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(\"ciao\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(0, \"ciao\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, \"ciao\") <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(\"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\")) <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(QString())",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, QString(\"\")) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, QString(\"\")) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, QString()) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(0, QString()) <=> QScriptValue(QString())",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString()) <=> QScriptValue(0, QString())",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(0, QString()) <=> QScriptValue(engine, QString())",
+    "QScriptValue(0, QString()) <=> engine->evaluate(\"''\")",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"0\")) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(0, QString(\"0\")) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"123\")) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(0, QString(\"123\")) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(0, QString(\"12.3\")) <=> QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")",
+    "QScriptValue(engine, QScriptValue::UndefinedValue) <=> engine->undefinedValue()",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->evaluate(\"null\")",
+    "QScriptValue(engine, QScriptValue::NullValue) <=> engine->nullValue()",
+    "QScriptValue(engine, true) <=> QScriptValue(true)",
+    "QScriptValue(engine, true) <=> QScriptValue(0, true)",
+    "QScriptValue(engine, true) <=> QScriptValue(engine, true)",
+    "QScriptValue(engine, true) <=> engine->evaluate(\"true\")",
+    "QScriptValue(engine, false) <=> QScriptValue(false)",
+    "QScriptValue(engine, false) <=> QScriptValue(0, false)",
+    "QScriptValue(engine, false) <=> QScriptValue(engine, false)",
+    "QScriptValue(engine, false) <=> engine->evaluate(\"false\")",
+    "QScriptValue(engine, int(122)) <=> QScriptValue(int(122))",
+    "QScriptValue(engine, int(122)) <=> QScriptValue(0, int(122))",
+    "QScriptValue(engine, int(122)) <=> QScriptValue(engine, int(122))",
+    "QScriptValue(engine, int(122)) <=> engine->evaluate(\"122\")",
+    "QScriptValue(engine, uint(124)) <=> QScriptValue(uint(124))",
+    "QScriptValue(engine, uint(124)) <=> QScriptValue(0, uint(124))",
+    "QScriptValue(engine, uint(124)) <=> QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, uint(124)) <=> engine->evaluate(\"124\")",
+    "QScriptValue(engine, 0) <=> QScriptValue(0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, 0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0.0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, 0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(0, 0.0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0) <=> QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"0\")",
+    "QScriptValue(engine, 0.0) <=> engine->evaluate(\"0.0\")",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(123.0)",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(0, 123.0)",
+    "QScriptValue(engine, 123.0) <=> QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 123.0) <=> engine->evaluate(\"123.0\")",
+    "QScriptValue(engine, 6.37e-8) <=> QScriptValue(6.37e-8)",
+    "QScriptValue(engine, 6.37e-8) <=> QScriptValue(0, 6.37e-8)",
+    "QScriptValue(engine, 6.37e-8) <=> QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, 6.37e-8) <=> engine->evaluate(\"6.37e-8\")",
+    "QScriptValue(engine, -6.37e-8) <=> QScriptValue(-6.37e-8)",
+    "QScriptValue(engine, -6.37e-8) <=> QScriptValue(0, -6.37e-8)",
+    "QScriptValue(engine, -6.37e-8) <=> QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, -6.37e-8) <=> engine->evaluate(\"-6.37e-8\")",
+    "QScriptValue(engine, 0x43211234) <=> QScriptValue(0x43211234)",
+    "QScriptValue(engine, 0x43211234) <=> QScriptValue(0, 0x43211234)",
+    "QScriptValue(engine, 0x43211234) <=> QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x43211234) <=> engine->evaluate(\"0x43211234\")",
+    "QScriptValue(engine, 0x10000) <=> QScriptValue(0x10000)",
+    "QScriptValue(engine, 0x10000) <=> QScriptValue(0, 0x10000)",
+    "QScriptValue(engine, 0x10000) <=> QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10000) <=> engine->evaluate(\"0x10000\")",
+    "QScriptValue(engine, 0x10001) <=> QScriptValue(0x10001)",
+    "QScriptValue(engine, 0x10001) <=> QScriptValue(0, 0x10001)",
+    "QScriptValue(engine, 0x10001) <=> QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, 0x10001) <=> engine->evaluate(\"0x10001\")",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(qInf())",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(0, qInf())",
+    "QScriptValue(engine, qInf()) <=> QScriptValue(engine, qInf())",
+    "QScriptValue(engine, qInf()) <=> engine->evaluate(\"Infinity\")",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(-qInf())",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(0, -qInf())",
+    "QScriptValue(engine, -qInf()) <=> QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, -qInf()) <=> engine->evaluate(\"-Infinity\")",
+    "QScriptValue(engine, \"NaN\") <=> QScriptValue(\"NaN\")",
+    "QScriptValue(engine, \"NaN\") <=> QScriptValue(0, \"NaN\")",
+    "QScriptValue(engine, \"NaN\") <=> QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(\"Infinity\")",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(0, \"Infinity\")",
+    "QScriptValue(engine, \"Infinity\") <=> QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(\"-Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(engine, \"-Infinity\") <=> QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(\"ciao\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, \"ciao\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, \"ciao\") <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(\"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\")) <=> engine->evaluate(\"'ciao'\")",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(QString())",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString(\"\")) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"\")) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, QString()) <=> QScriptValue(QString(\"\"))",
+    "QScriptValue(engine, QString()) <=> QScriptValue(QString())",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, QString(\"\"))",
+    "QScriptValue(engine, QString()) <=> QScriptValue(0, QString())",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString()) <=> QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString()) <=> engine->evaluate(\"''\")",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(QString(\"0\"))",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"0\")) <=> QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"0\")) <=> engine->evaluate(\"'0'\")",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(QString(\"123\"))",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"123\")) <=> QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"123\")) <=> engine->evaluate(\"'123'\")",
+    "QScriptValue(engine, QString(\"1.23\")) <=> QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"{}\") <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\") <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\") <=> engine->evaluate(\"{}\")",
+    "engine->evaluate(\"{}\") <=> engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"{}\") <=> engine->undefinedValue()",
+    "engine->evaluate(\"Object.prototype\") <=> engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\") <=> engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\") <=> engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\") <=> engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\") <=> engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\") <=> engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\") <=> engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"undefined\") <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"undefined\") <=> engine->evaluate(\"{}\")",
+    "engine->evaluate(\"undefined\") <=> engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"undefined\") <=> engine->undefinedValue()",
+    "engine->evaluate(\"null\") <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->evaluate(\"null\") <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->evaluate(\"null\") <=> engine->evaluate(\"null\")",
+    "engine->evaluate(\"null\") <=> engine->nullValue()",
+    "engine->evaluate(\"true\") <=> QScriptValue(true)",
+    "engine->evaluate(\"true\") <=> QScriptValue(0, true)",
+    "engine->evaluate(\"true\") <=> QScriptValue(engine, true)",
+    "engine->evaluate(\"true\") <=> engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\") <=> QScriptValue(false)",
+    "engine->evaluate(\"false\") <=> QScriptValue(0, false)",
+    "engine->evaluate(\"false\") <=> QScriptValue(engine, false)",
+    "engine->evaluate(\"false\") <=> engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\") <=> QScriptValue(int(122))",
+    "engine->evaluate(\"122\") <=> QScriptValue(0, int(122))",
+    "engine->evaluate(\"122\") <=> QScriptValue(engine, int(122))",
+    "engine->evaluate(\"122\") <=> engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\") <=> QScriptValue(uint(124))",
+    "engine->evaluate(\"124\") <=> QScriptValue(0, uint(124))",
+    "engine->evaluate(\"124\") <=> QScriptValue(engine, uint(124))",
+    "engine->evaluate(\"124\") <=> engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\") <=> QScriptValue(0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"0\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"0\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0.0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, 0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(0, 0.0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, 0)",
+    "engine->evaluate(\"0.0\") <=> QScriptValue(engine, 0.0)",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\") <=> engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(123.0)",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(0, 123.0)",
+    "engine->evaluate(\"123.0\") <=> QScriptValue(engine, 123.0)",
+    "engine->evaluate(\"123.0\") <=> engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\") <=> QScriptValue(6.37e-8)",
+    "engine->evaluate(\"6.37e-8\") <=> QScriptValue(0, 6.37e-8)",
+    "engine->evaluate(\"6.37e-8\") <=> QScriptValue(engine, 6.37e-8)",
+    "engine->evaluate(\"6.37e-8\") <=> engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\") <=> QScriptValue(-6.37e-8)",
+    "engine->evaluate(\"-6.37e-8\") <=> QScriptValue(0, -6.37e-8)",
+    "engine->evaluate(\"-6.37e-8\") <=> QScriptValue(engine, -6.37e-8)",
+    "engine->evaluate(\"-6.37e-8\") <=> engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\") <=> QScriptValue(0x43211234)",
+    "engine->evaluate(\"0x43211234\") <=> QScriptValue(0, 0x43211234)",
+    "engine->evaluate(\"0x43211234\") <=> QScriptValue(engine, 0x43211234)",
+    "engine->evaluate(\"0x43211234\") <=> engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\") <=> QScriptValue(0x10000)",
+    "engine->evaluate(\"0x10000\") <=> QScriptValue(0, 0x10000)",
+    "engine->evaluate(\"0x10000\") <=> QScriptValue(engine, 0x10000)",
+    "engine->evaluate(\"0x10000\") <=> engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\") <=> QScriptValue(0x10001)",
+    "engine->evaluate(\"0x10001\") <=> QScriptValue(0, 0x10001)",
+    "engine->evaluate(\"0x10001\") <=> QScriptValue(engine, 0x10001)",
+    "engine->evaluate(\"0x10001\") <=> engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(qInf())",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(0, qInf())",
+    "engine->evaluate(\"Infinity\") <=> QScriptValue(engine, qInf())",
+    "engine->evaluate(\"Infinity\") <=> engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(-qInf())",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(0, -qInf())",
+    "engine->evaluate(\"-Infinity\") <=> QScriptValue(engine, -qInf())",
+    "engine->evaluate(\"-Infinity\") <=> engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(\"ciao\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(0, \"ciao\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(engine, \"ciao\")",
+    "engine->evaluate(\"'ciao'\") <=> QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "engine->evaluate(\"'ciao'\") <=> engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\") <=> QScriptValue(QString(\"\"))",
+    "engine->evaluate(\"''\") <=> QScriptValue(QString())",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, QString(\"\"))",
+    "engine->evaluate(\"''\") <=> QScriptValue(0, QString())",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, QString(\"\"))",
+    "engine->evaluate(\"''\") <=> QScriptValue(engine, QString())",
+    "engine->evaluate(\"''\") <=> engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(QString(\"0\"))",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(0, QString(\"0\"))",
+    "engine->evaluate(\"'0'\") <=> QScriptValue(engine, QString(\"0\"))",
+    "engine->evaluate(\"'0'\") <=> engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(QString(\"123\"))",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(0, QString(\"123\"))",
+    "engine->evaluate(\"'123'\") <=> QScriptValue(engine, QString(\"123\"))",
+    "engine->evaluate(\"'123'\") <=> engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\") <=> QScriptValue(QString(\"12.4\"))",
+    "engine->evaluate(\"'12.4'\") <=> engine->evaluate(\"'12.4'\")",
+    "engine->nullValue() <=> QScriptValue(QScriptValue::NullValue)",
+    "engine->nullValue() <=> QScriptValue(0, QScriptValue::NullValue)",
+    "engine->nullValue() <=> QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->nullValue() <=> engine->evaluate(\"null\")",
+    "engine->nullValue() <=> engine->nullValue()",
+    "engine->undefinedValue() <=> QScriptValue(QScriptValue::UndefinedValue)",
+    "engine->undefinedValue() <=> QScriptValue(0, QScriptValue::UndefinedValue)",
+    "engine->undefinedValue() <=> QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->undefinedValue() <=> engine->evaluate(\"{}\")",
+    "engine->undefinedValue() <=> engine->evaluate(\"undefined\")",
+    "engine->undefinedValue() <=> engine->undefinedValue()"};
+
+void tst_QScriptValue::strictlyEquals_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<QScriptValue>("other");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> equals;
+    equals.reserve(491);
+    for (unsigned i = 0; i < 491; ++i)
+        equals.insert(strictlyEquals_array[i]);
+    for (unsigned i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> value1 = initScriptValues(i);
+        for (unsigned j = 0; j < 135; ++j) {
+            QPair<QString, QScriptValue> value2 = initScriptValues(j);
+            QString tag = QString::fromLatin1("%20 <=> %21").arg(value1.first, value2.first);
+            QTest::newRow(tag.toAscii().constData()) << value1.second << value2.second << equals.contains(tag);        }
+    }
+}
+
+void tst_QScriptValue::strictlyEquals()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QScriptValue, other);
+    QFETCH(bool, expected);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue) <=> engine->undefinedValue()", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue) <=> engine->evaluate(\"null\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue) <=> engine->nullValue()", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(true) <=> QScriptValue(true)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(true) <=> QScriptValue(0, true)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(false) <=> QScriptValue(false)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(false) <=> QScriptValue(0, false)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(0, QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::UndefinedValue) <=> QScriptValue(engine, QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"{}\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->evaluate(\"undefined\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::UndefinedValue) <=> engine->undefinedValue()", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(0, QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::NullValue) <=> QScriptValue(engine, QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::NullValue) <=> engine->evaluate(\"null\")", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, QScriptValue::NullValue) <=> engine->nullValue()", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, true) <=> QScriptValue(true)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, true) <=> QScriptValue(0, true)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, false) <=> QScriptValue(false)", "FIXME: WebKit bug 43038", Continue);
+    QEXPECT_FAIL("QScriptValue(0, false) <=> QScriptValue(0, false)", "FIXME: WebKit bug 43038", Continue);
+    QCOMPARE(value.strictlyEquals(other), expected);
+}
+
+static const QString instanceOf_array[] = {
+    "engine->evaluate(\"[]\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"[]\") <=> engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Date.prototype\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array.prototype\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Function.prototype\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Error.prototype\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Object\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Object\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"Array\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"Number\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Number\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"Function\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Function\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"(function() { return 1; })\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\") <=> engine->evaluate(\"Function\")",
+    "engine->evaluate(\"/foo/\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"new Object()\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"new Array()\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"new Array()\") <=> engine->evaluate(\"Array\")",
+    "engine->evaluate(\"new Error()\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Undefined\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Null\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"True\") <=> engine->evaluate(\"Object\")",
+    "engine->evaluate(\"False\") <=> engine->evaluate(\"Object\")",
+    "engine->newObject() <=> engine->evaluate(\"Object\")",
+    "engine->newArray() <=> engine->evaluate(\"Object\")",
+    "engine->newArray() <=> engine->evaluate(\"Array\")",
+    "engine->newArray(10) <=> engine->evaluate(\"Object\")",
+    "engine->newArray(10) <=> engine->evaluate(\"Array\")"};
+
+void tst_QScriptValue::instanceOf_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<QScriptValue>("other");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> equals;
+    equals.reserve(34);
+    for (unsigned i = 0; i < 34; ++i)
+        equals.insert(instanceOf_array[i]);
+    for (unsigned i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> value1 = initScriptValues(i);
+        for (unsigned j = 0; j < 135; ++j) {
+            QPair<QString, QScriptValue> value2 = initScriptValues(j);
+            QString tag = QString::fromLatin1("%20 <=> %21").arg(value1.first, value2.first);
+            QTest::newRow(tag.toAscii().constData()) << value1.second << value2.second << equals.contains(tag);        }
+    }
+}
+
+void tst_QScriptValue::instanceOf()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QScriptValue, other);
+    QFETCH(bool, expected);
+    QCOMPARE(value.instanceOf(other), expected);
+}
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue_generated_init.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue_generated_init.cpp
new file mode 100644 (file)
index 0000000..4c97dd4
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+/****************************************************************************
+*************** This file has been generated. DO NOT MODIFY! ****************
+****************************************************************************/
+
+#include "tst_qscriptvalue.h"
+
+
+QPair<QString, QScriptValue> tst_QScriptValue::initScriptValues(uint idx)
+{
+    QScriptEngine* engine = m_engine;
+    switch (idx) {
+    case 0: return QPair<QString, QScriptValue>("QScriptValue()", QScriptValue());
+    case 1: return QPair<QString, QScriptValue>("QScriptValue(QScriptValue::UndefinedValue)", QScriptValue(QScriptValue::UndefinedValue));
+    case 2: return QPair<QString, QScriptValue>("QScriptValue(QScriptValue::NullValue)", QScriptValue(QScriptValue::NullValue));
+    case 3: return QPair<QString, QScriptValue>("QScriptValue(true)", QScriptValue(true));
+    case 4: return QPair<QString, QScriptValue>("QScriptValue(false)", QScriptValue(false));
+    case 5: return QPair<QString, QScriptValue>("QScriptValue(int(122))", QScriptValue(int(122)));
+    case 6: return QPair<QString, QScriptValue>("QScriptValue(uint(124))", QScriptValue(uint(124)));
+    case 7: return QPair<QString, QScriptValue>("QScriptValue(0)", QScriptValue(0));
+    case 8: return QPair<QString, QScriptValue>("QScriptValue(0.0)", QScriptValue(0.0));
+    case 9: return QPair<QString, QScriptValue>("QScriptValue(123.0)", QScriptValue(123.0));
+    case 10: return QPair<QString, QScriptValue>("QScriptValue(6.37e-8)", QScriptValue(6.37e-8));
+    case 11: return QPair<QString, QScriptValue>("QScriptValue(-6.37e-8)", QScriptValue(-6.37e-8));
+    case 12: return QPair<QString, QScriptValue>("QScriptValue(0x43211234)", QScriptValue(0x43211234));
+    case 13: return QPair<QString, QScriptValue>("QScriptValue(0x10000)", QScriptValue(0x10000));
+    case 14: return QPair<QString, QScriptValue>("QScriptValue(0x10001)", QScriptValue(0x10001));
+    case 15: return QPair<QString, QScriptValue>("QScriptValue(qSNaN())", QScriptValue(qSNaN()));
+    case 16: return QPair<QString, QScriptValue>("QScriptValue(qQNaN())", QScriptValue(qQNaN()));
+    case 17: return QPair<QString, QScriptValue>("QScriptValue(qInf())", QScriptValue(qInf()));
+    case 18: return QPair<QString, QScriptValue>("QScriptValue(-qInf())", QScriptValue(-qInf()));
+    case 19: return QPair<QString, QScriptValue>("QScriptValue(\"NaN\")", QScriptValue("NaN"));
+    case 20: return QPair<QString, QScriptValue>("QScriptValue(\"Infinity\")", QScriptValue("Infinity"));
+    case 21: return QPair<QString, QScriptValue>("QScriptValue(\"-Infinity\")", QScriptValue("-Infinity"));
+    case 22: return QPair<QString, QScriptValue>("QScriptValue(\"ciao\")", QScriptValue("ciao"));
+    case 23: return QPair<QString, QScriptValue>("QScriptValue(QString::fromLatin1(\"ciao\"))", QScriptValue(QString::fromLatin1("ciao")));
+    case 24: return QPair<QString, QScriptValue>("QScriptValue(QString(\"\"))", QScriptValue(QString("")));
+    case 25: return QPair<QString, QScriptValue>("QScriptValue(QString())", QScriptValue(QString()));
+    case 26: return QPair<QString, QScriptValue>("QScriptValue(QString(\"0\"))", QScriptValue(QString("0")));
+    case 27: return QPair<QString, QScriptValue>("QScriptValue(QString(\"123\"))", QScriptValue(QString("123")));
+    case 28: return QPair<QString, QScriptValue>("QScriptValue(QString(\"12.4\"))", QScriptValue(QString("12.4")));
+    case 29: return QPair<QString, QScriptValue>("QScriptValue(0, QScriptValue::UndefinedValue)", QScriptValue(0, QScriptValue::UndefinedValue));
+    case 30: return QPair<QString, QScriptValue>("QScriptValue(0, QScriptValue::NullValue)", QScriptValue(0, QScriptValue::NullValue));
+    case 31: return QPair<QString, QScriptValue>("QScriptValue(0, true)", QScriptValue(0, true));
+    case 32: return QPair<QString, QScriptValue>("QScriptValue(0, false)", QScriptValue(0, false));
+    case 33: return QPair<QString, QScriptValue>("QScriptValue(0, int(122))", QScriptValue(0, int(122)));
+    case 34: return QPair<QString, QScriptValue>("QScriptValue(0, uint(124))", QScriptValue(0, uint(124)));
+    case 35: return QPair<QString, QScriptValue>("QScriptValue(0, 0)", QScriptValue(0, 0));
+    case 36: return QPair<QString, QScriptValue>("QScriptValue(0, 0.0)", QScriptValue(0, 0.0));
+    case 37: return QPair<QString, QScriptValue>("QScriptValue(0, 123.0)", QScriptValue(0, 123.0));
+    case 38: return QPair<QString, QScriptValue>("QScriptValue(0, 6.37e-8)", QScriptValue(0, 6.37e-8));
+    case 39: return QPair<QString, QScriptValue>("QScriptValue(0, -6.37e-8)", QScriptValue(0, -6.37e-8));
+    case 40: return QPair<QString, QScriptValue>("QScriptValue(0, 0x43211234)", QScriptValue(0, 0x43211234));
+    case 41: return QPair<QString, QScriptValue>("QScriptValue(0, 0x10000)", QScriptValue(0, 0x10000));
+    case 42: return QPair<QString, QScriptValue>("QScriptValue(0, 0x10001)", QScriptValue(0, 0x10001));
+    case 43: return QPair<QString, QScriptValue>("QScriptValue(0, qSNaN())", QScriptValue(0, qSNaN()));
+    case 44: return QPair<QString, QScriptValue>("QScriptValue(0, qQNaN())", QScriptValue(0, qQNaN()));
+    case 45: return QPair<QString, QScriptValue>("QScriptValue(0, qInf())", QScriptValue(0, qInf()));
+    case 46: return QPair<QString, QScriptValue>("QScriptValue(0, -qInf())", QScriptValue(0, -qInf()));
+    case 47: return QPair<QString, QScriptValue>("QScriptValue(0, \"NaN\")", QScriptValue(0, "NaN"));
+    case 48: return QPair<QString, QScriptValue>("QScriptValue(0, \"Infinity\")", QScriptValue(0, "Infinity"));
+    case 49: return QPair<QString, QScriptValue>("QScriptValue(0, \"-Infinity\")", QScriptValue(0, "-Infinity"));
+    case 50: return QPair<QString, QScriptValue>("QScriptValue(0, \"ciao\")", QScriptValue(0, "ciao"));
+    case 51: return QPair<QString, QScriptValue>("QScriptValue(0, QString::fromLatin1(\"ciao\"))", QScriptValue(0, QString::fromLatin1("ciao")));
+    case 52: return QPair<QString, QScriptValue>("QScriptValue(0, QString(\"\"))", QScriptValue(0, QString("")));
+    case 53: return QPair<QString, QScriptValue>("QScriptValue(0, QString())", QScriptValue(0, QString()));
+    case 54: return QPair<QString, QScriptValue>("QScriptValue(0, QString(\"0\"))", QScriptValue(0, QString("0")));
+    case 55: return QPair<QString, QScriptValue>("QScriptValue(0, QString(\"123\"))", QScriptValue(0, QString("123")));
+    case 56: return QPair<QString, QScriptValue>("QScriptValue(0, QString(\"12.3\"))", QScriptValue(0, QString("12.3")));
+    case 57: return QPair<QString, QScriptValue>("QScriptValue(engine, QScriptValue::UndefinedValue)", QScriptValue(engine, QScriptValue::UndefinedValue));
+    case 58: return QPair<QString, QScriptValue>("QScriptValue(engine, QScriptValue::NullValue)", QScriptValue(engine, QScriptValue::NullValue));
+    case 59: return QPair<QString, QScriptValue>("QScriptValue(engine, true)", QScriptValue(engine, true));
+    case 60: return QPair<QString, QScriptValue>("QScriptValue(engine, false)", QScriptValue(engine, false));
+    case 61: return QPair<QString, QScriptValue>("QScriptValue(engine, int(122))", QScriptValue(engine, int(122)));
+    case 62: return QPair<QString, QScriptValue>("QScriptValue(engine, uint(124))", QScriptValue(engine, uint(124)));
+    case 63: return QPair<QString, QScriptValue>("QScriptValue(engine, 0)", QScriptValue(engine, 0));
+    case 64: return QPair<QString, QScriptValue>("QScriptValue(engine, 0.0)", QScriptValue(engine, 0.0));
+    case 65: return QPair<QString, QScriptValue>("QScriptValue(engine, 123.0)", QScriptValue(engine, 123.0));
+    case 66: return QPair<QString, QScriptValue>("QScriptValue(engine, 6.37e-8)", QScriptValue(engine, 6.37e-8));
+    case 67: return QPair<QString, QScriptValue>("QScriptValue(engine, -6.37e-8)", QScriptValue(engine, -6.37e-8));
+    case 68: return QPair<QString, QScriptValue>("QScriptValue(engine, 0x43211234)", QScriptValue(engine, 0x43211234));
+    case 69: return QPair<QString, QScriptValue>("QScriptValue(engine, 0x10000)", QScriptValue(engine, 0x10000));
+    case 70: return QPair<QString, QScriptValue>("QScriptValue(engine, 0x10001)", QScriptValue(engine, 0x10001));
+    case 71: return QPair<QString, QScriptValue>("QScriptValue(engine, qSNaN())", QScriptValue(engine, qSNaN()));
+    case 72: return QPair<QString, QScriptValue>("QScriptValue(engine, qQNaN())", QScriptValue(engine, qQNaN()));
+    case 73: return QPair<QString, QScriptValue>("QScriptValue(engine, qInf())", QScriptValue(engine, qInf()));
+    case 74: return QPair<QString, QScriptValue>("QScriptValue(engine, -qInf())", QScriptValue(engine, -qInf()));
+    case 75: return QPair<QString, QScriptValue>("QScriptValue(engine, \"NaN\")", QScriptValue(engine, "NaN"));
+    case 76: return QPair<QString, QScriptValue>("QScriptValue(engine, \"Infinity\")", QScriptValue(engine, "Infinity"));
+    case 77: return QPair<QString, QScriptValue>("QScriptValue(engine, \"-Infinity\")", QScriptValue(engine, "-Infinity"));
+    case 78: return QPair<QString, QScriptValue>("QScriptValue(engine, \"ciao\")", QScriptValue(engine, "ciao"));
+    case 79: return QPair<QString, QScriptValue>("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", QScriptValue(engine, QString::fromLatin1("ciao")));
+    case 80: return QPair<QString, QScriptValue>("QScriptValue(engine, QString(\"\"))", QScriptValue(engine, QString("")));
+    case 81: return QPair<QString, QScriptValue>("QScriptValue(engine, QString())", QScriptValue(engine, QString()));
+    case 82: return QPair<QString, QScriptValue>("QScriptValue(engine, QString(\"0\"))", QScriptValue(engine, QString("0")));
+    case 83: return QPair<QString, QScriptValue>("QScriptValue(engine, QString(\"123\"))", QScriptValue(engine, QString("123")));
+    case 84: return QPair<QString, QScriptValue>("QScriptValue(engine, QString(\"1.23\"))", QScriptValue(engine, QString("1.23")));
+    case 85: return QPair<QString, QScriptValue>("engine->evaluate(\"[]\")", engine->evaluate("[]"));
+    case 86: return QPair<QString, QScriptValue>("engine->evaluate(\"{}\")", engine->evaluate("{}"));
+    case 87: return QPair<QString, QScriptValue>("engine->evaluate(\"Object.prototype\")", engine->evaluate("Object.prototype"));
+    case 88: return QPair<QString, QScriptValue>("engine->evaluate(\"Date.prototype\")", engine->evaluate("Date.prototype"));
+    case 89: return QPair<QString, QScriptValue>("engine->evaluate(\"Array.prototype\")", engine->evaluate("Array.prototype"));
+    case 90: return QPair<QString, QScriptValue>("engine->evaluate(\"Function.prototype\")", engine->evaluate("Function.prototype"));
+    case 91: return QPair<QString, QScriptValue>("engine->evaluate(\"Error.prototype\")", engine->evaluate("Error.prototype"));
+    case 92: return QPair<QString, QScriptValue>("engine->evaluate(\"Object\")", engine->evaluate("Object"));
+    case 93: return QPair<QString, QScriptValue>("engine->evaluate(\"Array\")", engine->evaluate("Array"));
+    case 94: return QPair<QString, QScriptValue>("engine->evaluate(\"Number\")", engine->evaluate("Number"));
+    case 95: return QPair<QString, QScriptValue>("engine->evaluate(\"Function\")", engine->evaluate("Function"));
+    case 96: return QPair<QString, QScriptValue>("engine->evaluate(\"(function() { return 1; })\")", engine->evaluate("(function() { return 1; })"));
+    case 97: return QPair<QString, QScriptValue>("engine->evaluate(\"(function() { return 'ciao'; })\")", engine->evaluate("(function() { return 'ciao'; })"));
+    case 98: return QPair<QString, QScriptValue>("engine->evaluate(\"(function() { throw new Error('foo'); })\")", engine->evaluate("(function() { throw new Error('foo'); })"));
+    case 99: return QPair<QString, QScriptValue>("engine->evaluate(\"/foo/\")", engine->evaluate("/foo/"));
+    case 100: return QPair<QString, QScriptValue>("engine->evaluate(\"new Object()\")", engine->evaluate("new Object()"));
+    case 101: return QPair<QString, QScriptValue>("engine->evaluate(\"new Array()\")", engine->evaluate("new Array()"));
+    case 102: return QPair<QString, QScriptValue>("engine->evaluate(\"new Error()\")", engine->evaluate("new Error()"));
+    case 103: return QPair<QString, QScriptValue>("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", engine->evaluate("a = new Object(); a.foo = 22; a.foo"));
+    case 104: return QPair<QString, QScriptValue>("engine->evaluate(\"Undefined\")", engine->evaluate("Undefined"));
+    case 105: return QPair<QString, QScriptValue>("engine->evaluate(\"Null\")", engine->evaluate("Null"));
+    case 106: return QPair<QString, QScriptValue>("engine->evaluate(\"True\")", engine->evaluate("True"));
+    case 107: return QPair<QString, QScriptValue>("engine->evaluate(\"False\")", engine->evaluate("False"));
+    case 108: return QPair<QString, QScriptValue>("engine->evaluate(\"undefined\")", engine->evaluate("undefined"));
+    case 109: return QPair<QString, QScriptValue>("engine->evaluate(\"null\")", engine->evaluate("null"));
+    case 110: return QPair<QString, QScriptValue>("engine->evaluate(\"true\")", engine->evaluate("true"));
+    case 111: return QPair<QString, QScriptValue>("engine->evaluate(\"false\")", engine->evaluate("false"));
+    case 112: return QPair<QString, QScriptValue>("engine->evaluate(\"122\")", engine->evaluate("122"));
+    case 113: return QPair<QString, QScriptValue>("engine->evaluate(\"124\")", engine->evaluate("124"));
+    case 114: return QPair<QString, QScriptValue>("engine->evaluate(\"0\")", engine->evaluate("0"));
+    case 115: return QPair<QString, QScriptValue>("engine->evaluate(\"0.0\")", engine->evaluate("0.0"));
+    case 116: return QPair<QString, QScriptValue>("engine->evaluate(\"123.0\")", engine->evaluate("123.0"));
+    case 117: return QPair<QString, QScriptValue>("engine->evaluate(\"6.37e-8\")", engine->evaluate("6.37e-8"));
+    case 118: return QPair<QString, QScriptValue>("engine->evaluate(\"-6.37e-8\")", engine->evaluate("-6.37e-8"));
+    case 119: return QPair<QString, QScriptValue>("engine->evaluate(\"0x43211234\")", engine->evaluate("0x43211234"));
+    case 120: return QPair<QString, QScriptValue>("engine->evaluate(\"0x10000\")", engine->evaluate("0x10000"));
+    case 121: return QPair<QString, QScriptValue>("engine->evaluate(\"0x10001\")", engine->evaluate("0x10001"));
+    case 122: return QPair<QString, QScriptValue>("engine->evaluate(\"NaN\")", engine->evaluate("NaN"));
+    case 123: return QPair<QString, QScriptValue>("engine->evaluate(\"Infinity\")", engine->evaluate("Infinity"));
+    case 124: return QPair<QString, QScriptValue>("engine->evaluate(\"-Infinity\")", engine->evaluate("-Infinity"));
+    case 125: return QPair<QString, QScriptValue>("engine->evaluate(\"'ciao'\")", engine->evaluate("'ciao'"));
+    case 126: return QPair<QString, QScriptValue>("engine->evaluate(\"''\")", engine->evaluate("''"));
+    case 127: return QPair<QString, QScriptValue>("engine->evaluate(\"'0'\")", engine->evaluate("'0'"));
+    case 128: return QPair<QString, QScriptValue>("engine->evaluate(\"'123'\")", engine->evaluate("'123'"));
+    case 129: return QPair<QString, QScriptValue>("engine->evaluate(\"'12.4'\")", engine->evaluate("'12.4'"));
+    case 130: return QPair<QString, QScriptValue>("engine->nullValue()", engine->nullValue());
+    case 131: return QPair<QString, QScriptValue>("engine->undefinedValue()", engine->undefinedValue());
+    case 132: return QPair<QString, QScriptValue>("engine->newObject()", engine->newObject());
+    case 133: return QPair<QString, QScriptValue>("engine->newArray()", engine->newArray());
+    case 134: return QPair<QString, QScriptValue>("engine->newArray(10)", engine->newArray(10));
+    }
+    Q_ASSERT(false);
+    return qMakePair(QString(), QScriptValue());
+}
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue_generated_istype.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue_generated_istype.cpp
new file mode 100644 (file)
index 0000000..433597f
--- /dev/null
@@ -0,0 +1,622 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+
+/****************************************************************************
+*************** This file has been generated. DO NOT MODIFY! ****************
+****************************************************************************/
+
+#include "tst_qscriptvalue.h"
+
+
+static const QString isValid_array[] = {
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+void tst_QScriptValue::isValid_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(134);
+    for (uint i = 0; i < 134; ++i)
+        expectedValue.insert(isValid_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isValid()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isValid(), expected);
+    QCOMPARE(value.isValid(), expected);
+}
+
+static const QString isBool_array[] = {
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")"};
+
+void tst_QScriptValue::isBool_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(8);
+    for (uint i = 0; i < 8; ++i)
+        expectedValue.insert(isBool_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isBool()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isBool(), expected);
+    QCOMPARE(value.isBool(), expected);
+}
+
+static const QString isBoolean_array[] = {
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")"};
+
+void tst_QScriptValue::isBoolean_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(8);
+    for (uint i = 0; i < 8; ++i)
+        expectedValue.insert(isBoolean_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isBoolean()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isBoolean(), expected);
+    QCOMPARE(value.isBoolean(), expected);
+}
+
+static const QString isNumber_array[] = {
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")"};
+
+void tst_QScriptValue::isNumber_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(56);
+    for (uint i = 0; i < 56; ++i)
+        expectedValue.insert(isNumber_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isNumber()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isNumber(), expected);
+    QCOMPARE(value.isNumber(), expected);
+}
+
+static const QString isFunction_array[] = {
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")"};
+
+void tst_QScriptValue::isFunction_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(9);
+    for (uint i = 0; i < 9; ++i)
+        expectedValue.insert(isFunction_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isFunction()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isFunction(), expected);
+    QCOMPARE(value.isFunction(), expected);
+}
+
+static const QString isNull_array[] = {
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "engine->evaluate(\"null\")",
+    "engine->nullValue()"};
+
+void tst_QScriptValue::isNull_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(5);
+    for (uint i = 0; i < 5; ++i)
+        expectedValue.insert(isNull_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isNull()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isNull(), expected);
+    QCOMPARE(value.isNull(), expected);
+}
+
+static const QString isString_array[] = {
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")"};
+
+void tst_QScriptValue::isString_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(35);
+    for (uint i = 0; i < 35; ++i)
+        expectedValue.insert(isString_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isString()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isString(), expected);
+    QCOMPARE(value.isString(), expected);
+}
+
+static const QString isUndefined_array[] = {
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->undefinedValue()"};
+
+void tst_QScriptValue::isUndefined_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(6);
+    for (uint i = 0; i < 6; ++i)
+        expectedValue.insert(isUndefined_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isUndefined()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isUndefined(), expected);
+    QCOMPARE(value.isUndefined(), expected);
+}
+
+
+
+
+static const QString isObject_array[] = {
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+void tst_QScriptValue::isObject_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(24);
+    for (uint i = 0; i < 24; ++i)
+        expectedValue.insert(isObject_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isObject()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isObject(), expected);
+    QCOMPARE(value.isObject(), expected);
+}
+
+static const QString isArray_array[] = {
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+void tst_QScriptValue::isArray_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(5);
+    for (uint i = 0; i < 5; ++i)
+        expectedValue.insert(isArray_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isArray()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isArray(), expected);
+    QCOMPARE(value.isArray(), expected);
+}
+
+static const QString isError_array[] = {
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")"};
+
+void tst_QScriptValue::isError_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QSet<QString> expectedValue;
+    expectedValue.reserve(6);
+    for (uint i = 0; i < 6; ++i)
+        expectedValue.insert(isError_array[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue.contains(testcase.first);
+    }
+}
+
+void tst_QScriptValue::isError()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.isError(), expected);
+    QCOMPARE(value.isError(), expected);
+}
diff --git a/qt/tests/qscriptvalue/tst_qscriptvalue_generated_totype.cpp b/qt/tests/qscriptvalue/tst_qscriptvalue_generated_totype.cpp
new file mode 100644 (file)
index 0000000..eaa5d14
--- /dev/null
@@ -0,0 +1,1786 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+/****************************************************************************
+*************** This file has been generated. DO NOT MODIFY! ****************
+****************************************************************************/
+
+#include "tst_qscriptvalue.h"
+
+static const QString toString_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const QString toString_valueArray[] = {
+    "", "undefined",
+    "null", "true",
+    "false", "122",
+    "124", "0",
+    "0", "123",
+    "6.37e-8", "-6.37e-8",
+    "1126240820", "65536",
+    "65537", "NaN",
+    "NaN", "Infinity",
+    "-Infinity", "NaN",
+    "Infinity", "-Infinity",
+    "ciao", "ciao",
+    "", "",
+    "0", "123",
+    "12.4", "undefined",
+    "null", "true",
+    "false", "122",
+    "124", "0",
+    "0", "123",
+    "6.37e-8", "-6.37e-8",
+    "1126240820", "65536",
+    "65537", "NaN",
+    "NaN", "Infinity",
+    "-Infinity", "NaN",
+    "Infinity", "-Infinity",
+    "ciao", "ciao",
+    "", "",
+    "0", "123",
+    "12.3", "undefined",
+    "null", "true",
+    "false", "122",
+    "124", "0",
+    "0", "123",
+    "6.37e-8", "-6.37e-8",
+    "1126240820", "65536",
+    "65537", "NaN",
+    "NaN", "Infinity",
+    "-Infinity", "NaN",
+    "Infinity", "-Infinity",
+    "ciao", "ciao",
+    "", "",
+    "0", "123",
+    "1.23", "",
+    "undefined", "[object Object]",
+    "Invalid Date", "",
+    "function () {\n    [native code]\n}", "Error: Unknown error",
+    "function Object() {\n    [native code]\n}", "function Array() {\n    [native code]\n}",
+    "function Number() {\n    [native code]\n}", "function Function() {\n    [native code]\n}",
+    "function () { return 1; }", "function () { return 'ciao'; }",
+    "function () { throw new Error('foo'); }", "/foo/",
+    "[object Object]", "",
+    "Error: Unknown error", "22",
+    "ReferenceError: Can't find variable: Undefined", "ReferenceError: Can't find variable: Null",
+    "ReferenceError: Can't find variable: True", "ReferenceError: Can't find variable: False",
+    "undefined", "null",
+    "true", "false",
+    "122", "124",
+    "0", "0",
+    "123", "6.37e-8",
+    "-6.37e-8", "1126240820",
+    "65536", "65537",
+    "NaN", "Infinity",
+    "-Infinity", "ciao",
+    "", "0",
+    "123", "12.4",
+    "null", "undefined",
+    "[object Object]", "",
+    ",,,,,,,,,"};
+
+void tst_QScriptValue::toString_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<QString>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, QString> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toString_tagArray[i], toString_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toString()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(QString, expected);
+    QCOMPARE(value.toString(), expected);
+    QCOMPARE(value.toString(), expected);
+}
+
+static const QString toNumber_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const qsreal toNumber_valueArray[] = {
+    0, qQNaN(), 0, 1, 0, 122, 124, 0, 0, 123,
+    6.369999999999999e-08, -6.369999999999999e-08, 1126240820, 65536, 65537, qQNaN(), qQNaN(), qInf(), qInf(), qQNaN(),
+    qInf(), qInf(), qQNaN(), qQNaN(), 0, 0, 0, 123, 12.4, qQNaN(),
+    0, 1, 0, 122, 124, 0, 0, 123, 6.369999999999999e-08, -6.369999999999999e-08,
+    1126240820, 65536, 65537, qQNaN(), qQNaN(), qInf(), qInf(), qQNaN(), qInf(), qInf(),
+    qQNaN(), qQNaN(), 0, 0, 0, 123, 12.3, qQNaN(), 0, 1,
+    0, 122, 124, 0, 0, 123, 6.369999999999999e-08, -6.369999999999999e-08, 1126240820, 65536,
+    65537, qQNaN(), qQNaN(), qInf(), qInf(), qQNaN(), qInf(), qInf(), qQNaN(), qQNaN(),
+    0, 0, 0, 123, 1.23, 0, qQNaN(), qQNaN(), qQNaN(), 0,
+    qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(),
+    qQNaN(), 0, qQNaN(), 22, qQNaN(), qQNaN(), qQNaN(), qQNaN(), qQNaN(), 0,
+    1, 0, 122, 124, 0, 0, 123, 6.369999999999999e-08, -6.369999999999999e-08, 1126240820,
+    65536, 65537, qQNaN(), qInf(), qInf(), qQNaN(), 0, 0, 123, 12.4,
+    0, qQNaN(), qQNaN(), 0, qQNaN()};
+
+void tst_QScriptValue::toNumber_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<qsreal>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, qsreal> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toNumber_tagArray[i], toNumber_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toNumber()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(qsreal, expected);
+    if (qIsNaN(expected)) {
+        QVERIFY(qIsNaN(value.toNumber()));
+        return;
+    }
+    if (qIsInf(expected)) {
+        QVERIFY(qIsInf(value.toNumber()));
+        QVERIFY(qIsInf(value.toNumber()));
+        return;
+    }
+    QCOMPARE(value.toNumber(), expected);
+    QCOMPARE(value.toNumber(), expected);
+}
+
+static const QString toBool_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const bool toBool_valueArray[] = {
+    false, false,
+    false, true,
+    false, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, true,
+    true, false,
+    false, true,
+    false, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, true,
+    true, false,
+    false, true,
+    false, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, true,
+    true, true,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, false,
+    true, true,
+    false, false,
+    true, true,
+    true, true,
+    true, true,
+    false, true,
+    true, true,
+    false, true,
+    true, true,
+    false, false,
+    true, true,
+    true};
+
+void tst_QScriptValue::toBool_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, bool> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toBool_tagArray[i], toBool_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toBool()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.toBool(), expected);
+    QCOMPARE(value.toBool(), expected);
+}
+
+static const QString toBoolean_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const bool toBoolean_valueArray[] = {
+    false, false,
+    false, true,
+    false, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, true,
+    true, false,
+    false, true,
+    false, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, true,
+    true, false,
+    false, true,
+    false, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, false,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, true,
+    true, true,
+    false, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    true, true,
+    false, false,
+    true, false,
+    true, true,
+    false, false,
+    true, true,
+    true, true,
+    true, true,
+    false, true,
+    true, true,
+    false, true,
+    true, true,
+    false, false,
+    true, true,
+    true};
+
+void tst_QScriptValue::toBoolean_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<bool>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, bool> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toBoolean_tagArray[i], toBoolean_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toBoolean()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(bool, expected);
+    QCOMPARE(value.toBoolean(), expected);
+    QCOMPARE(value.toBoolean(), expected);
+}
+
+static const QString toInteger_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const qsreal toInteger_valueArray[] = {
+    0, 0, 0, 1, 0, 122, 124, 0, 0, 123,
+    0, 0, 1126240820, 65536, 65537, 0, 0, qInf(), qInf(), 0,
+    qInf(), qInf(), 0, 0, 0, 0, 0, 123, 12, 0,
+    0, 1, 0, 122, 124, 0, 0, 123, 0, 0,
+    1126240820, 65536, 65537, 0, 0, qInf(), qInf(), 0, qInf(), qInf(),
+    0, 0, 0, 0, 0, 123, 12, 0, 0, 1,
+    0, 122, 124, 0, 0, 123, 0, 0, 1126240820, 65536,
+    65537, 0, 0, qInf(), qInf(), 0, qInf(), qInf(), 0, 0,
+    0, 0, 0, 123, 1, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 22, 0, 0, 0, 0, 0, 0,
+    1, 0, 122, 124, 0, 0, 123, 0, 0, 1126240820,
+    65536, 65537, 0, qInf(), qInf(), 0, 0, 0, 123, 12,
+    0, 0, 0, 0, 0};
+
+void tst_QScriptValue::toInteger_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<qsreal>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, qsreal> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toInteger_tagArray[i], toInteger_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toInteger()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(qsreal, expected);
+    if (qIsInf(expected)) {
+        QVERIFY(qIsInf(value.toInteger()));
+        QVERIFY(qIsInf(value.toInteger()));
+        return;
+    }
+    QCOMPARE(value.toInteger(), expected);
+    QCOMPARE(value.toInteger(), expected);
+}
+
+static const QString toInt32_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const qint32 toInt32_valueArray[] = {
+    0, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    1126240820, 65536,
+    65537, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    12, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    1126240820, 65536,
+    65537, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    12, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    1126240820, 65536,
+    65537, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    1, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 22,
+    0, 0,
+    0, 0,
+    0, 0,
+    1, 0,
+    122, 124,
+    0, 0,
+    123, 0,
+    0, 1126240820,
+    65536, 65537,
+    0, 0,
+    0, 0,
+    0, 0,
+    123, 12,
+    0, 0,
+    0, 0,
+    0};
+
+void tst_QScriptValue::toInt32_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<qint32>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, qint32> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toInt32_tagArray[i], toInt32_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toInt32()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(qint32, expected);
+    QCOMPARE(value.toInt32(), expected);
+    QCOMPARE(value.toInt32(), expected);
+}
+
+static const QString toUInt32_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const quint32 toUInt32_valueArray[] = {
+    0, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    1126240820, 65536,
+    65537, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    12, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    1126240820, 65536,
+    65537, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    12, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    1126240820, 65536,
+    65537, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    1, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 22,
+    0, 0,
+    0, 0,
+    0, 0,
+    1, 0,
+    122, 124,
+    0, 0,
+    123, 0,
+    0, 1126240820,
+    65536, 65537,
+    0, 0,
+    0, 0,
+    0, 0,
+    123, 12,
+    0, 0,
+    0, 0,
+    0};
+
+void tst_QScriptValue::toUInt32_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<quint32>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, quint32> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toUInt32_tagArray[i], toUInt32_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toUInt32()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(quint32, expected);
+    QCOMPARE(value.toUInt32(), expected);
+    QCOMPARE(value.toUInt32(), expected);
+}
+
+static const QString toUInt16_tagArray[] = {
+    "QScriptValue()",
+    "QScriptValue(QScriptValue::UndefinedValue)",
+    "QScriptValue(QScriptValue::NullValue)",
+    "QScriptValue(true)",
+    "QScriptValue(false)",
+    "QScriptValue(int(122))",
+    "QScriptValue(uint(124))",
+    "QScriptValue(0)",
+    "QScriptValue(0.0)",
+    "QScriptValue(123.0)",
+    "QScriptValue(6.37e-8)",
+    "QScriptValue(-6.37e-8)",
+    "QScriptValue(0x43211234)",
+    "QScriptValue(0x10000)",
+    "QScriptValue(0x10001)",
+    "QScriptValue(qSNaN())",
+    "QScriptValue(qQNaN())",
+    "QScriptValue(qInf())",
+    "QScriptValue(-qInf())",
+    "QScriptValue(\"NaN\")",
+    "QScriptValue(\"Infinity\")",
+    "QScriptValue(\"-Infinity\")",
+    "QScriptValue(\"ciao\")",
+    "QScriptValue(QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(QString(\"\"))",
+    "QScriptValue(QString())",
+    "QScriptValue(QString(\"0\"))",
+    "QScriptValue(QString(\"123\"))",
+    "QScriptValue(QString(\"12.4\"))",
+    "QScriptValue(0, QScriptValue::UndefinedValue)",
+    "QScriptValue(0, QScriptValue::NullValue)",
+    "QScriptValue(0, true)",
+    "QScriptValue(0, false)",
+    "QScriptValue(0, int(122))",
+    "QScriptValue(0, uint(124))",
+    "QScriptValue(0, 0)",
+    "QScriptValue(0, 0.0)",
+    "QScriptValue(0, 123.0)",
+    "QScriptValue(0, 6.37e-8)",
+    "QScriptValue(0, -6.37e-8)",
+    "QScriptValue(0, 0x43211234)",
+    "QScriptValue(0, 0x10000)",
+    "QScriptValue(0, 0x10001)",
+    "QScriptValue(0, qSNaN())",
+    "QScriptValue(0, qQNaN())",
+    "QScriptValue(0, qInf())",
+    "QScriptValue(0, -qInf())",
+    "QScriptValue(0, \"NaN\")",
+    "QScriptValue(0, \"Infinity\")",
+    "QScriptValue(0, \"-Infinity\")",
+    "QScriptValue(0, \"ciao\")",
+    "QScriptValue(0, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(0, QString(\"\"))",
+    "QScriptValue(0, QString())",
+    "QScriptValue(0, QString(\"0\"))",
+    "QScriptValue(0, QString(\"123\"))",
+    "QScriptValue(0, QString(\"12.3\"))",
+    "QScriptValue(engine, QScriptValue::UndefinedValue)",
+    "QScriptValue(engine, QScriptValue::NullValue)",
+    "QScriptValue(engine, true)",
+    "QScriptValue(engine, false)",
+    "QScriptValue(engine, int(122))",
+    "QScriptValue(engine, uint(124))",
+    "QScriptValue(engine, 0)",
+    "QScriptValue(engine, 0.0)",
+    "QScriptValue(engine, 123.0)",
+    "QScriptValue(engine, 6.37e-8)",
+    "QScriptValue(engine, -6.37e-8)",
+    "QScriptValue(engine, 0x43211234)",
+    "QScriptValue(engine, 0x10000)",
+    "QScriptValue(engine, 0x10001)",
+    "QScriptValue(engine, qSNaN())",
+    "QScriptValue(engine, qQNaN())",
+    "QScriptValue(engine, qInf())",
+    "QScriptValue(engine, -qInf())",
+    "QScriptValue(engine, \"NaN\")",
+    "QScriptValue(engine, \"Infinity\")",
+    "QScriptValue(engine, \"-Infinity\")",
+    "QScriptValue(engine, \"ciao\")",
+    "QScriptValue(engine, QString::fromLatin1(\"ciao\"))",
+    "QScriptValue(engine, QString(\"\"))",
+    "QScriptValue(engine, QString())",
+    "QScriptValue(engine, QString(\"0\"))",
+    "QScriptValue(engine, QString(\"123\"))",
+    "QScriptValue(engine, QString(\"1.23\"))",
+    "engine->evaluate(\"[]\")",
+    "engine->evaluate(\"{}\")",
+    "engine->evaluate(\"Object.prototype\")",
+    "engine->evaluate(\"Date.prototype\")",
+    "engine->evaluate(\"Array.prototype\")",
+    "engine->evaluate(\"Function.prototype\")",
+    "engine->evaluate(\"Error.prototype\")",
+    "engine->evaluate(\"Object\")",
+    "engine->evaluate(\"Array\")",
+    "engine->evaluate(\"Number\")",
+    "engine->evaluate(\"Function\")",
+    "engine->evaluate(\"(function() { return 1; })\")",
+    "engine->evaluate(\"(function() { return 'ciao'; })\")",
+    "engine->evaluate(\"(function() { throw new Error('foo'); })\")",
+    "engine->evaluate(\"/foo/\")",
+    "engine->evaluate(\"new Object()\")",
+    "engine->evaluate(\"new Array()\")",
+    "engine->evaluate(\"new Error()\")",
+    "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")",
+    "engine->evaluate(\"Undefined\")",
+    "engine->evaluate(\"Null\")",
+    "engine->evaluate(\"True\")",
+    "engine->evaluate(\"False\")",
+    "engine->evaluate(\"undefined\")",
+    "engine->evaluate(\"null\")",
+    "engine->evaluate(\"true\")",
+    "engine->evaluate(\"false\")",
+    "engine->evaluate(\"122\")",
+    "engine->evaluate(\"124\")",
+    "engine->evaluate(\"0\")",
+    "engine->evaluate(\"0.0\")",
+    "engine->evaluate(\"123.0\")",
+    "engine->evaluate(\"6.37e-8\")",
+    "engine->evaluate(\"-6.37e-8\")",
+    "engine->evaluate(\"0x43211234\")",
+    "engine->evaluate(\"0x10000\")",
+    "engine->evaluate(\"0x10001\")",
+    "engine->evaluate(\"NaN\")",
+    "engine->evaluate(\"Infinity\")",
+    "engine->evaluate(\"-Infinity\")",
+    "engine->evaluate(\"'ciao'\")",
+    "engine->evaluate(\"''\")",
+    "engine->evaluate(\"'0'\")",
+    "engine->evaluate(\"'123'\")",
+    "engine->evaluate(\"'12.4'\")",
+    "engine->nullValue()",
+    "engine->undefinedValue()",
+    "engine->newObject()",
+    "engine->newArray()",
+    "engine->newArray(10)"};
+
+static const quint16 toUInt16_valueArray[] = {
+    0, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    4660, 0,
+    1, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    12, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    4660, 0,
+    1, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    12, 0,
+    0, 1,
+    0, 122,
+    124, 0,
+    0, 123,
+    0, 0,
+    4660, 0,
+    1, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 123,
+    1, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 0,
+    0, 22,
+    0, 0,
+    0, 0,
+    0, 0,
+    1, 0,
+    122, 124,
+    0, 0,
+    123, 0,
+    0, 4660,
+    0, 1,
+    0, 0,
+    0, 0,
+    0, 0,
+    123, 12,
+    0, 0,
+    0, 0,
+    0};
+
+void tst_QScriptValue::toUInt16_data()
+{
+    QTest::addColumn<QScriptValue>("value");
+    QTest::addColumn<quint16>("expected");
+    if (m_engine)
+        delete m_engine;
+    m_engine = new QScriptEngine();
+    QHash<QString, quint16> expectedValue;
+    expectedValue.reserve(135);
+    for (uint i = 0; i < 135; ++i)
+        expectedValue.insert(toUInt16_tagArray[i], toUInt16_valueArray[i]);
+    for (uint i = 0; i < 135; ++i) {
+        QPair<QString, QScriptValue> testcase = initScriptValues(i);
+        QTest::newRow(testcase.first.toAscii().constData()) << testcase.second << expectedValue[testcase.first];
+    }
+}
+
+void tst_QScriptValue::toUInt16()
+{
+    QFETCH(QScriptValue, value);
+    QFETCH(quint16, expected);
+    QCOMPARE(value.toUInt16(), expected);
+    QCOMPARE(value.toUInt16(), expected);
+}
diff --git a/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro b/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro
new file mode 100644 (file)
index 0000000..5314ec9
--- /dev/null
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = tst_qscriptvalueiterator
+QT += testlib
+include(../tests.pri)
+
+SOURCES += tst_qscriptvalueiterator.cpp
+
diff --git a/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp b/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp
new file mode 100644 (file)
index 0000000..43d0042
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef tst_qscriptvalueiterator_h
+#define tst_qscriptvalueiterator_h
+
+#include "qscriptengine.h"
+#include "qscriptvalue.h"
+#include "qscriptvalueiterator.h"
+#include <QtCore/qhash.h>
+#include <QtTest/QtTest>
+
+class tst_QScriptValueIterator : public QObject {
+    Q_OBJECT
+
+public:
+    tst_QScriptValueIterator();
+    virtual ~tst_QScriptValueIterator();
+
+private slots:
+    void iterateForward_data();
+    void iterateForward();
+    void iterateBackward_data();
+    void iterateBackward();
+    void iterateArray_data();
+    void iterateArray();
+    void iterateBackAndForth();
+    void setValue();
+    void remove();
+    void removeMixed();
+    void removeUndeletable();
+    void iterateString();
+    void assignObjectToIterator();
+};
+
+tst_QScriptValueIterator::tst_QScriptValueIterator()
+{
+}
+
+tst_QScriptValueIterator::~tst_QScriptValueIterator()
+{
+}
+
+void tst_QScriptValueIterator::iterateForward_data()
+{
+    QTest::addColumn<QStringList>("propertyNames");
+    QTest::addColumn<QStringList>("propertyValues");
+
+    QTest::newRow("no properties")
+        << QStringList() << QStringList();
+    QTest::newRow("foo=bar")
+        << (QStringList() << "foo")
+        << (QStringList() << "bar");
+    QTest::newRow("foo=bar, baz=123")
+        << (QStringList() << "foo" << "baz")
+        << (QStringList() << "bar" << "123");
+    QTest::newRow("foo=bar, baz=123, rab=oof")
+        << (QStringList() << "foo" << "baz" << "rab")
+        << (QStringList() << "bar" << "123" << "oof");
+}
+
+void tst_QScriptValueIterator::iterateForward()
+{
+    QFETCH(QStringList, propertyNames);
+    QFETCH(QStringList, propertyValues);
+    QMap<QString, QString> pmap;
+    Q_ASSERT(propertyNames.size() == propertyValues.size());
+
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    for (int i = 0; i < propertyNames.size(); ++i) {
+        QString name = propertyNames.at(i);
+        QString value = propertyValues.at(i);
+        pmap.insert(name, value);
+        object.setProperty(name, QScriptValue(&engine, value));
+    }
+    QScriptValue otherObject = engine.newObject();
+    otherObject.setProperty("foo", QScriptValue(&engine, 123456));
+    otherObject.setProperty("protoProperty", QScriptValue(&engine, 654321));
+    object.setPrototype(otherObject); // should not affect iterator
+
+    QStringList lst;
+    QScriptValueIterator it(object);
+    while (!pmap.isEmpty()) {
+        QCOMPARE(it.hasNext(), true);
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QString name = it.name();
+        QCOMPARE(pmap.contains(name), true);
+        QCOMPARE(it.name(), name);
+        QCOMPARE(it.flags(), object.propertyFlags(name));
+        QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true);
+        QCOMPARE(it.scriptName(), engine.toStringHandle(name));
+        pmap.remove(name);
+        lst.append(name);
+    }
+
+    QCOMPARE(it.hasNext(), false);
+    QCOMPARE(it.hasNext(), false);
+
+    it.toFront();
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), lst.at(i));
+    }
+
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasPrevious(), true);
+        it.previous();
+        QCOMPARE(it.name(), lst.at(lst.count()-1-i));
+    }
+    QCOMPARE(it.hasPrevious(), false);
+}
+
+void tst_QScriptValueIterator::iterateBackward_data()
+{
+    iterateForward_data();
+}
+
+void tst_QScriptValueIterator::iterateBackward()
+{
+    QFETCH(QStringList, propertyNames);
+    QFETCH(QStringList, propertyValues);
+    QMap<QString, QString> pmap;
+    Q_ASSERT(propertyNames.size() == propertyValues.size());
+
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    for (int i = 0; i < propertyNames.size(); ++i) {
+        QString name = propertyNames.at(i);
+        QString value = propertyValues.at(i);
+        pmap.insert(name, value);
+        object.setProperty(name, QScriptValue(&engine, value));
+    }
+
+    QStringList lst;
+    QScriptValueIterator it(object);
+    it.toBack();
+    while (!pmap.isEmpty()) {
+        QCOMPARE(it.hasPrevious(), true);
+        QCOMPARE(it.hasPrevious(), true);
+        it.previous();
+        QString name = it.name();
+        QCOMPARE(pmap.contains(name), true);
+        QCOMPARE(it.name(), name);
+        QCOMPARE(it.flags(), object.propertyFlags(name));
+        QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true);
+        pmap.remove(name);
+        lst.append(name);
+    }
+
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasPrevious(), false);
+
+    it.toBack();
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasPrevious(), true);
+        it.previous();
+        QCOMPARE(it.name(), lst.at(i));
+    }
+
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), lst.at(lst.count()-1-i));
+    }
+    QCOMPARE(it.hasNext(), false);
+}
+
+void tst_QScriptValueIterator::iterateArray_data()
+{
+    QTest::addColumn<QStringList>("inputPropertyNames");
+    QTest::addColumn<QStringList>("inputPropertyValues");
+    QTest::addColumn<QStringList>("propertyNames");
+    QTest::addColumn<QStringList>("propertyValues");
+    QTest::newRow("no elements") << QStringList() << QStringList() << QStringList() << QStringList();
+
+    QTest::newRow("0=foo, 1=barr")
+        << (QStringList() << "0" << "1")
+        << (QStringList() << "foo" << "bar")
+        << (QStringList() << "0" << "1")
+        << (QStringList() << "foo" << "bar");
+
+    QTest::newRow("0=foo, 3=barr")
+        << (QStringList() << "0" << "1" << "2" << "3")
+        << (QStringList() << "foo" << "" << "" << "bar")
+        << (QStringList() << "0" << "1" << "2" << "3")
+        << (QStringList() << "foo" << "" << "" << "bar");
+}
+
+void tst_QScriptValueIterator::iterateArray()
+{
+    QFETCH(QStringList, inputPropertyNames);
+    QFETCH(QStringList, inputPropertyValues);
+    QFETCH(QStringList, propertyNames);
+    QFETCH(QStringList, propertyValues);
+
+    QScriptEngine engine;
+    QScriptValue array = engine.newArray();
+    for (int i = 0; i < inputPropertyNames.size(); ++i)
+        array.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i));
+
+    int length = array.property("length").toInt32();
+    QCOMPARE(length, propertyNames.size());
+    QScriptValueIterator it(array);
+    for (int i = 0; i < length; ++i) {
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), propertyNames.at(i));
+        QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
+        QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
+        QCOMPARE(it.value().toString(), propertyValues.at(i));
+    }
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("length"));
+    QVERIFY(it.value().isNumber());
+    QCOMPARE(it.value().toInt32(), length);
+    QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::SkipInEnumeration | QScriptValue::Undeletable));
+
+    it.previous();
+    QCOMPARE(it.hasPrevious(), length > 0);
+    for (int i = length - 1; i >= 0; --i) {
+        it.previous();
+        QCOMPARE(it.name(), propertyNames.at(i));
+        QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
+        QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
+        QCOMPARE(it.value().toString(), propertyValues.at(i));
+        QCOMPARE(it.hasPrevious(), i > 0);
+    }
+    QCOMPARE(it.hasPrevious(), false);
+
+    // hasNext() and hasPrevious() cache their result; verify that the result is in sync
+    if (length > 1) {
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("0"));
+        QVERIFY(it.hasNext());
+        it.previous();
+        QCOMPARE(it.name(), QString::fromLatin1("0"));
+        QVERIFY(!it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("0"));
+        QVERIFY(it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("1"));
+    }
+    {
+        // same test as object:
+        QScriptValue originalArray = engine.newArray();
+        for (int i = 0; i < inputPropertyNames.size(); ++i)
+            originalArray.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i));
+
+        QScriptValue array = originalArray.toObject();
+        int length = array.property("length").toInt32();
+        QCOMPARE(length, propertyNames.size());
+        QScriptValueIterator it(array);
+        for (int i = 0; i < length; ++i) {
+            QCOMPARE(it.hasNext(), true);
+            it.next();
+            QCOMPARE(it.name(), propertyNames.at(i));
+            QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
+            QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
+            QCOMPARE(it.value().toString(), propertyValues.at(i));
+        }
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("length"));
+    }
+}
+
+void tst_QScriptValueIterator::iterateBackAndForth()
+{
+    QScriptEngine engine;
+    {
+        QScriptValue object = engine.newObject();
+        object.setProperty("foo", QScriptValue(&engine, "bar"));
+        object.setProperty("rab", QScriptValue(&engine, "oof"),
+                           QScriptValue::SkipInEnumeration); // should not affect iterator
+        QScriptValueIterator it(object);
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+    }
+    {
+        // hasNext() and hasPrevious() cache their result; verify that the result is in sync
+        QScriptValue object = engine.newObject();
+        object.setProperty("foo", QScriptValue(&engine, "bar"));
+        object.setProperty("rab", QScriptValue(&engine, "oof"));
+        QScriptValueIterator it(object);
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("foo"));
+        QVERIFY(it.hasNext());
+        it.previous();
+        QCOMPARE(it.name(), QString::fromLatin1("foo"));
+        QVERIFY(!it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("foo"));
+        QVERIFY(it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("rab"));
+    }
+}
+
+void tst_QScriptValueIterator::setValue()
+{
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    object.setProperty("foo", QScriptValue(&engine, "bar"));
+    QScriptValueIterator it(object);
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("foo"));
+    it.setValue(QScriptValue(&engine, "baz"));
+    QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("baz"))), true);
+    QCOMPARE(object.property("foo").toString(), QLatin1String("baz"));
+    it.setValue(QScriptValue(&engine, "zab"));
+    QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("zab"))), true);
+    QCOMPARE(object.property("foo").toString(), QLatin1String("zab"));
+}
+
+void tst_QScriptValueIterator::remove()
+{
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    object.setProperty("foo", QScriptValue(&engine, "bar"),
+                       QScriptValue::SkipInEnumeration); // should not affect iterator
+    object.setProperty("rab", QScriptValue(&engine, "oof"));
+    QScriptValueIterator it(object);
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("foo"));
+    it.remove();
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(object.property("foo").isValid(), false);
+    QCOMPARE(object.property("rab").toString(), QLatin1String("oof"));
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("rab"));
+    QCOMPARE(it.value().toString(), QLatin1String("oof"));
+    QCOMPARE(it.hasNext(), false);
+    it.remove();
+    QCOMPARE(object.property("rab").isValid(), false);
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+}
+
+void tst_QScriptValueIterator::removeMixed()
+{
+    // This test checks if QScriptValueIterator behaives correctly if an object's property got deleted
+    // in different way.
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate("o = new Object; o");
+    object.setProperty("a", QScriptValue(124), QScriptValue::SkipInEnumeration);
+    object.setProperty("b", QScriptValue(816));
+    object.setProperty("c", QScriptValue(3264));
+    QScriptValueIterator it(object);
+    it.next();
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("b"));
+    QCOMPARE(it.hasPrevious(), true);
+    QCOMPARE(it.hasNext(), true);
+    // Remove 'a'
+    object.setProperty("a", QScriptValue());
+    QEXPECT_FAIL("", "That would be a significant behavioral and performance change, new QtScript API should be developed (QTBUG-12087)", Abort);
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), true);
+    // Remove 'c'
+    engine.evaluate("delete o.c");
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+    // Remove 'b'
+    object.setProperty("b", QScriptValue());
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+    QCOMPARE(it.name(), QString());
+    QCOMPARE(it.value().toString(), QString());
+
+    // Try to remove a removed property.
+    it.remove();
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+    QCOMPARE(it.name(), QString());
+    QCOMPARE(it.value().toString(), QString());
+
+    for (int i = 0; i < 2; ++i) {
+        it.next();
+        QCOMPARE(it.hasPrevious(), false);
+        QCOMPARE(it.hasNext(), false);
+        QCOMPARE(it.name(), QString());
+        QCOMPARE(it.value().toString(), QString());
+    }
+
+    for (int i = 0; i < 2; ++i) {
+        it.previous();
+        QCOMPARE(it.hasPrevious(), false);
+        QCOMPARE(it.hasNext(), false);
+        QCOMPARE(it.name(), QString());
+        QCOMPARE(it.value().toString(), QString());
+    }
+}
+
+void tst_QScriptValueIterator::removeUndeletable()
+{
+    // Undeletable property can't be deleted via iterator.
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate("o = new Object; o");
+    object.setProperty("a", QScriptValue(&engine, 124));
+    object.setProperty("b", QScriptValue(&engine, 816), QScriptValue::Undeletable);
+    QVERIFY(object.property("b").isValid());
+    QScriptValueIterator it(object);
+    it.next();
+    it.next();
+    it.remove();
+    it.toFront();
+    QVERIFY(it.hasNext());
+    QVERIFY(object.property("b").isValid());
+}
+
+void tst_QScriptValueIterator::iterateString()
+{
+    QScriptEngine engine;
+    QScriptValue str = QScriptValue(&engine, QString::fromLatin1("ciao"));
+    QVERIFY(str.isString());
+    QScriptValue obj = str.toObject();
+    int length = obj.property("length").toInt32();
+    QCOMPARE(length, 4);
+    QScriptValueIterator it(obj);
+    for (int i = 0; i < length; ++i) {
+        QCOMPARE(it.hasNext(), true);
+        QString indexStr = QScriptValue(&engine, i).toString();
+        it.next();
+        QCOMPARE(it.name(), indexStr);
+        QCOMPARE(it.flags(), obj.propertyFlags(indexStr));
+        QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true);
+    }
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("length"));
+    QVERIFY(it.value().isNumber());
+    QCOMPARE(it.value().toInt32(), length);
+    QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable));
+
+    it.previous();
+    QCOMPARE(it.hasPrevious(), length > 0);
+    for (int i = length - 1; i >= 0; --i) {
+        it.previous();
+        QString indexStr = QScriptValue(&engine, i).toString();
+        QCOMPARE(it.name(), indexStr);
+        QCOMPARE(it.flags(), obj.propertyFlags(indexStr));
+        QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true);
+        QCOMPARE(it.hasPrevious(), i > 0);
+    }
+    QCOMPARE(it.hasPrevious(), false);
+}
+
+void tst_QScriptValueIterator::assignObjectToIterator()
+{
+    QScriptEngine eng;
+    QScriptValue obj1 = eng.newObject();
+    obj1.setProperty("foo", 123);
+    QScriptValue obj2 = eng.newObject();
+    obj2.setProperty("bar", 456);
+
+    QScriptValueIterator it(obj1);
+    QVERIFY(it.hasNext());
+    it.next();
+    it = obj2;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("bar"));
+
+    it = obj1;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("foo"));
+
+    it = obj2;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("bar"));
+
+    it = obj2;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("bar"));
+}
+
+QTEST_MAIN(tst_QScriptValueIterator)
+#include "tst_qscriptvalueiterator.moc"
+
+#endif // tst_qscriptvalueiterator_h
index 7c3f590c5c9c80abc609b4d2400c62ca1294b4e7..6d5559b6d1bf5c4c3ae5435a4fa4fcb6190c4452 100644 (file)
@@ -1,4 +1,5 @@
 TEMPLATE = subdirs
 SUBDIRS =   qscriptengine \
             qscriptvalue \
+            qscriptvalueiterator \
             qscriptstring
index ab2b5d7dae7143c5166aa943cb8abce37e4ba67e..c1aa9dd7a6935e6b98059c043bb3c4c80b4f46fb 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "JSValue.h"
 #include "JSCell.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 
 using std::min;
 
@@ -37,12 +39,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
     result = ArgList(m_args + startIndex, m_argCount - startIndex);
 }
 
-void MarkedArgumentBuffer::markLists(MarkStack& markStack, ListSet& markSet)
+void MarkedArgumentBuffer::markLists(HeapRootVisitor& heapRootMarker, ListSet& markSet)
 {
     ListSet::iterator end = markSet.end();
     for (ListSet::iterator it = markSet.begin(); it != end; ++it) {
         MarkedArgumentBuffer* list = *it;
-        markStack.appendValues(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size);
+        heapRootMarker.mark(reinterpret_cast<JSValue*>(list->m_buffer), list->m_size);
     }
 }
 
@@ -54,8 +56,8 @@ void MarkedArgumentBuffer::slowAppend(JSValue v)
     // our Vector's inline capacity, though, our values move to the 
     // heap, where they do need explicit marking.
     if (!m_markSet) {
-        // We can only register for explicit marking once we know which heap
-        // is the current one, i.e., when a non-immediate value is appended.
+        // FIXME: Even if v is not a JSCell*, if previous values in the buffer
+        // are, then they won't be marked!
         if (Heap* heap = Heap::heap(v)) {
             ListSet& markSet = heap->markListSet();
             markSet.add(this);
index 8e1fdbe4b89af9084b631ae851c3304c1c45ad6c..ef7809fe8fc5682162e22cfb3e213aa86c230033 100644 (file)
 #ifndef ArgList_h
 #define ArgList_h
 
+#include "CallFrame.h"
 #include "Register.h"
+#include "WriteBarrier.h"
 #include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
     class MarkStack;
+    typedef MarkStack SlotVisitor;
 
-    class MarkedArgumentBuffer : public Noncopyable {
+    class MarkedArgumentBuffer {
+        WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
     private:
         static const unsigned inlineCapacity = 8;
         typedef Vector<Register, inlineCapacity> VectorType;
@@ -66,12 +69,12 @@ namespace JSC {
         {
         }
 
-        void initialize(Register* buffer, size_t size)
+        void initialize(WriteBarrier<Unknown>* buffer, size_t size)
         {
             ASSERT(!m_markSet);
             ASSERT(isEmpty());
 
-            m_buffer = buffer;
+            m_buffer = reinterpret_cast<Register*>(buffer);
             m_size = size;
 #ifndef NDEBUG
             m_isReadOnly = true;
@@ -140,7 +143,7 @@ namespace JSC {
         const_iterator begin() const { return m_buffer; }
         const_iterator end() const { return m_buffer + m_size; }
 
-        static void markLists(MarkStack&, ListSet&);
+        static void markLists(HeapRootVisitor&, ListSet&);
 
     private:
         void slowAppend(JSValue);
@@ -187,6 +190,12 @@ namespace JSC {
         {
         }
         
+        ArgList(ExecState* exec)
+            : m_args(reinterpret_cast<JSValue*>(&exec[exec->hostThisRegister() + 1]))
+            , m_argCount(exec->argumentCount())
+        {
+        }
+        
         ArgList(JSValue* args, unsigned argCount)
             : m_args(args)
             , m_argCount(argCount)
index bb30e3bc981b4740c8295f784cc5438402838a30..ec6cc8f1c7207da83af151426b9f581b19846c49 100644 (file)
@@ -35,7 +35,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(Arguments);
 
-const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
+const ClassInfo Arguments::s_info = { "Arguments", &JSNonFinalObject::s_info, 0, 0 };
 
 Arguments::~Arguments()
 {
@@ -43,22 +43,25 @@ Arguments::~Arguments()
         delete [] d->extraArguments;
 }
 
-void Arguments::markChildren(MarkStack& markStack)
+void Arguments::visitChildren(SlotVisitor& visitor)
 {
-    JSObject::markChildren(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSObject::visitChildren(visitor);
 
     if (d->registerArray)
-        markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters);
+        visitor.appendValues(d->registerArray.get(), d->numParameters);
 
     if (d->extraArguments) {
         unsigned numExtraArguments = d->numArguments - d->numParameters;
-        markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments);
+        visitor.appendValues(d->extraArguments, numExtraArguments);
     }
 
-    markStack.append(d->callee);
+    visitor.append(&d->callee);
 
     if (d->activation)
-        markStack.append(d->activation);
+        visitor.append(&d->activation);
 }
 
 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
@@ -74,9 +77,9 @@ void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxS
         unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
         unsigned i = 0;
         for (; i < parametersLength; ++i)
-            buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
+            buffer[i] = d->registers[d->firstParameterIndex + i].get();
         for (; i < d->numArguments; ++i)
-            buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+            buffer[i] = d->extraArguments[i - d->numParameters].get();
         return;
     }
     
@@ -84,13 +87,13 @@ void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxS
     unsigned i = 0;
     for (; i < parametersLength; ++i) {
         if (!d->deletedArguments[i])
-            buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
+            buffer[i] = d->registers[d->firstParameterIndex + i].get();
         else
             buffer[i] = get(exec, i);
     }
     for (; i < d->numArguments; ++i) {
         if (!d->deletedArguments[i])
-            buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+            buffer[i] = d->extraArguments[i - d->numParameters].get();
         else
             buffer[i] = get(exec, i);
     }
@@ -119,9 +122,9 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
         unsigned parametersLength = min(d->numParameters, d->numArguments);
         unsigned i = 0;
         for (; i < parametersLength; ++i)
-            args.append(d->registers[d->firstParameterIndex + i].jsValue());
+            args.append(d->registers[d->firstParameterIndex + i].get());
         for (; i < d->numArguments; ++i)
-            args.append(d->extraArguments[i - d->numParameters].jsValue());
+            args.append(d->extraArguments[i - d->numParameters].get());
         return;
     }
 
@@ -129,13 +132,13 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
     unsigned i = 0;
     for (; i < parametersLength; ++i) {
         if (!d->deletedArguments[i])
-            args.append(d->registers[d->firstParameterIndex + i].jsValue());
+            args.append(d->registers[d->firstParameterIndex + i].get());
         else
             args.append(get(exec, i));
     }
     for (; i < d->numArguments; ++i) {
         if (!d->deletedArguments[i])
-            args.append(d->extraArguments[i - d->numParameters].jsValue());
+            args.append(d->extraArguments[i - d->numParameters].get());
         else
             args.append(get(exec, i));
     }
@@ -145,61 +148,97 @@ bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& sl
 {
     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
         if (i < d->numParameters) {
-            slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+            slot.setValue(d->registers[d->firstParameterIndex + i].get());
         } else
-            slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
+            slot.setValue(d->extraArguments[i - d->numParameters].get());
         return true;
     }
 
-    return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
+    return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::number(i)), slot);
+}
+    
+void Arguments::createStrictModeCallerIfNecessary(ExecState* exec)
+{
+    if (d->overrodeCaller)
+        return;
+
+    d->overrodeCaller = true;
+    PropertyDescriptor descriptor;
+    JSValue thrower = createTypeErrorFunction(exec, "Unable to access caller of strict mode function");
+    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
+    defineOwnProperty(exec, exec->propertyNames().caller, descriptor, false);
+}
+
+void Arguments::createStrictModeCalleeIfNecessary(ExecState* exec)
+{
+    if (d->overrodeCallee)
+        return;
+    
+    d->overrodeCallee = true;
+    PropertyDescriptor descriptor;
+    JSValue thrower = createTypeErrorFunction(exec, "Unable to access callee of strict mode function");
+    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
+    defineOwnProperty(exec, exec->propertyNames().callee, descriptor, false);
 }
 
 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
         if (i < d->numParameters) {
-            slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
+            slot.setValue(d->registers[d->firstParameterIndex + i].get());
         } else
-            slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
+            slot.setValue(d->extraArguments[i - d->numParameters].get());
         return true;
     }
 
     if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
-        slot.setValue(jsNumber(exec, d->numArguments));
+        slot.setValue(jsNumber(d->numArguments));
         return true;
     }
 
     if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
-        slot.setValue(d->callee);
-        return true;
+        if (!d->isStrictMode) {
+            slot.setValue(d->callee.get());
+            return true;
+        }
+        createStrictModeCalleeIfNecessary(exec);
     }
 
+    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
+        createStrictModeCallerIfNecessary(exec);
+
     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
 bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
         if (i < d->numParameters) {
-            descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
+            descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].get(), DontEnum);
         } else
-            descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
+            descriptor.setDescriptor(d->extraArguments[i - d->numParameters].get(), DontEnum);
         return true;
     }
     
     if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
-        descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum);
+        descriptor.setDescriptor(jsNumber(d->numArguments), DontEnum);
         return true;
     }
     
     if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
-        descriptor.setDescriptor(d->callee, DontEnum);
-        return true;
+        if (!d->isStrictMode) {
+            descriptor.setDescriptor(d->callee.get(), DontEnum);
+            return true;
+        }
+        createStrictModeCalleeIfNecessary(exec);
     }
+
+    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
+        createStrictModeCallerIfNecessary(exec);
     
     return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
 }
@@ -209,7 +248,7 @@ void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& property
     if (mode == IncludeDontEnumProperties) {
         for (unsigned i = 0; i < d->numArguments; ++i) {
             if (!d->deletedArguments || !d->deletedArguments[i])
-                propertyNames.add(Identifier(exec, UString::from(i)));
+                propertyNames.add(Identifier(exec, UString::number(i)));
         }
         propertyNames.add(exec->propertyNames().callee);
         propertyNames.add(exec->propertyNames().length);
@@ -217,43 +256,50 @@ void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& property
     JSObject::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
-void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
+void Arguments::put(ExecState* exec, unsigned i, JSValue value)
 {
     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
         if (i < d->numParameters)
-            d->registers[d->firstParameterIndex + i] = JSValue(value);
+            d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
         else
-            d->extraArguments[i - d->numParameters] = JSValue(value);
+            d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
         return;
     }
 
-    JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
+    PutPropertySlot slot;
+    JSObject::put(exec, Identifier(exec, UString::number(i)), value, slot);
 }
 
 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
         if (i < d->numParameters)
-            d->registers[d->firstParameterIndex + i] = JSValue(value);
+            d->registers[d->firstParameterIndex + i].set(exec->globalData(), d->activation ? static_cast<JSCell*>(d->activation.get()) : static_cast<JSCell*>(this), value);
         else
-            d->extraArguments[i - d->numParameters] = JSValue(value);
+            d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
         return;
     }
 
     if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
         d->overrodeLength = true;
-        putDirect(propertyName, value, DontEnum);
+        putDirect(exec->globalData(), propertyName, value, DontEnum);
         return;
     }
 
     if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
-        d->overrodeCallee = true;
-        putDirect(propertyName, value, DontEnum);
-        return;
+        if (!d->isStrictMode) {
+            d->overrodeCallee = true;
+            putDirect(exec->globalData(), propertyName, value, DontEnum);
+            return;
+        }
+        createStrictModeCalleeIfNecessary(exec);
     }
 
+    if (propertyName == exec->propertyNames().caller && d->isStrictMode)
+        createStrictModeCallerIfNecessary(exec);
+
     JSObject::put(exec, propertyName, value, slot);
 }
 
@@ -261,7 +307,7 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i)
 {
     if (i < d->numArguments) {
         if (!d->deletedArguments) {
-            d->deletedArguments.set(new bool[d->numArguments]);
+            d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]);
             memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
         }
         if (!d->deletedArguments[i]) {
@@ -270,16 +316,16 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i)
         }
     }
 
-    return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
+    return JSObject::deleteProperty(exec, Identifier(exec, UString::number(i)));
 }
 
 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) 
 {
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex && i < d->numArguments) {
         if (!d->deletedArguments) {
-            d->deletedArguments.set(new bool[d->numArguments]);
+            d->deletedArguments = adoptArrayPtr(new bool[d->numArguments]);
             memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
         }
         if (!d->deletedArguments[i]) {
@@ -294,9 +340,15 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
     }
 
     if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
-        d->overrodeCallee = true;
-        return true;
+        if (!d->isStrictMode) {
+            d->overrodeCallee = true;
+            return true;
+        }
+        createStrictModeCalleeIfNecessary(exec);
     }
+    
+    if (propertyName == exec->propertyNames().caller && !d->isStrictMode)
+        createStrictModeCallerIfNecessary(exec);
 
     return JSObject::deleteProperty(exec, propertyName);
 }
index cca3cf21d019236f4f6651d19cd2719c48472001..9686d8b6cfea2054c37bac95b2311278f2363a75 100644 (file)
 #include "JSGlobalObject.h"
 #include "Interpreter.h"
 #include "ObjectConstructor.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
-    struct ArgumentsData : Noncopyable {
-        JSActivation* activation;
+    struct ArgumentsData {
+        WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        ArgumentsData() { }
+        WriteBarrier<JSActivation> activation;
 
         unsigned numParameters;
         ptrdiff_t firstParameterIndex;
         unsigned numArguments;
 
-        Register* registers;
-        OwnArrayPtr<Register> registerArray;
+        WriteBarrier<Unknown>* registers;
+        OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
 
-        Register* extraArguments;
+        WriteBarrier<Unknown>* extraArguments;
         OwnArrayPtr<bool> deletedArguments;
-        Register extraArgumentsFixedBuffer[4];
+        WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
 
-        JSFunction* callee;
+        WriteBarrier<JSFunction> callee;
         bool overrodeLength : 1;
         bool overrodeCallee : 1;
+        bool overrodeCaller : 1;
+        bool isStrictMode : 1;
     };
 
 
-    class Arguments : public JSObject {
+    class Arguments : public JSNonFinalObject {
     public:
         // Use an enum because otherwise gcc insists on doing a memory
         // read.
@@ -65,9 +69,9 @@ namespace JSC {
         Arguments(CallFrame*, NoParametersType);
         virtual ~Arguments();
 
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
@@ -79,21 +83,22 @@ namespace JSC {
         }
         
         void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
-        void copyRegisters();
+        void copyRegisters(JSGlobalData&);
         bool isTornOff() const { return d->registerArray; }
-        void setActivation(JSActivation* activation)
+        void setActivation(JSGlobalData& globalData, JSActivation* activation)
         {
-            d->activation = activation;
+            ASSERT(!d->registerArray);
+            d->activation.set(globalData, this, activation);
             d->registers = &activation->registerAt(0);
         }
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
         { 
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
     private:
         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
@@ -102,11 +107,11 @@ namespace JSC {
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
+        virtual void put(ExecState*, unsigned propertyName, JSValue);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
-
-        virtual const ClassInfo* classInfo() const { return &info; }
+        void createStrictModeCallerIfNecessary(ExecState*);
+        void createStrictModeCalleeIfNecessary(ExecState*);
 
         void init(CallFrame*);
 
@@ -117,16 +122,16 @@ namespace JSC {
 
     inline Arguments* asArguments(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&Arguments::info));
+        ASSERT(asObject(value)->inherits(&Arguments::s_info));
         return static_cast<Arguments*>(asObject(value));
     }
 
     ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
     {
-        function = callFrame->callee();
+        function = asFunction(callFrame->callee());
 
         int numParameters = function->jsExecutable()->parameterCount();
-        argc = callFrame->argumentCount();
+        argc = callFrame->argumentCountIncludingThis();
 
         if (argc <= numParameters)
             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
@@ -138,9 +143,11 @@ namespace JSC {
     }
 
     inline Arguments::Arguments(CallFrame* callFrame)
-        : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
-        , d(new ArgumentsData)
+        : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
+        , d(adoptPtr(new ArgumentsData))
     {
+        ASSERT(inherits(&s_info));
+
         JSFunction* callee;
         ptrdiff_t firstParameterIndex;
         Register* argv;
@@ -151,59 +158,66 @@ namespace JSC {
         d->firstParameterIndex = firstParameterIndex;
         d->numArguments = numArguments;
 
-        d->activation = 0;
-        d->registers = callFrame->registers();
+        d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
 
-        Register* extraArguments;
+        WriteBarrier<Unknown>* extraArguments;
         if (d->numArguments <= d->numParameters)
             extraArguments = 0;
         else {
             unsigned numExtraArguments = d->numArguments - d->numParameters;
-            if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
-                extraArguments = new Register[numExtraArguments];
+            if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
+                extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
             else
                 extraArguments = d->extraArgumentsFixedBuffer;
             for (unsigned i = 0; i < numExtraArguments; ++i)
-                extraArguments[i] = argv[d->numParameters + i];
+                extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
         }
 
         d->extraArguments = extraArguments;
 
-        d->callee = callee;
+        d->callee.set(callFrame->globalData(), this, callee);
         d->overrodeLength = false;
         d->overrodeCallee = false;
+        d->overrodeCaller = false;
+        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
+        if (d->isStrictMode)
+            copyRegisters(callFrame->globalData());
     }
 
     inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
-        : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
-        , d(new ArgumentsData)
+        : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
+        , d(adoptPtr(new ArgumentsData))
     {
-        ASSERT(!callFrame->callee()->jsExecutable()->parameterCount());
+        ASSERT(inherits(&s_info));
+        ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
 
-        unsigned numArguments = callFrame->argumentCount() - 1;
+        unsigned numArguments = callFrame->argumentCount();
 
         d->numParameters = 0;
         d->numArguments = numArguments;
-        d->activation = 0;
 
-        Register* extraArguments;
+        WriteBarrier<Unknown>* extraArguments;
         if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
-            extraArguments = new Register[numArguments];
+            extraArguments = new WriteBarrier<Unknown>[numArguments];
         else
             extraArguments = d->extraArgumentsFixedBuffer;
 
         Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
         for (unsigned i = 0; i < numArguments; ++i)
-            extraArguments[i] = argv[i];
+            extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
 
         d->extraArguments = extraArguments;
 
-        d->callee = callFrame->callee();
+        d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
         d->overrodeLength = false;
         d->overrodeCallee = false;
+        d->overrodeCaller = false;
+        d->isStrictMode = callFrame->codeBlock()->isStrictMode();
+        if (d->isStrictMode)
+            copyRegisters(callFrame->globalData());
     }
 
-    inline void Arguments::copyRegisters()
+    inline void Arguments::copyRegisters(JSGlobalData& globalData)
     {
         ASSERT(!isTornOff());
 
@@ -213,40 +227,30 @@ namespace JSC {
         int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
         size_t registerArraySize = d->numParameters;
 
-        Register* registerArray = new Register[registerArraySize];
-        memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
-        d->registerArray.set(registerArray);
-        d->registers = registerArray + registerOffset;
+        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
+        for (size_t i = 0; i < registerArraySize; i++)
+            registerArray[i].set(globalData, this, d->registers[i - registerOffset].get());
+        d->registers = registerArray.get() + registerOffset;
+        d->registerArray = registerArray.release();
     }
 
     // This JSActivation function is defined here so it can get at Arguments::setRegisters.
-    inline void JSActivation::copyRegisters(Arguments* arguments)
+    inline void JSActivation::copyRegisters(JSGlobalData& globalData)
     {
-        ASSERT(!d()->registerArray);
+        ASSERT(!m_registerArray);
 
-        size_t numParametersMinusThis = d()->functionExecutable->generatedBytecode().m_numParameters - 1;
-        size_t numVars = d()->functionExecutable->generatedBytecode().m_numVars;
-        size_t numLocals = numVars + numParametersMinusThis;
+        size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
 
         if (!numLocals)
             return;
 
-        int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+        int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
         size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
 
-        Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
-        setRegisters(registerArray + registerOffset, registerArray);
-        if (arguments && !arguments->isTornOff())
-            static_cast<Arguments*>(arguments)->setActivation(this);
-    }
-
-    ALWAYS_INLINE Arguments* Register::arguments() const
-    {
-        if (jsValue() == JSValue())
-            return 0;
-        return asArguments(jsValue());
+        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
+        WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
+        setRegisters(registers, registerArray.release());
     }
-    
 
 } // namespace JSC
 
index fb4449405130bd557d93cf576d57cb376b8d568a..a4df41193d25e25f88a47ec602f7cc6e2605a5de 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008, 2011 Apple Inc. All rights reserved.
  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
 
 #include "ArrayPrototype.h"
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Lookup.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
+static EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*);
+
+}
+
+#include "ArrayConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo ArrayConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::arrayConstructorTable };
+
+/* Source for ArrayConstructor.lut.h
+@begin arrayConstructorTable
+  isArray   arrayConstructorIsArray     DontEnum|Function 1
+@end
+*/
+
 ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor);
-    
-static JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList&);
 
-ArrayConstructor::ArrayConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className))
+ArrayConstructor::ArrayConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, arrayPrototype->classInfo()->className))
 {
-    // ECMA 15.4.3.1 Array.prototype
-    putDirectWithoutTransition(exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, arrayPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
+}
 
-    // no. of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+bool ArrayConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::arrayConstructorTable(exec), this, propertyName, slot);
+}
 
-    // ES5
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum);
+bool ArrayConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::arrayConstructorTable(exec), this, propertyName, descriptor);
 }
 
+// ------------------------------ Functions ---------------------------
+
 static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args)
 {
+    JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
+
     // a single numeric argument denotes the array size (!)
     if (args.size() == 1 && args.at(0).isNumber()) {
         uint32_t n = args.at(0).toUInt32(exec);
         if (n != args.at(0).toNumber(exec))
-            return throwError(exec, RangeError, "Array size is not a small enough positive integer.");
-        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), n);
+            return throwError(exec, createRangeError(exec, "Array size is not a small enough positive integer."));
+        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), n, CreateInitialized);
     }
 
     // otherwise the array is constructed with the arguments in it
-    return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), args);
+    return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), args);
 }
 
-static JSObject* constructWithArrayConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec)
 {
-    return constructArrayWithSizeQuirk(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructArrayWithSizeQuirk(exec, args));
 }
 
-// ECMA 15.4.2
 ConstructType ArrayConstructor::getConstructData(ConstructData& constructData)
 {
     constructData.native.function = constructWithArrayConstructor;
     return ConstructTypeHost;
 }
 
-static JSValue JSC_HOST_CALL callArrayConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callArrayConstructor(ExecState* exec)
 {
-    return constructArrayWithSizeQuirk(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructArrayWithSizeQuirk(exec, args));
 }
 
-// ECMA 15.6.1
 CallType ArrayConstructor::getCallData(CallData& callData)
 {
     // equivalent to 'new Array(....)'
@@ -89,9 +111,9 @@ CallType ArrayConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
-JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState* exec)
 {
-    return jsBoolean(args.at(0).inherits(&JSArray::info));
+    return JSValue::encode(jsBoolean(exec->argument(0).inherits(&JSArray::s_info)));
 }
 
 } // namespace JSC
index 6d25400145acfdec411427d699b46d404fbdf99f..dc0df2455e05a8d3f532318af6a005e12e8db818 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -29,7 +29,21 @@ namespace JSC {
 
     class ArrayConstructor : public InternalFunction {
     public:
-        ArrayConstructor(ExecState*, NonNullPassRefPtr<Structure>, ArrayPrototype*, Structure*);
+        ArrayConstructor(ExecState*, JSGlobalObject*, Structure*, ArrayPrototype*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
+
+    private:
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
index 20ad8c1ef2a8ac72281d3efb2964f246a224d206..8b2393ce890bda356e6f063e5593f006dff8867a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
@@ -32,6 +32,7 @@
 #include "Lookup.h"
 #include "ObjectPrototype.h"
 #include "Operations.h"
+#include "StringRecursionChecker.h"
 #include <algorithm>
 #include <wtf/Assertions.h>
 #include <wtf/HashSet.h>
@@ -40,27 +41,27 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
 
-static JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState*);
+static EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState*);
 
 }
 
@@ -73,32 +74,21 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
     if (callType != CallTypeJS)
         return false;
 
-#if ENABLE(JIT)
-    // If the JIT is enabled then we need to preserve the invariant that every
-    // function with a CodeBlock also has JIT code.
-    CodeBlock* codeBlock = 0;
-#if ENABLE(INTERPRETER)
-    if (!exec->globalData().canUseJIT())
-        codeBlock = &callData.js.functionExecutable->bytecode(exec, callData.js.scopeChain);
-    else
-#endif
-    {
-        callData.js.functionExecutable->jitCode(exec, callData.js.scopeChain);
-        codeBlock = &callData.js.functionExecutable->generatedBytecode();
-    }
-#else
-    CodeBlock* codeBlock = &callData.js.functionExecutable->bytecode(exec, callData.js.scopeChain);
-#endif
+    FunctionExecutable* executable = callData.js.functionExecutable;
 
-    return codeBlock->isNumericCompareFunction();
+    JSObject* error = executable->compileForCall(exec, callData.js.scopeChain);
+    if (error)
+        return false;
+
+    return executable->generatedBytecodeForCall().isNumericCompareFunction();
 }
 
 // ------------------------------ ArrayPrototype ----------------------------
 
-const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::arrayTable};
+const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, 0, ExecState::arrayPrototypeTable};
 
 /* Source for ArrayPrototype.lut.h
-@begin arrayTable 16
+@begin arrayPrototypeTable 16
   toString       arrayProtoFuncToString       DontEnum|Function 0
   toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
   concat         arrayProtoFuncConcat         DontEnum|Function 1
@@ -124,19 +114,21 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a
 */
 
 // ECMA 15.4.4
-ArrayPrototype::ArrayPrototype(NonNullPassRefPtr<Structure> structure)
-    : JSArray(structure)
+ArrayPrototype::ArrayPrototype(JSGlobalObject* globalObject, Structure* structure)
+    : JSArray(globalObject->globalData(), structure)
 {
+    ASSERT(inherits(&s_info));
+    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
 bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, slot);
+    return getStaticFunctionSlot<JSArray>(exec, ExecState::arrayPrototypeTable(exec), this, propertyName, slot);
 }
 
 bool ArrayPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
-    return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, descriptor);
+    return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayPrototypeTable(exec), this, propertyName, descriptor);
 }
 
 // ------------------------------ Array Functions ----------------------------
@@ -156,26 +148,46 @@ static void putProperty(ExecState* exec, JSObject* obj, const Identifier& proper
     obj->put(exec, propertyName, value, slot);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+static unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
+{
+    JSValue value = exec->argument(argument);
+    if (value.isUndefined())
+        return undefinedValue;
+
+    double indexDouble = value.toInteger(exec);
+    if (indexDouble < 0) {
+        indexDouble += length;
+        return indexDouble < 0 ? 0 : static_cast<unsigned>(indexDouble);
+    }
+    return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
+}
+
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+
     bool isRealArray = isJSArray(&exec->globalData(), thisValue);
-    if (!isRealArray && !thisValue.inherits(&JSArray::info))
-        return throwError(exec, TypeError);
+    if (!isRealArray && !thisValue.inherits(&JSArray::s_info))
+        return throwVMTypeError(exec);
     JSArray* thisObj = asArray(thisValue);
     
-    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
-    if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
-        if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
-            return throwError(exec, RangeError, "Maximum call stack size exceeded.");    
-    }
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
-    if (alreadyVisited)
-        return jsEmptyString(exec); // return an empty string, avoiding infinite recursion.
+    StringRecursionChecker checker(exec, thisObj);
+    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+        return earlyReturnValue;
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned totalSize = length ? length - 1 : 0;
-    Vector<RefPtr<UString::Rep>, 256> strBuffer(length);
+#if OS(SYMBIAN)
+    // Symbian has very limited stack size available.
+    // This function could be called recursively and allocating 1K on stack here cause
+    // stack overflow on Symbian devices.
+    Vector<RefPtr<StringImpl> > strBuffer(length);
+#else
+    Vector<RefPtr<StringImpl>, 256> strBuffer(length);
+#endif    
     for (unsigned k = 0; k < length; k++) {
         JSValue element;
         if (isRealArray && thisObj->canGetIndex(k))
@@ -187,8 +199,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
             continue;
         
         UString str = element.toString(exec);
-        strBuffer[k] = str.rep();
-        totalSize += str.size();
+        strBuffer[k] = str.impl();
+        totalSize += str.length();
         
         if (!strBuffer.data()) {
             throwOutOfMemoryError(exec);
@@ -197,42 +209,40 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
         if (exec->hadException())
             break;
     }
-    arrayVisitedElements.remove(thisObj);
     if (!totalSize)
-        return jsEmptyString(exec);
+        return JSValue::encode(jsEmptyString(exec));
     Vector<UChar> buffer;
     buffer.reserveCapacity(totalSize);
     if (!buffer.data())
-        return throwOutOfMemoryError(exec);
+        return JSValue::encode(throwOutOfMemoryError(exec));
         
     for (unsigned i = 0; i < length; i++) {
         if (i)
             buffer.append(',');
-        if (RefPtr<UString::Rep> rep = strBuffer[i])
+        if (RefPtr<StringImpl> rep = strBuffer[i])
             buffer.append(rep->characters(), rep->length());
     }
     ASSERT(buffer.size() == totalSize);
-    return jsString(exec, UString::adopt(buffer));
+    return JSValue::encode(jsString(exec, UString::adopt(buffer)));
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
 {
-    if (!thisValue.inherits(&JSArray::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+
+    if (!thisValue.inherits(&JSArray::s_info))
+        return throwVMTypeError(exec);
     JSObject* thisObj = asArray(thisValue);
 
-    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
-    if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
-        if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
-            return throwError(exec, RangeError, "Maximum call stack size exceeded.");    
-    }
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
-    if (alreadyVisited)
-        return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
+    StringRecursionChecker checker(exec, thisObj);
+    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+        return earlyReturnValue;
 
     JSStringBuilder strBuffer;
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     for (unsigned k = 0; k < length; k++) {
         if (k >= 1)
             strBuffer.append(',');
@@ -243,7 +253,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, J
             JSValue conversionFunction = o->get(exec, exec->propertyNames().toLocaleString);
             UString str;
             CallData callData;
-            CallType callType = conversionFunction.getCallData(callData);
+            CallType callType = getCallData(conversionFunction, callData);
             if (callType != CallTypeNone)
                 str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec);
             else
@@ -251,48 +261,61 @@ JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, J
             strBuffer.append(str);
         }
     }
-    arrayVisitedElements.remove(thisObj);
-    return strBuffer.build(exec);
+
+    return JSValue::encode(strBuffer.build(exec));
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
-
-    HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements;
-    if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) {
-        if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth)
-            return throwError(exec, RangeError, "Maximum call stack size exceeded.");    
-    }
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    bool alreadyVisited = !arrayVisitedElements.add(thisObj).second;
-    if (alreadyVisited)
-        return jsEmptyString(exec); // return an empty string, avoding infinite recursion.
+    StringRecursionChecker checker(exec, thisObj);
+    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+        return earlyReturnValue;
 
     JSStringBuilder strBuffer;
 
     UString separator;
-    if (!args.at(0).isUndefined())
-        separator = args.at(0).toString(exec);
+    if (!exec->argument(0).isUndefined())
+        separator = exec->argument(0).toString(exec);
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned k = 0;
     if (isJSArray(&exec->globalData(), thisObj)) {
         JSArray* array = asArray(thisObj);
-        for (; k < length; k++) {
-            if (!array->canGetIndex(k))
-                break;
-            if (k >= 1) {
-                if (separator.isNull())
-                    strBuffer.append(',');
-                else
-                    strBuffer.append(separator);
-            }
+
+        if (length) {
+            if (!array->canGetIndex(k)) 
+                goto skipFirstLoop;
             JSValue element = array->getIndex(k);
             if (!element.isUndefinedOrNull())
                 strBuffer.append(element.toString(exec));
+            k++;
+        }
+
+        if (separator.isNull()) {
+            for (; k < length; k++) {
+                if (!array->canGetIndex(k))
+                    break;
+                strBuffer.append(',');
+                JSValue element = array->getIndex(k);
+                if (!element.isUndefinedOrNull())
+                    strBuffer.append(element.toString(exec));
+            }
+        } else {
+            for (; k < length; k++) {
+                if (!array->canGetIndex(k))
+                    break;
+                strBuffer.append(separator);
+                JSValue element = array->getIndex(k);
+                if (!element.isUndefinedOrNull())
+                    strBuffer.append(element.toString(exec));
+            }
         }
     }
+ skipFirstLoop:
     for (; k < length; k++) {
         if (k >= 1) {
             if (separator.isNull())
@@ -305,19 +328,20 @@ JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thi
         if (!element.isUndefinedOrNull())
             strBuffer.append(element.toString(exec));
     }
-    arrayVisitedElements.remove(thisObj);
-    return strBuffer.build(exec);
+
+    return JSValue::encode(strBuffer.build(exec));
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     JSArray* arr = constructEmptyArray(exec);
-    int n = 0;
+    unsigned n = 0;
     JSValue curArg = thisValue.toThisObject(exec);
-    ArgList::const_iterator it = args.begin();
-    ArgList::const_iterator end = args.end();
+    size_t i = 0;
+    size_t argCount = exec->argumentCount();
     while (1) {
-        if (curArg.inherits(&JSArray::info)) {
+        if (curArg.inherits(&JSArray::s_info)) {
             unsigned length = curArg.get(exec, exec->propertyNames().length).toUInt32(exec);
             JSObject* curObject = curArg.toObject(exec);
             for (unsigned k = 0; k < length; ++k) {
@@ -329,57 +353,69 @@ JSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec, JSObject*, JSValue t
             arr->put(exec, n, curArg);
             n++;
         }
-        if (it == end)
+        if (i == argCount)
             break;
-        curArg = (*it);
-        ++it;
+        curArg = (exec->argument(i));
+        ++i;
     }
     arr->setLength(n);
-    return arr;
+    return JSValue::encode(arr);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+
     if (isJSArray(&exec->globalData(), thisValue))
-        return asArray(thisValue)->pop();
+        return JSValue::encode(asArray(thisValue)->pop());
 
     JSObject* thisObj = thisValue.toThisObject(exec);
-    JSValue result;
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue result;
     if (length == 0) {
-        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, length - 1);
         thisObj->deleteProperty(exec, length - 1);
-        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
+        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
     }
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
 {
-    if (isJSArray(&exec->globalData(), thisValue) && args.size() == 1) {
+    JSValue thisValue = exec->hostThisValue();
+
+    if (isJSArray(&exec->globalData(), thisValue) && exec->argumentCount() == 1) {
         JSArray* array = asArray(thisValue);
-        array->push(exec, *args.begin());
-        return jsNumber(exec, array->length());
+        array->push(exec, exec->argument(0));
+        return JSValue::encode(jsNumber(array->length()));
     }
 
     JSObject* thisObj = thisValue.toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    for (unsigned n = 0; n < args.size(); n++)
-        thisObj->put(exec, length + n, args.at(n));
-    length += args.size();
-    putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
-    return jsNumber(exec, length);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    for (unsigned n = 0; n < exec->argumentCount(); n++)
+        thisObj->put(exec, length + n, exec->argument(n));
+    length += exec->argumentCount();
+    putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
+    return JSValue::encode(jsNumber(length));
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    unsigned middle = length / 2;
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
+    unsigned middle = length / 2;
     for (unsigned k = 0; k < middle; k++) {
         unsigned lk1 = length - k - 1;
         JSValue obj2 = getProperty(exec, thisObj, lk1);
@@ -395,108 +431,97 @@ JSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec, JSObject*, JSValue
         else
             thisObj->deleteProperty(exec, lk1);
     }
-    return thisObj;
+    return JSValue::encode(thisObj);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     JSValue result;
 
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
     if (length == 0) {
-        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length));
+        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
         result = jsUndefined();
     } else {
         result = thisObj->get(exec, 0);
-        for (unsigned k = 1; k < length; k++) {
-            if (JSValue obj = getProperty(exec, thisObj, k))
-                thisObj->put(exec, k - 1, obj);
-            else
-                thisObj->deleteProperty(exec, k - 1);
+        if (isJSArray(&exec->globalData(), thisObj))
+            ((JSArray *)thisObj)->shiftCount(exec, 1);
+        else {
+            for (unsigned k = 1; k < length; k++) {
+                if (JSValue obj = getProperty(exec, thisObj, k))
+                    thisObj->put(exec, k - 1, obj);
+                else
+                    thisObj->deleteProperty(exec, k - 1);
+            }
+            thisObj->deleteProperty(exec, length - 1);
         }
-        thisObj->deleteProperty(exec, length - 1);
-        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - 1));
+        putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - 1));
     }
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
 {
     // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
-
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
 
     // We return a new array
     JSArray* resObj = constructEmptyArray(exec);
     JSValue result = resObj;
-    double begin = args.at(0).toInteger(exec);
+
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    if (begin >= 0) {
-        if (begin > length)
-            begin = length;
-    } else {
-        begin += length;
-        if (begin < 0)
-            begin = 0;
-    }
-    double end;
-    if (args.at(1).isUndefined())
-        end = length;
-    else {
-        end = args.at(1).toInteger(exec);
-        if (end < 0) {
-            end += length;
-            if (end < 0)
-                end = 0;
-        } else {
-            if (end > length)
-                end = length;
-        }
-    }
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
+    unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
 
-    int n = 0;
-    int b = static_cast<int>(begin);
-    int e = static_cast<int>(end);
-    for (int k = b; k < e; k++, n++) {
+    unsigned n = 0;
+    for (unsigned k = begin; k < end; k++, n++) {
         if (JSValue v = getProperty(exec, thisObj, k))
             resObj->put(exec, n, v);
     }
     resObj->setLength(n);
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (!length || exec->hadException())
+        return JSValue::encode(thisObj);
 
-    JSValue function = args.at(0);
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
 
-    if (thisObj->classInfo() == &JSArray::info) {
+    if (thisObj->classInfo() == &JSArray::s_info) {
         if (isNumericCompareFunction(exec, callType, callData))
             asArray(thisObj)->sortNumeric(exec, function, callType, callData);
         else if (callType != CallTypeNone)
             asArray(thisObj)->sort(exec, function, callType, callData);
         else
             asArray(thisObj)->sort(exec);
-        return thisObj;
+        return JSValue::encode(thisObj);
     }
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-
-    if (!length)
-        return thisObj;
-
     // "Min" sort. Not the fastest, but definitely less code than heapsort
     // or quicksort, and much less swapping than bubblesort/insertionsort.
     for (unsigned i = 0; i < length - 1; ++i) {
         JSValue iObj = thisObj->get(exec, i);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         unsigned themin = i;
         JSValue minObj = iObj;
         for (unsigned j = i + 1; j < length; ++j) {
             JSValue jObj = thisObj->get(exec, j);
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
             double compareResult;
             if (jObj.isUndefined())
                 compareResult = 1; // don't check minObj because there's no need to differentiate == (0) from > (1)
@@ -521,118 +546,135 @@ JSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec, JSObject*, JSValue thi
             thisObj->put(exec, themin, iObj);
         }
     }
-    return thisObj;
+    return JSValue::encode(thisObj);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
-
     // 15.4.4.12
-    JSArray* resObj = constructEmptyArray(exec);
-    JSValue result = resObj;
-
-    // FIXME: Firefox returns an empty array.
-    if (!args.size())
-        return jsUndefined();
 
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    double relativeBegin = args.at(0).toInteger(exec);
-    unsigned begin;
-    if (relativeBegin < 0) {
-        relativeBegin += length;
-        begin = (relativeBegin < 0) ? 0 : static_cast<unsigned>(relativeBegin);
-    } else
-        begin = std::min<unsigned>(static_cast<unsigned>(relativeBegin), length);
-
-    unsigned deleteCount;
-    if (args.size() > 1)
-        deleteCount = std::min<int>(std::max<int>(args.at(1).toUInt32(exec), 0), length - begin);
-    else
-        deleteCount = length - begin;
-
-    for (unsigned k = 0; k < deleteCount; k++) {
-        if (JSValue v = getProperty(exec, thisObj, k + begin))
-            resObj->put(exec, k, v);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    if (!exec->argumentCount())
+        return JSValue::encode(constructEmptyArray(exec));
+
+    unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
+
+    unsigned deleteCount = length - begin;
+    if (exec->argumentCount() > 1) {
+        double deleteDouble = exec->argument(1).toInteger(exec);
+        if (deleteDouble < 0)
+            deleteCount = 0;
+        else if (deleteDouble > length - begin)
+            deleteCount = length - begin;
+        else
+            deleteCount = static_cast<unsigned>(deleteDouble);
     }
+
+    JSArray* resObj = new (exec) JSArray(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), deleteCount, CreateCompact);
+    JSValue result = resObj;
+    JSGlobalData& globalData = exec->globalData();
+    for (unsigned k = 0; k < deleteCount; k++)
+        resObj->uncheckedSetIndex(globalData, k, getProperty(exec, thisObj, k + begin));
+
     resObj->setLength(deleteCount);
 
-    unsigned additionalArgs = std::max<int>(args.size() - 2, 0);
+    unsigned additionalArgs = std::max<int>(exec->argumentCount() - 2, 0);
     if (additionalArgs != deleteCount) {
         if (additionalArgs < deleteCount) {
-            for (unsigned k = begin; k < length - deleteCount; ++k) {
-                if (JSValue v = getProperty(exec, thisObj, k + deleteCount))
-                    thisObj->put(exec, k + additionalArgs, v);
-                else
-                    thisObj->deleteProperty(exec, k + additionalArgs);
+            if ((!begin) && (isJSArray(&exec->globalData(), thisObj)))
+                ((JSArray *)thisObj)->shiftCount(exec, deleteCount - additionalArgs);
+            else {
+                for (unsigned k = begin; k < length - deleteCount; ++k) {
+                    if (JSValue v = getProperty(exec, thisObj, k + deleteCount))
+                        thisObj->put(exec, k + additionalArgs, v);
+                    else
+                        thisObj->deleteProperty(exec, k + additionalArgs);
+                }
+                for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
+                    thisObj->deleteProperty(exec, k - 1);
             }
-            for (unsigned k = length; k > length - deleteCount + additionalArgs; --k)
-                thisObj->deleteProperty(exec, k - 1);
         } else {
-            for (unsigned k = length - deleteCount; k > begin; --k) {
-                if (JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1))
-                    thisObj->put(exec, k + additionalArgs - 1, obj);
-                else
-                    thisObj->deleteProperty(exec, k + additionalArgs - 1);
+            if ((!begin) && (isJSArray(&exec->globalData(), thisObj)))
+                ((JSArray *)thisObj)->unshiftCount(exec, additionalArgs - deleteCount);
+            else {
+                for (unsigned k = length - deleteCount; k > begin; --k) {
+                    if (JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1))
+                        thisObj->put(exec, k + additionalArgs - 1, obj);
+                    else
+                        thisObj->deleteProperty(exec, k + additionalArgs - 1);
+                }
             }
         }
     }
     for (unsigned k = 0; k < additionalArgs; ++k)
-        thisObj->put(exec, k + begin, args.at(k + 2));
+        thisObj->put(exec, k + begin, exec->argument(k + 2));
 
-    putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(exec, length - deleteCount + additionalArgs));
-    return result;
+    putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length - deleteCount + additionalArgs));
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
-
     // 15.4.4.13
+
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    unsigned nrArgs = args.size();
-    if (nrArgs) {
-        for (unsigned k = length; k > 0; --k) {
-            if (JSValue v = getProperty(exec, thisObj, k - 1))
-                thisObj->put(exec, k + nrArgs - 1, v);
-            else
-                thisObj->deleteProperty(exec, k + nrArgs - 1);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    unsigned nrArgs = exec->argumentCount();
+    if ((nrArgs) && (length)) {
+        if (isJSArray(&exec->globalData(), thisObj))
+            ((JSArray *)thisObj)->unshiftCount(exec, nrArgs);
+        else {
+            for (unsigned k = length; k > 0; --k) {
+                if (JSValue v = getProperty(exec, thisObj, k - 1))
+                    thisObj->put(exec, k + nrArgs - 1, v);
+                else
+                    thisObj->deleteProperty(exec, k + nrArgs - 1);
+            }
         }
     }
     for (unsigned k = 0; k < nrArgs; ++k)
-        thisObj->put(exec, k, args.at(k));
-    JSValue result = jsNumber(exec, length + nrArgs);
+        thisObj->put(exec, k, exec->argument(k));
+    JSValue result = jsNumber(length + nrArgs);
     putProperty(exec, thisObj, exec->propertyNames().length, result);
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    JSValue function = args.at(0);
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
+    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
     JSArray* resultArray = constructEmptyArray(exec);
 
     unsigned filterIndex = 0;
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned k = 0;
     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
         JSFunction* f = asFunction(function);
         JSArray* array = asArray(thisObj);
-        CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+        CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
             if (!array->canGetIndex(k))
                 break;
             JSValue v = array->getIndex(k);
             cachedCall.setThis(applyThis);
             cachedCall.setArgument(0, v);
-            cachedCall.setArgument(1, jsNumber(exec, k));
+            cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
             
             JSValue result = cachedCall.call();
@@ -640,57 +682,57 @@ JSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec, JSObject*, JSValue t
                 resultArray->put(exec, filterIndex++, v);
         }
         if (k == length)
-            return resultArray;
+            return JSValue::encode(resultArray);
     }
     for (; k < length && !exec->hadException(); ++k) {
         PropertySlot slot(thisObj);
-
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
-
         JSValue v = slot.getValue(exec, k);
 
-        MarkedArgumentBuffer eachArguments;
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
+        MarkedArgumentBuffer eachArguments;
         eachArguments.append(v);
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
-
         if (result.toBoolean(exec))
             resultArray->put(exec, filterIndex++, v);
     }
-    return resultArray;
+    return JSValue::encode(resultArray);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    JSValue function = args.at(0);
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
-
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
 
     JSArray* resultArray = constructEmptyArray(exec, length);
     unsigned k = 0;
     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
         JSFunction* f = asFunction(function);
         JSArray* array = asArray(thisObj);
-        CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+        CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
             if (UNLIKELY(!array->canGetIndex(k)))
                 break;
 
             cachedCall.setThis(applyThis);
             cachedCall.setArgument(0, array->getIndex(k));
-            cachedCall.setArgument(1, jsNumber(exec, k));
+            cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
 
             resultArray->JSArray::put(exec, k, cachedCall.call());
@@ -700,20 +742,24 @@ JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue this
         PropertySlot slot(thisObj);
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
-
         JSValue v = slot.getValue(exec, k);
 
-        MarkedArgumentBuffer eachArguments;
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
+        MarkedArgumentBuffer eachArguments;
         eachArguments.append(v);
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
         resultArray->put(exec, k, result);
     }
 
-    return resultArray;
+    return JSValue::encode(resultArray);
 }
 
 // Documentation for these three is available at:
@@ -721,87 +767,91 @@ JSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec, JSObject*, JSValue this
 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
 // http://developer-test.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
 
-JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    JSValue function = args.at(0);
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
+    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
 
     JSValue result = jsBoolean(true);
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned k = 0;
     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
         JSFunction* f = asFunction(function);
         JSArray* array = asArray(thisObj);
-        CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+        CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
             if (UNLIKELY(!array->canGetIndex(k)))
                 break;
             
             cachedCall.setThis(applyThis);
             cachedCall.setArgument(0, array->getIndex(k));
-            cachedCall.setArgument(1, jsNumber(exec, k));
+            cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
             JSValue result = cachedCall.call();
             if (!result.toBoolean(cachedCall.newCallFrame(exec)))
-                return jsBoolean(false);
+                return JSValue::encode(jsBoolean(false));
         }
     }
     for (; k < length && !exec->hadException(); ++k) {
         PropertySlot slot(thisObj);
-
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
 
         MarkedArgumentBuffer eachArguments;
-
         eachArguments.append(slot.getValue(exec, k));
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
-        bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
+        bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
         if (!predicateResult) {
             result = jsBoolean(false);
             break;
         }
     }
 
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    JSValue function = args.at(0);
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
+    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned k = 0;
     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
         JSFunction* f = asFunction(function);
         JSArray* array = asArray(thisObj);
-        CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+        CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
             if (UNLIKELY(!array->canGetIndex(k)))
                 break;
 
             cachedCall.setThis(applyThis);
             cachedCall.setArgument(0, array->getIndex(k));
-            cachedCall.setArgument(1, jsNumber(exec, k));
+            cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
 
             cachedCall.call();
@@ -814,45 +864,50 @@ JSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec, JSObject*, JSValue
 
         MarkedArgumentBuffer eachArguments;
         eachArguments.append(slot.getValue(exec, k));
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
         call(exec, function, callType, callData, applyThis, eachArguments);
     }
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    JSValue function = args.at(0);
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSObject* applyThis = args.at(1).isUndefinedOrNull() ? exec->globalThisValue() : args.at(1).toObject(exec);
+    JSObject* applyThis = exec->argument(1).isUndefinedOrNull() ? exec->globalThisValue() : exec->argument(1).toObject(exec);
 
     JSValue result = jsBoolean(false);
 
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned k = 0;
     if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
         JSFunction* f = asFunction(function);
         JSArray* array = asArray(thisObj);
-        CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+        CachedCall cachedCall(exec, f, 3);
         for (; k < length && !exec->hadException(); ++k) {
             if (UNLIKELY(!array->canGetIndex(k)))
                 break;
             
             cachedCall.setThis(applyThis);
             cachedCall.setArgument(0, array->getIndex(k));
-            cachedCall.setArgument(1, jsNumber(exec, k));
+            cachedCall.setArgument(1, jsNumber(k));
             cachedCall.setArgument(2, thisObj);
             JSValue result = cachedCall.call();
             if (result.toBoolean(cachedCall.newCallFrame(exec)))
-                return jsBoolean(true);
+                return JSValue::encode(jsBoolean(true));
         }
     }
     for (; k < length && !exec->hadException(); ++k) {
@@ -862,40 +917,45 @@ JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thi
 
         MarkedArgumentBuffer eachArguments;
         eachArguments.append(slot.getValue(exec, k));
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
-        bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
+        bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments).toBoolean(exec);
         if (predicateResult) {
             result = jsBoolean(true);
             break;
         }
     }
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
-    
-    JSValue function = args.at(0);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
     unsigned i = 0;
     JSValue rv;
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    if (!length && args.size() == 1)
-        return throwError(exec, TypeError);
+    if (!length && exec->argumentCount() == 1)
+        return throwVMTypeError(exec);
+
     JSArray* array = 0;
     if (isJSArray(&exec->globalData(), thisObj))
         array = asArray(thisObj);
 
-    if (args.size() >= 2)
-        rv = args.at(1);
+    if (exec->argumentCount() >= 2)
+        rv = exec->argument(1);
     else if (array && array->canGetIndex(0)){
         rv = array->getIndex(0);
         i = 1;
@@ -906,12 +966,12 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue t
                 break;
         }
         if (!rv)
-            return throwError(exec, TypeError);
+            return throwVMTypeError(exec);
         i++;
     }
 
     if (callType == CallTypeJS && array) {
-        CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot());
+        CachedCall cachedCall(exec, asFunction(function), 4);
         for (; i < length && !exec->hadException(); ++i) {
             cachedCall.setThis(jsNull());
             cachedCall.setArgument(0, rv);
@@ -921,51 +981,56 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec, JSObject*, JSValue t
             else
                 break; // length has been made unsafe while we enumerate fallback to slow path
             cachedCall.setArgument(1, v);
-            cachedCall.setArgument(2, jsNumber(exec, i));
+            cachedCall.setArgument(2, jsNumber(i));
             cachedCall.setArgument(3, array);
             rv = cachedCall.call();
         }
         if (i == length) // only return if we reached the end of the array
-            return rv;
+            return JSValue::encode(rv);
     }
 
     for (; i < length && !exec->hadException(); ++i) {
         JSValue prop = getProperty(exec, thisObj, i);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         if (!prop)
             continue;
         
         MarkedArgumentBuffer eachArguments;
         eachArguments.append(rv);
         eachArguments.append(prop);
-        eachArguments.append(jsNumber(exec, i));
+        eachArguments.append(jsNumber(i));
         eachArguments.append(thisObj);
         
         rv = call(exec, function, callType, callData, jsNull(), eachArguments);
     }
-    return rv;
+    return JSValue::encode(rv);
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
-    
-    JSValue function = args.at(0);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue function = exec->argument(0);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
     
     unsigned i = 0;
     JSValue rv;
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    if (!length && args.size() == 1)
-        return throwError(exec, TypeError);
+    if (!length && exec->argumentCount() == 1)
+        return throwVMTypeError(exec);
+
     JSArray* array = 0;
     if (isJSArray(&exec->globalData(), thisObj))
         array = asArray(thisObj);
     
-    if (args.size() >= 2)
-        rv = args.at(1);
+    if (exec->argumentCount() >= 2)
+        rv = exec->argument(1);
     else if (array && array->canGetIndex(length - 1)){
         rv = array->getIndex(length - 1);
         i = 1;
@@ -976,12 +1041,12 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSVa
                 break;
         }
         if (!rv)
-            return throwError(exec, TypeError);
+            return throwVMTypeError(exec);
         i++;
     }
     
     if (callType == CallTypeJS && array) {
-        CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot());
+        CachedCall cachedCall(exec, asFunction(function), 4);
         for (; i < length && !exec->hadException(); ++i) {
             unsigned idx = length - i - 1;
             cachedCall.setThis(jsNull());
@@ -989,91 +1054,86 @@ JSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec, JSObject*, JSVa
             if (UNLIKELY(!array->canGetIndex(idx)))
                 break; // length has been made unsafe while we enumerate fallback to slow path
             cachedCall.setArgument(1, array->getIndex(idx));
-            cachedCall.setArgument(2, jsNumber(exec, idx));
+            cachedCall.setArgument(2, jsNumber(idx));
             cachedCall.setArgument(3, array);
             rv = cachedCall.call();
         }
         if (i == length) // only return if we reached the end of the array
-            return rv;
+            return JSValue::encode(rv);
     }
     
     for (; i < length && !exec->hadException(); ++i) {
         unsigned idx = length - i - 1;
         JSValue prop = getProperty(exec, thisObj, idx);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
         if (!prop)
             continue;
         
         MarkedArgumentBuffer eachArguments;
         eachArguments.append(rv);
         eachArguments.append(prop);
-        eachArguments.append(jsNumber(exec, idx));
+        eachArguments.append(jsNumber(idx));
         eachArguments.append(thisObj);
         
         rv = call(exec, function, callType, callData, jsNull(), eachArguments);
     }
-    return rv;        
+    return JSValue::encode(rv);        
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 {
-    // JavaScript 1.5 Extension by Mozilla
-    // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
-
-    JSObject* thisObj = thisValue.toThisObject(exec);
-
-    unsigned index = 0;
-    double d = args.at(1).toInteger(exec);
+    // 15.4.4.14
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    if (d < 0)
-        d += length;
-    if (d > 0) {
-        if (d > length)
-            index = length;
-        else
-            index = static_cast<unsigned>(d);
-    }
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
 
-    JSValue searchElement = args.at(0);
+    unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
+    JSValue searchElement = exec->argument(0);
     for (; index < length; ++index) {
         JSValue e = getProperty(exec, thisObj, index);
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
-            return jsNumber(exec, index);
+            return JSValue::encode(jsNumber(index));
     }
 
-    return jsNumber(exec, -1);
+    return JSValue::encode(jsNumber(-1));
 }
 
-JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
 {
-    // JavaScript 1.6 Extension by Mozilla
-    // Documentation: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
-
-    JSObject* thisObj = thisValue.toThisObject(exec);
-
+    // 15.4.4.15
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
-    int index = length - 1;
-    double d = args.at(1).toIntegerPreserveNaN(exec);
-
-    if (d < 0) {
-        d += length;
-        if (d < 0)
-            return jsNumber(exec, -1);
+    if (!length)
+        return JSValue::encode(jsNumber(-1));
+
+    unsigned index = length - 1;
+    JSValue fromValue = exec->argument(1);
+    if (!fromValue.isUndefined()) {
+        double fromDouble = fromValue.toInteger(exec);
+        if (fromDouble < 0) {
+            fromDouble += length;
+            if (fromDouble < 0)
+                return JSValue::encode(jsNumber(-1));
+        }
+        if (fromDouble < length)
+            index = static_cast<unsigned>(fromDouble);
     }
-    if (d < length)
-        index = static_cast<int>(d);
 
-    JSValue searchElement = args.at(0);
-    for (; index >= 0; --index) {
+    JSValue searchElement = exec->argument(0);
+    do {
+        ASSERT(index < length);
         JSValue e = getProperty(exec, thisObj, index);
         if (!e)
             continue;
         if (JSValue::strictEqual(exec, searchElement, e))
-            return jsNumber(exec, index);
-    }
+            return JSValue::encode(jsNumber(index));
+    } while (index--);
 
-    return jsNumber(exec, -1);
+    return JSValue::encode(jsNumber(-1));
 }
 
 } // namespace JSC
index e52914c2f2aa9132d5d7ef8b4fda318439016672..bbc170ca76af4ba94d9c75e2cc3950606aa28db8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -28,13 +28,20 @@ namespace JSC {
 
     class ArrayPrototype : public JSArray {
     public:
-        explicit ArrayPrototype(NonNullPassRefPtr<Structure>);
+        explicit ArrayPrototype(JSGlobalObject*, Structure*);
 
         bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned AnonymousSlotCount = JSArray::AnonymousSlotCount + 1;
     };
 
 } // namespace JSC
index 74089a53b9129c186839abb9625092c7215c7d99..610b8d16cb8a89cdb874cb39972663df63f3d0a8 100644 (file)
 #ifndef BatchedTransitionOptimizer_h
 #define BatchedTransitionOptimizer_h
 
-#include <wtf/Noncopyable.h>
 #include "JSObject.h"
 
 namespace JSC {
 
-    class BatchedTransitionOptimizer : public Noncopyable {
+    class BatchedTransitionOptimizer {
+        WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer);
     public:
-        BatchedTransitionOptimizer(JSObject* object)
-            : m_object(object)
+        BatchedTransitionOptimizer(JSGlobalData& globalData, JSObject* object)
+            : m_globalData(&globalData)
+            , m_object(object)
         {
-            if (!m_object->structure()->isDictionary())
-                m_object->setStructure(Structure::toCacheableDictionaryTransition(m_object->structure()));
         }
 
         ~BatchedTransitionOptimizer()
         {
-            m_object->flattenDictionaryObject();
+            if (m_object->structure()->isDictionary())
+                m_object->flattenDictionaryObject(*m_globalData);
         }
 
     private:
+        JSGlobalData* m_globalData;
         JSObject* m_object;
     };
 
index b0d8df38ea5dfecd9f0e04aa4ca498e3057e91b9..a1a4ed48bfb2c8ddb6ea881cbe79157bb8025b0e 100644 (file)
@@ -28,26 +28,27 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
 
-BooleanConstructor::BooleanConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className))
+BooleanConstructor::BooleanConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, BooleanPrototype* booleanPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, booleanPrototype->classInfo()->className))
 {
-    putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
 }
 
 // ECMA 15.6.2
 JSObject* constructBoolean(ExecState* exec, const ArgList& args)
 {
-    BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
-    obj->setInternalValue(jsBoolean(args.at(0).toBoolean(exec)));
+    BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->booleanObjectStructure());
+    obj->setInternalValue(exec->globalData(), jsBoolean(args.at(0).toBoolean(exec)));
     return obj;
 }
 
-static JSObject* constructWithBooleanConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithBooleanConstructor(ExecState* exec)
 {
-    return constructBoolean(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructBoolean(exec, args));
 }
 
 ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
@@ -57,9 +58,9 @@ ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.6.1
-static JSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callBooleanConstructor(ExecState* exec)
 {
-    return jsBoolean(args.at(0).toBoolean(exec));
+    return JSValue::encode(jsBoolean(exec->argument(0).toBoolean(exec)));
 }
 
 CallType BooleanConstructor::getCallData(CallData& callData)
@@ -68,10 +69,10 @@ CallType BooleanConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
-JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSValue immediateBooleanValue)
+JSObject* constructBooleanFromImmediateBoolean(ExecState* exec, JSGlobalObject* globalObject, JSValue immediateBooleanValue)
 {
-    BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
-    obj->setInternalValue(immediateBooleanValue);
+    BooleanObject* obj = new (exec) BooleanObject(exec->globalData(), globalObject->booleanObjectStructure());
+    obj->setInternalValue(exec->globalData(), immediateBooleanValue);
     return obj;
 }
 
index 1d8a26a57009b5bcaecd094ccd2bd31f4ab3acb5..fa0d05e5887f10126961f13ac2e811153884222f 100644 (file)
@@ -29,14 +29,14 @@ namespace JSC {
 
     class BooleanConstructor : public InternalFunction {
     public:
-        BooleanConstructor(ExecState*, NonNullPassRefPtr<Structure>, BooleanPrototype*);
+        BooleanConstructor(ExecState*, JSGlobalObject*, Structure*, BooleanPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
-    JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSValue);
+    JSObject* constructBooleanFromImmediateBoolean(ExecState*, JSGlobalObject*, JSValue);
     JSObject* constructBoolean(ExecState*, const ArgList&);
 
 } // namespace JSC
index c9b3846597e68a1824f197577807a7772edad283..e24a30a4bb54ae500ed0e9d7165fc9ce7a5d9a63 100644 (file)
@@ -25,11 +25,12 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
 
-const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 };
+const ClassInfo BooleanObject::s_info = { "Boolean", &JSWrapperObject::s_info, 0, 0 };
 
-BooleanObject::BooleanObject(NonNullPassRefPtr<Structure> structure)
-    : JSWrapperObject(structure)
+BooleanObject::BooleanObject(JSGlobalData& globalData, Structure* structure)
+    : JSWrapperObject(globalData, structure)
 {
+    ASSERT(inherits(&s_info));
 }
 
 } // namespace JSC
index 4b02acb1dc9503d9b0b77be650187eabb131c702..def44b44dcd84fce03269190ff67cabb500272b2 100644 (file)
@@ -27,14 +27,13 @@ namespace JSC {
 
     class BooleanObject : public JSWrapperObject {
     public:
-        explicit BooleanObject(NonNullPassRefPtr<Structure>);
+        explicit BooleanObject(JSGlobalData&, Structure*);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static const ClassInfo s_info;
         
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
     };
 
@@ -42,7 +41,7 @@ namespace JSC {
 
     inline BooleanObject* asBooleanObject(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&BooleanObject::info));
+        ASSERT(asObject(value)->inherits(&BooleanObject::s_info));
         return static_cast<BooleanObject*>(asObject(value));
     }
 
index 8d338f9c3bf37eba25bbbfdae75d82699c0fe898..dd0194f3f5d092b08eac266ea96995d5b6310f1b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include "BooleanPrototype.h"
 
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
-ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+static EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*);
+
+}
+
+#include "BooleanPrototype.lut.h"
+
+namespace JSC {
 
-// Functions
-static JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
+const ClassInfo BooleanPrototype::s_info = { "Boolean", &BooleanObject::s_info, 0, ExecState::booleanPrototypeTable };
 
-// ECMA 15.6.4
+/* Source for BooleanPrototype.lut.h
+@begin booleanPrototypeTable
+  toString  booleanProtoFuncToString    DontEnum|Function 0
+  valueOf   booleanProtoFuncValueOf     DontEnum|Function 0
+@end
+*/
 
-BooleanPrototype::BooleanPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
-    : BooleanObject(structure)
+ASSERT_CLASS_FITS_IN_CELL(BooleanPrototype);
+
+BooleanPrototype::BooleanPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+    : BooleanObject(exec->globalData(), structure)
 {
-    setInternalValue(jsBoolean(false));
+    setInternalValue(exec->globalData(), jsBoolean(false));
 
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, booleanProtoFuncToString), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, booleanProtoFuncValueOf), DontEnum);
+    ASSERT(inherits(&s_info));
+    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
+bool BooleanPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<BooleanObject>(exec, ExecState::booleanPrototypeTable(exec), this, propertyName, slot);
+}
 
-// ------------------------------ Functions --------------------------
+bool BooleanPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<BooleanObject>(exec, ExecState::booleanPrototypeTable(exec), this, propertyName, descriptor);
+}
 
-// ECMA 15.6.4.2 + 15.6.4.3
+// ------------------------------ Functions ---------------------------
 
-JSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     if (thisValue == jsBoolean(false))
-        return jsNontrivialString(exec, "false");
+        return JSValue::encode(jsNontrivialString(exec, "false"));
 
     if (thisValue == jsBoolean(true))
-        return jsNontrivialString(exec, "true");
+        return JSValue::encode(jsNontrivialString(exec, "true"));
 
-    if (!thisValue.inherits(&BooleanObject::info))
-        return throwError(exec, TypeError);
+    if (!thisValue.inherits(&BooleanObject::s_info))
+        return throwVMTypeError(exec);
 
     if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
-        return jsNontrivialString(exec, "false");
+        return JSValue::encode(jsNontrivialString(exec, "false"));
 
     ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
-    return jsNontrivialString(exec, "true");
+    return JSValue::encode(jsNontrivialString(exec, "true"));
 }
 
-JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     if (thisValue.isBoolean())
-        return thisValue;
+        return JSValue::encode(thisValue);
 
-    if (!thisValue.inherits(&BooleanObject::info))
-        return throwError(exec, TypeError);
+    if (!thisValue.inherits(&BooleanObject::s_info))
+        return throwVMTypeError(exec);
 
-    return asBooleanObject(thisValue)->internalValue();
+    return JSValue::encode(asBooleanObject(thisValue)->internalValue());
 }
 
 } // namespace JSC
index cc69b3f00c699d99075232172c5a87914298d6de..2341c1147a4384d6ae8ab5d2b3a0fe56639ce009 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,22 @@ namespace JSC {
 
     class BooleanPrototype : public BooleanObject {
     public:
-        BooleanPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        BooleanPrototype(ExecState*, JSGlobalObject*, Structure*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | BooleanObject::StructureFlags;
+        static const unsigned AnonymousSlotCount = BooleanObject::AnonymousSlotCount + 1;
+
+    private:
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
index 04f7f62af06805d706be003762152f20c0e4c49e..67c7af8b9405df1435bc7ee45db737932eb8249d 100644 (file)
@@ -56,18 +56,18 @@ public:
             fastFree(m_cache);
     }
 
-    JSValue operator() (ExecState* exec, double operand)
+    JSValue operator() (double operand)
     {
         if (UNLIKELY(!m_cache))
             initialize();
         CacheEntry* entry = &m_cache[hash(operand)];
 
         if (entry->operand == operand)
-            return jsDoubleNumber(exec, entry->result);
+            return jsDoubleNumber(entry->result);
         double result = orignalFunction(operand);
         entry->operand = operand;
         entry->result = result;
-        return jsDoubleNumber(exec, result);
+        return jsDoubleNumber(result);
     }
 
 private:
index 62e42fef5ca59d78190167382c42109179b26900..018e2ca34b516be6bc691d31fac9a91f17c707e1 100644 (file)
 #include "config.h"
 #include "CallData.h"
 
+#include "Executable.h"
+#include "Interpreter.h"
 #include "JSFunction.h"
 
 namespace JSC {
 
 JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
-    if (callType == CallTypeHost)
-        return callData.native.function(exec, asObject(functionObject), thisValue, args);
-    ASSERT(callType == CallTypeJS);
-    // FIXME: Can this be done more efficiently using the callData?
-    return asFunction(functionObject)->call(exec, thisValue, args);
+    ASSERT(callType == CallTypeJS || callType == CallTypeHost);
+    return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args);
 }
 
 } // namespace JSC
index 24c19f91dbdf7f4c216ef71fe3a665f4a8d403d7..b138f548405c24fa3c59f15838f90864f6b53fe7 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef CallData_h
 #define CallData_h
 
-#include "NativeFunctionWrapper.h"
+#include "JSValue.h"
 
 namespace JSC {
 
@@ -37,7 +37,6 @@ namespace JSC {
     class ExecState;
     class FunctionExecutable;
     class JSObject;
-    class JSValue;
     class ScopeChainNode;
 
     enum CallType {
@@ -46,7 +45,7 @@ namespace JSC {
         CallTypeJS
     };
 
-    typedef JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*, JSObject*, JSValue thisValue, const ArgList&);
+    typedef EncodedJSValue (JSC_HOST_CALL *NativeFunction)(ExecState*);
 
     union CallData {
         struct {
diff --git a/runtime/Collector.cpp b/runtime/Collector.cpp
deleted file mode 100644 (file)
index 2789e50..0000000
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#include "config.h"
-#include "Collector.h"
-
-#include "ArgList.h"
-#include "CallFrame.h"
-#include "CodeBlock.h"
-#include "CollectorHeapIterator.h"
-#include "Interpreter.h"
-#include "JSArray.h"
-#include "JSGlobalObject.h"
-#include "JSLock.h"
-#include "JSONObject.h"
-#include "JSString.h"
-#include "JSValue.h"
-#include "JSZombie.h"
-#include "MarkStack.h"
-#include "Nodes.h"
-#include "Tracing.h"
-#include <algorithm>
-#include <limits.h>
-#include <setjmp.h>
-#include <stdlib.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/UnusedParam.h>
-#include <wtf/VMTags.h>
-
-#if OS(DARWIN)
-
-#include <mach/mach_init.h>
-#include <mach/mach_port.h>
-#include <mach/task.h>
-#include <mach/thread_act.h>
-#include <mach/vm_map.h>
-
-#elif OS(WINDOWS)
-
-#include <windows.h>
-#include <malloc.h>
-
-#elif OS(HAIKU)
-
-#include <OS.h>
-
-#elif OS(UNIX)
-
-#include <stdlib.h>
-#if !OS(HAIKU)
-#include <sys/mman.h>
-#endif
-#include <unistd.h>
-
-#if OS(SOLARIS)
-#include <thread.h>
-#else
-#include <pthread.h>
-#endif
-
-#if HAVE(PTHREAD_NP_H)
-#include <pthread_np.h>
-#endif
-
-#if OS(QNX)
-#include <fcntl.h>
-#include <sys/procfs.h>
-#include <stdio.h>
-#include <errno.h>
-#endif
-
-#endif
-
-#define COLLECT_ON_EVERY_ALLOCATION 0
-
-using std::max;
-
-namespace JSC {
-
-// tunable parameters
-
-const size_t GROWTH_FACTOR = 2;
-const size_t LOW_WATER_FACTOR = 4;
-const size_t ALLOCATIONS_PER_COLLECTION = 3600;
-// This value has to be a macro to be used in max() without introducing
-// a PIC branch in Mach-O binaries, see <rdar://problem/5971391>.
-#define MIN_ARRAY_SIZE (static_cast<size_t>(14))
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-#if OS(DARWIN)
-typedef mach_port_t PlatformThread;
-#elif OS(WINDOWS)
-typedef HANDLE PlatformThread;
-#endif
-
-class Heap::Thread {
-public:
-    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
-        : posixThread(pthread)
-        , platformThread(platThread)
-        , stackBase(base)
-    {
-    }
-
-    Thread* next;
-    pthread_t posixThread;
-    PlatformThread platformThread;
-    void* stackBase;
-};
-
-#endif
-
-Heap::Heap(JSGlobalData* globalData)
-    : m_markListSet(0)
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    , m_registeredThreads(0)
-    , m_currentThreadRegistrar(0)
-#endif
-#if OS(SYMBIAN)
-    , m_blockallocator(JSCCOLLECTOR_VIRTUALMEM_RESERVATION, BLOCK_SIZE)
-#endif
-    , m_globalData(globalData)
-{
-    ASSERT(globalData);
-    memset(&m_heap, 0, sizeof(CollectorHeap));
-    allocateBlock();
-}
-
-Heap::~Heap()
-{
-    // The destroy function must already have been called, so assert this.
-    ASSERT(!m_globalData);
-}
-
-void Heap::destroy()
-{
-    JSLock lock(SilenceAssertionsOnly);
-
-    if (!m_globalData)
-        return;
-
-    ASSERT(!m_globalData->dynamicGlobalObject);
-    ASSERT(!isBusy());
-    
-    // The global object is not GC protected at this point, so sweeping may delete it
-    // (and thus the global data) before other objects that may use the global data.
-    RefPtr<JSGlobalData> protect(m_globalData);
-
-    delete m_markListSet;
-    m_markListSet = 0;
-
-    freeBlocks();
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    if (m_currentThreadRegistrar) {
-        int error = pthread_key_delete(m_currentThreadRegistrar);
-        ASSERT_UNUSED(error, !error);
-    }
-
-    MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
-    for (Heap::Thread* t = m_registeredThreads; t;) {
-        Heap::Thread* next = t->next;
-        delete t;
-        t = next;
-    }
-#endif
-#if OS(SYMBIAN)
-    m_blockallocator.destroy();
-#endif
-    m_globalData = 0;
-}
-
-NEVER_INLINE CollectorBlock* Heap::allocateBlock()
-{
-#if OS(DARWIN)
-    vm_address_t address = 0;
-    vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
-#elif OS(SYMBIAN)
-    void* address = m_blockallocator.alloc();  
-    if (!address)
-        CRASH();
-#elif OS(WINCE)
-    void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-#elif OS(WINDOWS)
-#if COMPILER(MINGW) && !COMPILER(MINGW64)
-    void* address = __mingw_aligned_malloc(BLOCK_SIZE, BLOCK_SIZE);
-#else
-    void* address = _aligned_malloc(BLOCK_SIZE, BLOCK_SIZE);
-#endif
-    memset(address, 0, BLOCK_SIZE);
-#elif HAVE(POSIX_MEMALIGN)
-    void* address;
-    posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE);
-#else
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#error Need to initialize pagesize safely.
-#endif
-    static size_t pagesize = getpagesize();
-
-    size_t extra = 0;
-    if (BLOCK_SIZE > pagesize)
-        extra = BLOCK_SIZE - pagesize;
-
-    void* mmapResult = mmap(NULL, BLOCK_SIZE + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-    uintptr_t address = reinterpret_cast<uintptr_t>(mmapResult);
-
-    size_t adjust = 0;
-    if ((address & BLOCK_OFFSET_MASK) != 0)
-        adjust = BLOCK_SIZE - (address & BLOCK_OFFSET_MASK);
-
-    if (adjust > 0)
-        munmap(reinterpret_cast<char*>(address), adjust);
-
-    if (adjust < extra)
-        munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust);
-
-    address += adjust;
-#endif
-
-    // Initialize block.
-
-    CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address);
-    block->heap = this;
-    clearMarkBits(block);
-
-    Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
-    for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i)
-        new (block->cells + i) JSCell(dummyMarkableCellStructure);
-    
-    // Add block to blocks vector.
-
-    size_t numBlocks = m_heap.numBlocks;
-    if (m_heap.usedBlocks == numBlocks) {
-        static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
-        if (numBlocks > maxNumBlocks)
-            CRASH();
-        numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
-        m_heap.numBlocks = numBlocks;
-        m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, numBlocks * sizeof(CollectorBlock*)));
-    }
-    m_heap.blocks[m_heap.usedBlocks++] = block;
-
-    return block;
-}
-
-NEVER_INLINE void Heap::freeBlock(size_t block)
-{
-    m_heap.didShrink = true;
-
-    ObjectIterator it(m_heap, block);
-    ObjectIterator end(m_heap, block + 1);
-    for ( ; it != end; ++it)
-        (*it)->~JSCell();
-    freeBlockPtr(m_heap.blocks[block]);
-
-    // swap with the last block so we compact as we go
-    m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1];
-    m_heap.usedBlocks--;
-
-    if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) {
-        m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; 
-        m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(CollectorBlock*)));
-    }
-}
-
-NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block)
-{
-#if OS(DARWIN)    
-    vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE);
-#elif OS(SYMBIAN)
-    m_blockallocator.free(reinterpret_cast<void*>(block));
-#elif OS(WINCE)
-    VirtualFree(block, 0, MEM_RELEASE);
-#elif OS(WINDOWS)
-#if COMPILER(MINGW) && !COMPILER(MINGW64)
-    __mingw_aligned_free(block);
-#else
-    _aligned_free(block);
-#endif
-#elif HAVE(POSIX_MEMALIGN)
-    free(block);
-#else
-    munmap(reinterpret_cast<char*>(block), BLOCK_SIZE);
-#endif
-}
-
-void Heap::freeBlocks()
-{
-    ProtectCountSet protectedValuesCopy = m_protectedValues;
-
-    clearMarkBits();
-    ProtectCountSet::iterator protectedValuesEnd = protectedValuesCopy.end();
-    for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it)
-        markCell(it->first);
-
-    m_heap.nextCell = 0;
-    m_heap.nextBlock = 0;
-    DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell);
-    DeadObjectIterator end(m_heap, m_heap.usedBlocks);
-    for ( ; it != end; ++it)
-        (*it)->~JSCell();
-
-    ASSERT(!protectedObjectCount());
-
-    protectedValuesEnd = protectedValuesCopy.end();
-    for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it)
-        it->first->~JSCell();
-
-    for (size_t block = 0; block < m_heap.usedBlocks; ++block)
-        freeBlockPtr(m_heap.blocks[block]);
-
-    fastFree(m_heap.blocks);
-
-    memset(&m_heap, 0, sizeof(CollectorHeap));
-}
-
-void Heap::recordExtraCost(size_t cost)
-{
-    // Our frequency of garbage collection tries to balance memory use against speed
-    // by collecting based on the number of newly created values. However, for values
-    // that hold on to a great deal of memory that's not in the form of other JS values,
-    // that is not good enough - in some cases a lot of those objects can pile up and
-    // use crazy amounts of memory without a GC happening. So we track these extra
-    // memory costs. Only unusually large objects are noted, and we only keep track
-    // of this extra cost until the next GC. In garbage collected languages, most values
-    // are either very short lived temporaries, or have extremely long lifetimes. So
-    // if a large value survives one garbage collection, there is not much point to
-    // collecting more frequently as long as it stays alive.
-
-    if (m_heap.extraCost > maxExtraCost && m_heap.extraCost > m_heap.usedBlocks * BLOCK_SIZE / 2) {
-        // If the last iteration through the heap deallocated blocks, we need
-        // to clean up remaining garbage before marking. Otherwise, the conservative
-        // marking mechanism might follow a pointer to unmapped memory.
-        if (m_heap.didShrink)
-            sweep();
-        reset();
-    }
-    m_heap.extraCost += cost;
-}
-
-void* Heap::allocate(size_t s)
-{
-    typedef HeapConstants::Block Block;
-    typedef HeapConstants::Cell Cell;
-    
-    ASSERT(JSLock::lockCount() > 0);
-    ASSERT(JSLock::currentThreadIsHoldingLock());
-    ASSERT_UNUSED(s, s <= HeapConstants::cellSize);
-
-    ASSERT(m_heap.operationInProgress == NoOperation);
-
-#if COLLECT_ON_EVERY_ALLOCATION
-    collectAllGarbage();
-    ASSERT(m_heap.operationInProgress == NoOperation);
-#endif
-
-allocate:
-
-    // Fast case: find the next garbage cell and recycle it.
-
-    do {
-        ASSERT(m_heap.nextBlock < m_heap.usedBlocks);
-        Block* block = reinterpret_cast<Block*>(m_heap.blocks[m_heap.nextBlock]);
-        do {
-            ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock);
-            if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block
-                Cell* cell = block->cells + m_heap.nextCell;
-
-                m_heap.operationInProgress = Allocation;
-                JSCell* imp = reinterpret_cast<JSCell*>(cell);
-                imp->~JSCell();
-                m_heap.operationInProgress = NoOperation;
-
-                ++m_heap.nextCell;
-                return cell;
-            }
-        } while (++m_heap.nextCell != HeapConstants::cellsPerBlock);
-        m_heap.nextCell = 0;
-    } while (++m_heap.nextBlock != m_heap.usedBlocks);
-
-    // Slow case: reached the end of the heap. Mark live objects and start over.
-
-    reset();
-    goto allocate;
-}
-
-void Heap::resizeBlocks()
-{
-    m_heap.didShrink = false;
-
-    size_t usedCellCount = markedCells();
-    size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount);
-    size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
-
-    size_t maxCellCount = 1.25f * minCellCount;
-    size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
-
-    if (m_heap.usedBlocks < minBlockCount)
-        growBlocks(minBlockCount);
-    else if (m_heap.usedBlocks > maxBlockCount)
-        shrinkBlocks(maxBlockCount);
-}
-
-void Heap::growBlocks(size_t neededBlocks)
-{
-    ASSERT(m_heap.usedBlocks < neededBlocks);
-    while (m_heap.usedBlocks < neededBlocks)
-        allocateBlock();
-}
-
-void Heap::shrinkBlocks(size_t neededBlocks)
-{
-    ASSERT(m_heap.usedBlocks > neededBlocks);
-    
-    // Clear the always-on last bit, so isEmpty() isn't fooled by it.
-    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
-        m_heap.blocks[i]->marked.clear(HeapConstants::cellsPerBlock - 1);
-
-    for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) {
-        if (m_heap.blocks[i]->marked.isEmpty()) {
-            freeBlock(i);
-        } else
-            ++i;
-    }
-
-    // Reset the always-on last bit.
-    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
-        m_heap.blocks[i]->marked.set(HeapConstants::cellsPerBlock - 1);
-}
-
-#if OS(WINCE)
-JS_EXPORTDATA void* g_stackBase = 0;
-
-inline bool isPageWritable(void* page)
-{
-    MEMORY_BASIC_INFORMATION memoryInformation;
-    DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
-
-    // return false on error, including ptr outside memory
-    if (result != sizeof(memoryInformation))
-        return false;
-
-    DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
-    return protect == PAGE_READWRITE
-        || protect == PAGE_WRITECOPY
-        || protect == PAGE_EXECUTE_READWRITE
-        || protect == PAGE_EXECUTE_WRITECOPY;
-}
-
-static void* getStackBase(void* previousFrame)
-{
-    // find the address of this stack frame by taking the address of a local variable
-    bool isGrowingDownward;
-    void* thisFrame = (void*)(&isGrowingDownward);
-
-    isGrowingDownward = previousFrame < &thisFrame;
-    static DWORD pageSize = 0;
-    if (!pageSize) {
-        SYSTEM_INFO systemInfo;
-        GetSystemInfo(&systemInfo);
-        pageSize = systemInfo.dwPageSize;
-    }
-
-    // scan all of memory starting from this frame, and return the last writeable page found
-    register char* currentPage = (char*)((DWORD)thisFrame & ~(pageSize - 1));
-    if (isGrowingDownward) {
-        while (currentPage > 0) {
-            // check for underflow
-            if (currentPage >= (char*)pageSize)
-                currentPage -= pageSize;
-            else
-                currentPage = 0;
-            if (!isPageWritable(currentPage))
-                return currentPage + pageSize;
-        }
-        return 0;
-    } else {
-        while (true) {
-            // guaranteed to complete because isPageWritable returns false at end of memory
-            currentPage += pageSize;
-            if (!isPageWritable(currentPage))
-                return currentPage;
-        }
-    }
-}
-#endif
-
-#if OS(QNX)
-static inline void *currentThreadStackBaseQNX()
-{
-    static void* stackBase = 0;
-    static size_t stackSize = 0;
-    static pthread_t stackThread;
-    pthread_t thread = pthread_self();
-    if (stackBase == 0 || thread != stackThread) {
-        struct _debug_thread_info threadInfo;
-        memset(&threadInfo, 0, sizeof(threadInfo));
-        threadInfo.tid = pthread_self();
-        int fd = open("/proc/self", O_RDONLY);
-        if (fd == -1) {
-            LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);
-            return 0;
-        }
-        devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
-        close(fd);
-        stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
-        stackSize = threadInfo.stksize;
-        ASSERT(stackBase);
-        stackThread = thread;
-    }
-    return static_cast<char*>(stackBase) + stackSize;
-}
-#endif
-
-static inline void* currentThreadStackBase()
-{
-#if OS(DARWIN)
-    pthread_t thread = pthread_self();
-    return pthread_get_stackaddr_np(thread);
-#elif OS(WINDOWS) && CPU(X86) && COMPILER(MSVC)
-    // offset 0x18 from the FS segment register gives a pointer to
-    // the thread information block for the current thread
-    NT_TIB* pTib;
-    __asm {
-        MOV EAX, FS:[18h]
-        MOV pTib, EAX
-    }
-    return static_cast<void*>(pTib->StackBase);
-#elif OS(WINDOWS) && CPU(X86) && COMPILER(GCC)
-    // offset 0x18 from the FS segment register gives a pointer to
-    // the thread information block for the current thread
-    NT_TIB* pTib;
-    asm ( "movl %%fs:0x18, %0\n"
-          : "=r" (pTib)
-        );
-    return static_cast<void*>(pTib->StackBase);
-#elif OS(WINDOWS) && CPU(X86_64)
-    PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
-    return reinterpret_cast<void*>(pTib->StackBase);
-#elif OS(QNX)
-    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
-    MutexLocker locker(mutex);
-    return currentThreadStackBaseQNX();
-#elif OS(SOLARIS)
-    stack_t s;
-    thr_stksegment(&s);
-    return s.ss_sp;
-#elif OS(OPENBSD)
-    pthread_t thread = pthread_self();
-    stack_t stack;
-    pthread_stackseg_np(thread, &stack);
-    return stack.ss_sp;
-#elif OS(SYMBIAN)
-    TThreadStackInfo info;
-    RThread thread;
-    thread.StackInfo(info);
-    return (void*)info.iBase;
-#elif OS(HAIKU)
-    thread_info threadInfo;
-    get_thread_info(find_thread(NULL), &threadInfo);
-    return threadInfo.stack_end;
-#elif OS(UNIX)
-    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
-    MutexLocker locker(mutex);
-    static void* stackBase = 0;
-    static size_t stackSize = 0;
-    static pthread_t stackThread;
-    pthread_t thread = pthread_self();
-    if (stackBase == 0 || thread != stackThread) {
-        pthread_attr_t sattr;
-        pthread_attr_init(&sattr);
-#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
-        // e.g. on FreeBSD 5.4, neundorf@kde.org
-        pthread_attr_get_np(thread, &sattr);
-#else
-        // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
-        pthread_getattr_np(thread, &sattr);
-#endif
-        int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
-        (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
-        ASSERT(stackBase);
-        pthread_attr_destroy(&sattr);
-        stackThread = thread;
-    }
-    return static_cast<char*>(stackBase) + stackSize;
-#elif OS(WINCE)
-    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
-    MutexLocker locker(mutex);
-    if (g_stackBase)
-        return g_stackBase;
-    else {
-        int dummy;
-        return getStackBase(&dummy);
-    }
-#else
-#error Need a way to get the stack base on this platform
-#endif
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline PlatformThread getCurrentPlatformThread()
-{
-#if OS(DARWIN)
-    return pthread_mach_thread_np(pthread_self());
-#elif OS(WINDOWS)
-    return pthread_getw32threadhandle_np(pthread_self());
-#endif
-}
-
-void Heap::makeUsableFromMultipleThreads()
-{
-    if (m_currentThreadRegistrar)
-        return;
-
-    int error = pthread_key_create(&m_currentThreadRegistrar, unregisterThread);
-    if (error)
-        CRASH();
-}
-
-void Heap::registerThread()
-{
-    ASSERT(!m_globalData->exclusiveThread || m_globalData->exclusiveThread == currentThread());
-
-    if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar))
-        return;
-
-    pthread_setspecific(m_currentThreadRegistrar, this);
-    Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());
-
-    MutexLocker lock(m_registeredThreadsMutex);
-
-    thread->next = m_registeredThreads;
-    m_registeredThreads = thread;
-}
-
-void Heap::unregisterThread(void* p)
-{
-    if (p)
-        static_cast<Heap*>(p)->unregisterThread();
-}
-
-void Heap::unregisterThread()
-{
-    pthread_t currentPosixThread = pthread_self();
-
-    MutexLocker lock(m_registeredThreadsMutex);
-
-    if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) {
-        Thread* t = m_registeredThreads;
-        m_registeredThreads = m_registeredThreads->next;
-        delete t;
-    } else {
-        Heap::Thread* last = m_registeredThreads;
-        Heap::Thread* t;
-        for (t = m_registeredThreads->next; t; t = t->next) {
-            if (pthread_equal(t->posixThread, currentPosixThread)) {
-                last->next = t->next;
-                break;
-            }
-            last = t;
-        }
-        ASSERT(t); // If t is NULL, we never found ourselves in the list.
-        delete t;
-    }
-}
-
-#else // ENABLE(JSC_MULTIPLE_THREADS)
-
-void Heap::registerThread()
-{
-}
-
-#endif
-
-inline bool isPointerAligned(void* p)
-{
-    return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0);
-}
-
-// Cell size needs to be a power of two for isPossibleCell to be valid.
-COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two);
-
-#if USE(JSVALUE32)
-static bool isHalfCellAligned(void *p)
-{
-    return (((intptr_t)(p) & (CELL_MASK >> 1)) == 0);
-}
-
-static inline bool isPossibleCell(void* p)
-{
-    return isHalfCellAligned(p) && p;
-}
-
-#else
-
-static inline bool isCellAligned(void *p)
-{
-    return (((intptr_t)(p) & CELL_MASK) == 0);
-}
-
-static inline bool isPossibleCell(void* p)
-{
-    return isCellAligned(p) && p;
-}
-#endif // USE(JSVALUE32)
-
-void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
-{
-    if (start > end) {
-        void* tmp = start;
-        start = end;
-        end = tmp;
-    }
-
-    ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
-    ASSERT(isPointerAligned(start));
-    ASSERT(isPointerAligned(end));
-
-    char** p = static_cast<char**>(start);
-    char** e = static_cast<char**>(end);
-
-    CollectorBlock** blocks = m_heap.blocks;
-    while (p != e) {
-        char* x = *p++;
-        if (isPossibleCell(x)) {
-            size_t usedBlocks;
-            uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
-            xAsBits &= CELL_ALIGN_MASK;
-
-            uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK;
-            const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1);
-            if (offset > lastCellOffset)
-                continue;
-
-            CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
-            usedBlocks = m_heap.usedBlocks;
-            for (size_t block = 0; block < usedBlocks; block++) {
-                if (blocks[block] != blockAddr)
-                    continue;
-                markStack.append(reinterpret_cast<JSCell*>(xAsBits));
-                markStack.drain();
-            }
-        }
-    }
-}
-
-void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack)
-{
-    void* dummy;
-    void* stackPointer = &dummy;
-    void* stackBase = currentThreadStackBase();
-    markConservatively(markStack, stackPointer, stackBase);
-}
-
-#if COMPILER(GCC)
-#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
-#else
-#define REGISTER_BUFFER_ALIGNMENT
-#endif
-
-void Heap::markCurrentThreadConservatively(MarkStack& markStack)
-{
-    // setjmp forces volatile registers onto the stack
-    jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#endif
-    setjmp(registers);
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
-    markCurrentThreadConservativelyInternal(markStack);
-}
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-static inline void suspendThread(const PlatformThread& platformThread)
-{
-#if OS(DARWIN)
-    thread_suspend(platformThread);
-#elif OS(WINDOWS)
-    SuspendThread(platformThread);
-#else
-#error Need a way to suspend threads on this platform
-#endif
-}
-
-static inline void resumeThread(const PlatformThread& platformThread)
-{
-#if OS(DARWIN)
-    thread_resume(platformThread);
-#elif OS(WINDOWS)
-    ResumeThread(platformThread);
-#else
-#error Need a way to resume threads on this platform
-#endif
-}
-
-typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit
-
-#if OS(DARWIN)
-
-#if CPU(X86)
-typedef i386_thread_state_t PlatformThreadRegisters;
-#elif CPU(X86_64)
-typedef x86_thread_state64_t PlatformThreadRegisters;
-#elif CPU(PPC)
-typedef ppc_thread_state_t PlatformThreadRegisters;
-#elif CPU(PPC64)
-typedef ppc_thread_state64_t PlatformThreadRegisters;
-#elif CPU(ARM)
-typedef arm_thread_state_t PlatformThreadRegisters;
-#else
-#error Unknown Architecture
-#endif
-
-#elif OS(WINDOWS) && CPU(X86)
-typedef CONTEXT PlatformThreadRegisters;
-#else
-#error Need a thread register struct for this platform
-#endif
-
-static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs)
-{
-#if OS(DARWIN)
-
-#if CPU(X86)
-    unsigned user_count = sizeof(regs)/sizeof(int);
-    thread_state_flavor_t flavor = i386_THREAD_STATE;
-#elif CPU(X86_64)
-    unsigned user_count = x86_THREAD_STATE64_COUNT;
-    thread_state_flavor_t flavor = x86_THREAD_STATE64;
-#elif CPU(PPC) 
-    unsigned user_count = PPC_THREAD_STATE_COUNT;
-    thread_state_flavor_t flavor = PPC_THREAD_STATE;
-#elif CPU(PPC64)
-    unsigned user_count = PPC_THREAD_STATE64_COUNT;
-    thread_state_flavor_t flavor = PPC_THREAD_STATE64;
-#elif CPU(ARM)
-    unsigned user_count = ARM_THREAD_STATE_COUNT;
-    thread_state_flavor_t flavor = ARM_THREAD_STATE;
-#else
-#error Unknown Architecture
-#endif
-
-    kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
-    if (result != KERN_SUCCESS) {
-        WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 
-                            "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
-        CRASH();
-    }
-    return user_count * sizeof(usword_t);
-// end OS(DARWIN)
-
-#elif OS(WINDOWS) && CPU(X86)
-    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
-    GetThreadContext(platformThread, &regs);
-    return sizeof(CONTEXT);
-#else
-#error Need a way to get thread registers on this platform
-#endif
-}
-
-static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
-{
-#if OS(DARWIN)
-
-#if __DARWIN_UNIX03
-
-#if CPU(X86)
-    return reinterpret_cast<void*>(regs.__esp);
-#elif CPU(X86_64)
-    return reinterpret_cast<void*>(regs.__rsp);
-#elif CPU(PPC) || CPU(PPC64)
-    return reinterpret_cast<void*>(regs.__r1);
-#elif CPU(ARM)
-    return reinterpret_cast<void*>(regs.__sp);
-#else
-#error Unknown Architecture
-#endif
-
-#else // !__DARWIN_UNIX03
-
-#if CPU(X86)
-    return reinterpret_cast<void*>(regs.esp);
-#elif CPU(X86_64)
-    return reinterpret_cast<void*>(regs.rsp);
-#elif CPU(PPC) || CPU(PPC64)
-    return reinterpret_cast<void*>(regs.r1);
-#else
-#error Unknown Architecture
-#endif
-
-#endif // __DARWIN_UNIX03
-
-// end OS(DARWIN)
-#elif CPU(X86) && OS(WINDOWS)
-    return reinterpret_cast<void*>((uintptr_t) regs.Esp);
-#else
-#error Need a way to get the stack pointer for another thread on this platform
-#endif
-}
-
-void Heap::markOtherThreadConservatively(MarkStack& markStack, Thread* thread)
-{
-    suspendThread(thread->platformThread);
-
-    PlatformThreadRegisters regs;
-    size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
-
-    // mark the thread's registers
-    markConservatively(markStack, static_cast<void*>(&regs), static_cast<void*>(reinterpret_cast<char*>(&regs) + regSize));
-
-    void* stackPointer = otherThreadStackPointer(regs);
-    markConservatively(markStack, stackPointer, thread->stackBase);
-
-    resumeThread(thread->platformThread);
-}
-
-#endif
-
-void Heap::markStackObjectsConservatively(MarkStack& markStack)
-{
-    markCurrentThreadConservatively(markStack);
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
-    if (m_currentThreadRegistrar) {
-
-        MutexLocker lock(m_registeredThreadsMutex);
-
-#ifndef NDEBUG
-        // Forbid malloc during the mark phase. Marking a thread suspends it, so 
-        // a malloc inside markChildren() would risk a deadlock with a thread that had been 
-        // suspended while holding the malloc lock.
-        fastMallocForbid();
-#endif
-        // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
-        // and since this is a shared heap, they are real locks.
-        for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
-            if (!pthread_equal(thread->posixThread, pthread_self()))
-                markOtherThreadConservatively(markStack, thread);
-        }
-#ifndef NDEBUG
-        fastMallocAllow();
-#endif
-    }
-#endif
-}
-
-void Heap::protect(JSValue k)
-{
-    ASSERT(k);
-    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
-
-    if (!k.isCell())
-        return;
-
-    m_protectedValues.add(k.asCell());
-}
-
-bool Heap::unprotect(JSValue k)
-{
-    ASSERT(k);
-    ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
-
-    if (!k.isCell())
-        return false;
-
-    return m_protectedValues.remove(k.asCell());
-}
-
-void Heap::markProtectedObjects(MarkStack& markStack)
-{
-    ProtectCountSet::iterator end = m_protectedValues.end();
-    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) {
-        markStack.append(it->first);
-        markStack.drain();
-    }
-}
-
-void Heap::pushTempSortVector(Vector<ValueStringPair>* tempVector)
-{
-    m_tempSortingVectors.append(tempVector);
-}
-
-void Heap::popTempSortVector(Vector<ValueStringPair>* tempVector)
-{
-    ASSERT_UNUSED(tempVector, tempVector == m_tempSortingVectors.last());
-    m_tempSortingVectors.removeLast();
-}
-    
-void Heap::markTempSortVectors(MarkStack& markStack)
-{
-    typedef Vector<Vector<ValueStringPair>* > VectorOfValueStringVectors;
-
-    VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
-    for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
-        Vector<ValueStringPair>* tempSortingVector = *it;
-
-        Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
-        for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt)
-            if (vectorIt->first)
-                markStack.append(vectorIt->first);
-        markStack.drain();
-    }
-}
-    
-void Heap::clearMarkBits()
-{
-    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
-        clearMarkBits(m_heap.blocks[i]);
-}
-
-void Heap::clearMarkBits(CollectorBlock* block)
-{
-    // allocate assumes that the last cell in every block is marked.
-    block->marked.clearAll();
-    block->marked.set(HeapConstants::cellsPerBlock - 1);
-}
-
-size_t Heap::markedCells(size_t startBlock, size_t startCell) const
-{
-    ASSERT(startBlock <= m_heap.usedBlocks);
-    ASSERT(startCell < HeapConstants::cellsPerBlock);
-
-    if (startBlock >= m_heap.usedBlocks)
-        return 0;
-
-    size_t result = 0;
-    result += m_heap.blocks[startBlock]->marked.count(startCell);
-    for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i)
-        result += m_heap.blocks[i]->marked.count();
-
-    return result;
-}
-
-void Heap::sweep()
-{
-    ASSERT(m_heap.operationInProgress == NoOperation);
-    if (m_heap.operationInProgress != NoOperation)
-        CRASH();
-    m_heap.operationInProgress = Collection;
-    
-#if !ENABLE(JSC_ZOMBIES)
-    Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
-#endif
-
-    DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell);
-    DeadObjectIterator end(m_heap, m_heap.usedBlocks);
-    for ( ; it != end; ++it) {
-        JSCell* cell = *it;
-#if ENABLE(JSC_ZOMBIES)
-        if (!cell->isZombie()) {
-            const ClassInfo* info = cell->classInfo();
-            cell->~JSCell();
-            new (cell) JSZombie(info, JSZombie::leakedZombieStructure());
-            Heap::markCell(cell);
-        }
-#else
-        cell->~JSCell();
-        // Callers of sweep assume it's safe to mark any cell in the heap.
-        new (cell) JSCell(dummyMarkableCellStructure);
-#endif
-    }
-
-    m_heap.operationInProgress = NoOperation;
-}
-
-void Heap::markRoots()
-{
-#ifndef NDEBUG
-    if (m_globalData->isSharedInstance()) {
-        ASSERT(JSLock::lockCount() > 0);
-        ASSERT(JSLock::currentThreadIsHoldingLock());
-    }
-#endif
-
-    ASSERT(m_heap.operationInProgress == NoOperation);
-    if (m_heap.operationInProgress != NoOperation)
-        CRASH();
-
-    m_heap.operationInProgress = Collection;
-
-    MarkStack& markStack = m_globalData->markStack;
-
-    // Reset mark bits.
-    clearMarkBits();
-
-    // Mark stack roots.
-    markStackObjectsConservatively(markStack);
-    m_globalData->interpreter->registerFile().markCallFrames(markStack, this);
-
-    // Mark explicitly registered roots.
-    markProtectedObjects(markStack);
-    
-    // Mark temporary vector for Array sorting
-    markTempSortVectors(markStack);
-
-    // Mark misc. other roots.
-    if (m_markListSet && m_markListSet->size())
-        MarkedArgumentBuffer::markLists(markStack, *m_markListSet);
-    if (m_globalData->exception)
-        markStack.append(m_globalData->exception);
-    if (m_globalData->functionCodeBlockBeingReparsed)
-        m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack);
-    if (m_globalData->firstStringifierToMark)
-        JSONObject::markStringifiers(markStack, m_globalData->firstStringifierToMark);
-
-    // Mark the small strings cache last, since it will clear itself if nothing
-    // else has marked it.
-    m_globalData->smallStrings.markChildren(markStack);
-
-    markStack.drain();
-    markStack.compact();
-
-    m_heap.operationInProgress = NoOperation;
-}
-
-size_t Heap::objectCount() const
-{
-    return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks
-           + m_heap.nextCell // allocated cells in current block
-           + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap
-           - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel
-}
-
-void Heap::addToStatistics(Heap::Statistics& statistics) const
-{
-    statistics.size += m_heap.usedBlocks * BLOCK_SIZE;
-    statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize);
-}
-
-Heap::Statistics Heap::statistics() const
-{
-    Statistics statistics = { 0, 0 };
-    addToStatistics(statistics);
-    return statistics;
-}
-
-size_t Heap::globalObjectCount()
-{
-    size_t count = 0;
-    if (JSGlobalObject* head = m_globalData->head) {
-        JSGlobalObject* o = head;
-        do {
-            ++count;
-            o = o->next();
-        } while (o != head);
-    }
-    return count;
-}
-
-size_t Heap::protectedGlobalObjectCount()
-{
-    size_t count = 0;
-    if (JSGlobalObject* head = m_globalData->head) {
-        JSGlobalObject* o = head;
-        do {
-            if (m_protectedValues.contains(o))
-                ++count;
-            o = o->next();
-        } while (o != head);
-    }
-
-    return count;
-}
-
-size_t Heap::protectedObjectCount()
-{
-    return m_protectedValues.size();
-}
-
-static const char* typeName(JSCell* cell)
-{
-    if (cell->isString())
-        return "string";
-#if USE(JSVALUE32)
-    if (cell->isNumber())
-        return "number";
-#endif
-    if (cell->isGetterSetter())
-        return "Getter-Setter";
-    if (cell->isAPIValueWrapper())
-        return "API wrapper";
-    if (cell->isPropertyNameIterator())
-        return "For-in iterator";
-    if (!cell->isObject())
-        return "[empty cell]";
-    const ClassInfo* info = cell->classInfo();
-    return info ? info->className : "Object";
-}
-
-HashCountedSet<const char*>* Heap::protectedObjectTypeCounts()
-{
-    HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
-
-    ProtectCountSet::iterator end = m_protectedValues.end();
-    for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
-        counts->add(typeName(it->first));
-
-    return counts;
-}
-
-HashCountedSet<const char*>* Heap::objectTypeCounts()
-{
-    HashCountedSet<const char*>* counts = new HashCountedSet<const char*>;
-
-    LiveObjectIterator it = primaryHeapBegin();
-    LiveObjectIterator heapEnd = primaryHeapEnd();
-    for ( ; it != heapEnd; ++it)
-        counts->add(typeName(*it));
-
-    return counts;
-}
-
-bool Heap::isBusy()
-{
-    return m_heap.operationInProgress != NoOperation;
-}
-
-void Heap::reset()
-{
-    JAVASCRIPTCORE_GC_BEGIN();
-
-    markRoots();
-
-    JAVASCRIPTCORE_GC_MARKED();
-
-    m_heap.nextCell = 0;
-    m_heap.nextBlock = 0;
-    m_heap.nextNumber = 0;
-    m_heap.extraCost = 0;
-#if ENABLE(JSC_ZOMBIES)
-    sweep();
-#endif
-    resizeBlocks();
-
-    JAVASCRIPTCORE_GC_END();
-}
-
-void Heap::collectAllGarbage()
-{
-    JAVASCRIPTCORE_GC_BEGIN();
-
-    // If the last iteration through the heap deallocated blocks, we need
-    // to clean up remaining garbage before marking. Otherwise, the conservative
-    // marking mechanism might follow a pointer to unmapped memory.
-    if (m_heap.didShrink)
-        sweep();
-
-    markRoots();
-
-    JAVASCRIPTCORE_GC_MARKED();
-
-    m_heap.nextCell = 0;
-    m_heap.nextBlock = 0;
-    m_heap.nextNumber = 0;
-    m_heap.extraCost = 0;
-    sweep();
-    resizeBlocks();
-
-    JAVASCRIPTCORE_GC_END();
-}
-
-LiveObjectIterator Heap::primaryHeapBegin()
-{
-    return LiveObjectIterator(m_heap, 0);
-}
-
-LiveObjectIterator Heap::primaryHeapEnd()
-{
-    return LiveObjectIterator(m_heap, m_heap.usedBlocks);
-}
-
-} // namespace JSC
diff --git a/runtime/Collector.h b/runtime/Collector.h
deleted file mode 100644 (file)
index 12893a3..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- */
-
-#ifndef Collector_h
-#define Collector_h
-
-#include "JSValue.h"
-#include <stddef.h>
-#include <string.h>
-#include <wtf/HashCountedSet.h>
-#include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/StdLibExtras.h>
-#include <wtf/Threading.h>
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <pthread.h>
-#endif
-
-#if OS(SYMBIAN)
-#include <wtf/symbian/BlockAllocatorSymbian.h>
-#endif
-
-#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell)
-
-namespace JSC {
-
-    class CollectorBlock;
-    class JSCell;
-    class JSGlobalData;
-    class JSValue;
-    class MarkedArgumentBuffer;
-    class MarkStack;
-
-    enum OperationInProgress { NoOperation, Allocation, Collection };
-
-    class LiveObjectIterator;
-
-    struct CollectorHeap {
-        size_t nextBlock;
-        size_t nextCell;
-        CollectorBlock** blocks;
-        
-        void* nextNumber;
-
-        size_t numBlocks;
-        size_t usedBlocks;
-
-        size_t extraCost;
-        bool didShrink;
-
-        OperationInProgress operationInProgress;
-    };
-
-    class Heap : public Noncopyable {
-    public:
-        class Thread;
-
-        void destroy();
-
-        void* allocateNumber(size_t);
-        void* allocate(size_t);
-
-        bool isBusy(); // true if an allocation or collection is in progress
-        void collectAllGarbage();
-
-        static const size_t minExtraCost = 256;
-        static const size_t maxExtraCost = 1024 * 1024;
-
-        void reportExtraMemoryCost(size_t cost);
-
-        size_t objectCount() const;
-        struct Statistics {
-            size_t size;
-            size_t free;
-        };
-        Statistics statistics() const;
-
-        void protect(JSValue);
-        // Returns true if the value is no longer protected by any protect pointers
-        // (though it may still be alive due to heap/stack references).
-        bool unprotect(JSValue);
-
-        static Heap* heap(JSValue); // 0 for immediate values
-        static Heap* heap(JSCell*);
-
-        size_t globalObjectCount();
-        size_t protectedObjectCount();
-        size_t protectedGlobalObjectCount();
-        HashCountedSet<const char*>* protectedObjectTypeCounts();
-        HashCountedSet<const char*>* objectTypeCounts();
-
-        void registerThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
-
-        static bool isCellMarked(const JSCell*);
-        static void markCell(JSCell*);
-
-        void markConservatively(MarkStack&, void* start, void* end);
-
-        void pushTempSortVector(WTF::Vector<ValueStringPair>*);
-        void popTempSortVector(WTF::Vector<ValueStringPair>*);        
-
-        HashSet<MarkedArgumentBuffer*>& markListSet() { if (!m_markListSet) m_markListSet = new HashSet<MarkedArgumentBuffer*>; return *m_markListSet; }
-
-        JSGlobalData* globalData() const { return m_globalData; }
-        static bool isNumber(JSCell*);
-        
-        LiveObjectIterator primaryHeapBegin();
-        LiveObjectIterator primaryHeapEnd();
-
-    private:
-        void reset();
-        void sweep();
-        static CollectorBlock* cellBlock(const JSCell*);
-        static size_t cellOffset(const JSCell*);
-
-        friend class JSGlobalData;
-        Heap(JSGlobalData*);
-        ~Heap();
-
-        NEVER_INLINE CollectorBlock* allocateBlock();
-        NEVER_INLINE void freeBlock(size_t);
-        NEVER_INLINE void freeBlockPtr(CollectorBlock*);
-        void freeBlocks();
-        void resizeBlocks();
-        void growBlocks(size_t neededBlocks);
-        void shrinkBlocks(size_t neededBlocks);
-        void clearMarkBits();
-        void clearMarkBits(CollectorBlock*);
-        size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
-
-        void recordExtraCost(size_t);
-
-        void addToStatistics(Statistics&) const;
-
-        void markRoots();
-        void markProtectedObjects(MarkStack&);
-        void markTempSortVectors(MarkStack&);
-        void markCurrentThreadConservatively(MarkStack&);
-        void markCurrentThreadConservativelyInternal(MarkStack&);
-        void markOtherThreadConservatively(MarkStack&, Thread*);
-        void markStackObjectsConservatively(MarkStack&);
-
-        typedef HashCountedSet<JSCell*> ProtectCountSet;
-
-        CollectorHeap m_heap;
-
-        ProtectCountSet m_protectedValues;
-        WTF::Vector<WTF::Vector<ValueStringPair>* > m_tempSortingVectors;
-
-        HashSet<MarkedArgumentBuffer*>* m_markListSet;
-
-#if ENABLE(JSC_MULTIPLE_THREADS)
-        void makeUsableFromMultipleThreads();
-
-        static void unregisterThread(void*);
-        void unregisterThread();
-
-        Mutex m_registeredThreadsMutex;
-        Thread* m_registeredThreads;
-        pthread_key_t m_currentThreadRegistrar;
-#endif
-
-#if OS(SYMBIAN)
-        // Allocates collector blocks with correct alignment
-        WTF::AlignedBlockAllocator m_blockallocator; 
-#endif
-        
-        JSGlobalData* m_globalData;
-    };
-
-    // tunable parameters
-    template<size_t bytesPerWord> struct CellSize;
-
-    // cell size needs to be a power of two for certain optimizations in collector.cpp
-#if USE(JSVALUE32)
-    template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; };
-#else
-    template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 64; };
-#endif
-    template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; };
-
-    const size_t BLOCK_SIZE = 64 * 1024; // 64k
-
-    // derived constants
-    const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
-    const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
-    const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value;
-    const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
-    const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double);
-    const size_t SMALL_CELL_SIZE = CELL_SIZE / 2;
-    const size_t CELL_MASK = CELL_SIZE - 1;
-    const size_t CELL_ALIGN_MASK = ~CELL_MASK;
-    const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
-    
-    const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
-    const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
-
-    struct CollectorBitmap {
-        uint32_t bits[BITMAP_WORDS];
-        bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 
-        void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 
-        void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 
-        void clearAll() { memset(bits, 0, sizeof(bits)); }
-        size_t count(size_t startCell = 0)
-        {
-            size_t result = 0;
-            for ( ; (startCell & 0x1F) != 0; ++startCell) {
-                if (get(startCell))
-                    ++result;
-            }
-            for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i)
-                result += WTF::bitCount(bits[i]);
-            return result;
-        }
-        size_t isEmpty() // Much more efficient than testing count() == 0.
-        {
-            for (size_t i = 0; i < BITMAP_WORDS; ++i)
-                if (bits[i] != 0)
-                    return false;
-            return true;
-        }
-    };
-  
-    struct CollectorCell {
-        double memory[CELL_ARRAY_LENGTH];
-    };
-
-    class CollectorBlock {
-    public:
-        CollectorCell cells[CELLS_PER_BLOCK];
-        CollectorBitmap marked;
-        Heap* heap;
-    };
-
-    struct HeapConstants {
-        static const size_t cellSize = CELL_SIZE;
-        static const size_t cellsPerBlock = CELLS_PER_BLOCK;
-        typedef CollectorCell Cell;
-        typedef CollectorBlock Block;
-    };
-
-    inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
-    {
-        return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
-    }
-
-    inline size_t Heap::cellOffset(const JSCell* cell)
-    {
-        return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
-    }
-
-    inline bool Heap::isCellMarked(const JSCell* cell)
-    {
-        return cellBlock(cell)->marked.get(cellOffset(cell));
-    }
-
-    inline void Heap::markCell(JSCell* cell)
-    {
-        cellBlock(cell)->marked.set(cellOffset(cell));
-    }
-
-    inline void Heap::reportExtraMemoryCost(size_t cost)
-    {
-        if (cost > minExtraCost) 
-            recordExtraCost(cost);
-    }
-    
-    inline void* Heap::allocateNumber(size_t s)
-    {
-        if (void* result = m_heap.nextNumber) {
-            m_heap.nextNumber = 0;
-            return result;
-        }
-
-        void* result = allocate(s);
-        m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2);
-        return result;
-    }
-
-} // namespace JSC
-
-#endif /* Collector_h */
diff --git a/runtime/CollectorHeapIterator.h b/runtime/CollectorHeapIterator.h
deleted file mode 100644 (file)
index be6f3c9..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2008, 2009 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. 
- */
-
-#include "config.h"
-#include "Collector.h"
-
-#ifndef CollectorHeapIterator_h
-#define CollectorHeapIterator_h
-
-namespace JSC {
-
-    class CollectorHeapIterator {
-    public:
-        bool operator!=(const CollectorHeapIterator& other);
-        JSCell* operator*() const;
-    
-    protected:
-        CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell);
-        void advance(size_t max);
-
-        CollectorHeap& m_heap;
-        size_t m_block;
-        size_t m_cell;
-    };
-
-    class LiveObjectIterator : public CollectorHeapIterator {
-    public:
-        LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
-        LiveObjectIterator& operator++();
-    };
-
-    class DeadObjectIterator : public CollectorHeapIterator {
-    public:
-        DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
-        DeadObjectIterator& operator++();
-    };
-
-    class ObjectIterator : public CollectorHeapIterator {
-    public:
-        ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
-        ObjectIterator& operator++();
-    };
-
-    inline CollectorHeapIterator::CollectorHeapIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : m_heap(heap)
-        , m_block(startBlock)
-        , m_cell(startCell)
-    {
-    }
-
-    inline bool CollectorHeapIterator::operator!=(const CollectorHeapIterator& other)
-    {
-        return m_block != other.m_block || m_cell != other.m_cell;
-    }
-
-    inline JSCell* CollectorHeapIterator::operator*() const
-    {
-        return reinterpret_cast<JSCell*>(m_heap.blocks[m_block]->cells + m_cell);
-    }
-    
-    // Iterators advance up to the next-to-last -- and not the last -- cell in a
-    // block, since the last cell is a dummy sentinel.
-    inline void CollectorHeapIterator::advance(size_t max)
-    {
-        ++m_cell;
-        if (m_cell == max) {
-            m_cell = 0;
-            ++m_block;
-        }
-    }
-
-    inline LiveObjectIterator::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : CollectorHeapIterator(heap, startBlock, startCell - 1)
-    {
-        ++(*this);
-    }
-
-    inline LiveObjectIterator& LiveObjectIterator::operator++()
-    {
-        advance(HeapConstants::cellsPerBlock - 1);
-        if (m_block < m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell < m_heap.nextCell))
-            return *this;
-
-        while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell))
-            advance(HeapConstants::cellsPerBlock - 1);
-        return *this;
-    }
-
-    inline DeadObjectIterator::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : CollectorHeapIterator(heap, startBlock, startCell - 1)
-    {
-        ++(*this);
-    }
-
-    inline DeadObjectIterator& DeadObjectIterator::operator++()
-    {
-        do {
-            advance(HeapConstants::cellsPerBlock - 1);
-            ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell));
-        } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell));
-        return *this;
-    }
-
-    inline ObjectIterator::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
-        : CollectorHeapIterator(heap, startBlock, startCell - 1)
-    {
-        ++(*this);
-    }
-
-    inline ObjectIterator& ObjectIterator::operator++()
-    {
-        advance(HeapConstants::cellsPerBlock - 1);
-        return *this;
-    }
-
-} // namespace JSC
-
-#endif // CollectorHeapIterator_h
index 3837817d052f78ece061ac6de717104defb7b7eb..82beda336296ee55913bbaf36cd32d00f772ab9d 100644 (file)
@@ -26,12 +26,15 @@ namespace JSC {
 static const char* const nullCString = 0;
 
 #define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name)
+#define INITIALIZE_KEYWORD(name) , name##Keyword(globalData, #name)
 
 CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData)
     : nullIdentifier(globalData, nullCString)
     , emptyIdentifier(globalData, "")
     , underscoreProto(globalData, "__proto__")
     , thisIdentifier(globalData, "this")
+    , useStrictIdentifier(globalData, "use strict")
+    JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(INITIALIZE_KEYWORD)
     JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
 {
 }
index de24f4a0d4847b5a2a89896e964d034bad717f6a..f74a84344a0a9167b0877f9c20d6007f590d1996 100644 (file)
     macro(compile) \
     macro(configurable) \
     macro(constructor) \
-    macro(create) \
-    macro(defineProperty) \
-    macro(defineProperties) \
     macro(enumerable) \
     macro(eval) \
     macro(exec) \
     macro(fromCharCode) \
     macro(global) \
     macro(get) \
-    macro(getPrototypeOf) \
-    macro(getOwnPropertyDescriptor) \
-    macro(getOwnPropertyNames) \
     macro(hasOwnProperty) \
     macro(ignoreCase) \
     macro(index) \
     macro(input) \
     macro(isArray) \
     macro(isPrototypeOf) \
-    macro(keys) \
     macro(length) \
     macro(message) \
     macro(multiline) \
     macro(writable) \
     macro(displayName)
 
+#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
+    macro(null) \
+    macro(true) \
+    macro(false) \
+    macro(break) \
+    macro(case) \
+    macro(catch) \
+    macro(const) \
+    macro(default) \
+    macro(finally) \
+    macro(for) \
+    macro(instanceof) \
+    macro(new) \
+    macro(var) \
+    macro(continue) \
+    macro(function) \
+    macro(return) \
+    macro(void) \
+    macro(delete) \
+    macro(if) \
+    macro(this) \
+    macro(do) \
+    macro(while) \
+    macro(else) \
+    macro(in) \
+    macro(switch) \
+    macro(throw) \
+    macro(try) \
+    macro(typeof) \
+    macro(with) \
+    macro(debugger) \
+    macro(class) \
+    macro(enum) \
+    macro(export) \
+    macro(extends) \
+    macro(import) \
+    macro(super)
+
 namespace JSC {
 
-    class CommonIdentifiers : public Noncopyable {
+    class CommonIdentifiers {
+        WTF_MAKE_NONCOPYABLE(CommonIdentifiers); WTF_MAKE_FAST_ALLOCATED;
     private:
         CommonIdentifiers(JSGlobalData*);
         friend class JSGlobalData;
@@ -94,7 +126,13 @@ namespace JSC {
         const Identifier emptyIdentifier;
         const Identifier underscoreProto;
         const Identifier thisIdentifier;
+        const Identifier useStrictIdentifier;
 
+        
+#define JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL(name) const Identifier name##Keyword;
+        JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL)
+#undef JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL
+        
 #define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name;
         JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL)
 #undef JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL
index 9af5171a11defb9d415d04a27fef3046345245f1..ac19705c0aa9699707106e103bbe6eb33b385914 100644 (file)
@@ -39,7 +39,7 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
     JSLock lock(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
 
-    RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
+    ProgramExecutable* program = ProgramExecutable::create(exec, source);
     JSObject* error = program->checkSyntax(exec);
     if (error)
         return Completion(Throw, error);
@@ -47,22 +47,26 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source)
     return Completion(Normal);
 }
 
-Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue)
+Completion evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& source, JSValue thisValue)
 {
     JSLock lock(exec);
     ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
 
-    RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source);
-    JSObject* error = program->compile(exec, scopeChain.node());
-    if (error)
-        return Completion(Throw, error);
+    ProgramExecutable* program = ProgramExecutable::create(exec, source);
+    if (!program) {
+        JSValue exception = exec->globalData().exception;
+        exec->globalData().exception = JSValue();
+        return Completion(Throw, exception);
+    }
 
     JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
 
-    JSValue exception;
-    JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception);
+    JSValue result = exec->interpreter()->execute(program, exec, scopeChain, thisObj);
+
+    if (exec->hadException()) {
+        JSValue exception = exec->exception();
+        exec->clearException();
 
-    if (exception) {
         ComplType exceptionType = Throw;
         if (exception.isObject())
             exceptionType = asObject(exception)->exceptionType();
index 63b315e18f639dd84f5ebca8a5dea077f432e320..1dd25fd11ae3fdc2e85783ad1524c6f2b0acb66a 100644 (file)
@@ -28,7 +28,7 @@
 namespace JSC {
 
     class ExecState;
-    class ScopeChain;
+    class ScopeChainNode;
     class SourceCode;
 
     enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted, Terminated };
@@ -56,7 +56,7 @@ namespace JSC {
     };
 
     Completion checkSyntax(ExecState*, const SourceCode&);
-    Completion evaluate(ExecState*, ScopeChain&, const SourceCode&, JSValue thisValue = JSValue());
+    Completion evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue());
 
 } // namespace JSC
 
index 7ee59d7ef77bf261c18c16c8190be56aff60957e..5da2a911cc5177a0d9bda27ebb5be8d6ef8d2de2 100644 (file)
 #include "config.h"
 #include "ConstructData.h"
 
+#include "Executable.h"
+#include "Interpreter.h"
 #include "JSFunction.h"
+#include "JSGlobalObject.h"
 
 namespace JSC {
 
-JSObject* construct(ExecState* exec, JSValue object, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
+JSObject* construct(ExecState* exec, JSValue constructorObject, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
 {
-    if (constructType == ConstructTypeHost)
-        return constructData.native.function(exec, asObject(object), args);
-    ASSERT(constructType == ConstructTypeJS);
-    // FIXME: Can this be done more efficiently using the constructData?
-    return asFunction(object)->construct(exec, args);
+    ASSERT(constructType == ConstructTypeJS || constructType == ConstructTypeHost);
+    return exec->interpreter()->executeConstruct(exec, asObject(constructorObject), constructType, constructData, args);
 }
 
 } // namespace JSC
index 6b954a629e518b28e4783c817f86cc32b9431603..3d5f732a2210cfe2622ddaa22016053dc53f2ffe 100644 (file)
 #ifndef ConstructData_h
 #define ConstructData_h
 
+#include "JSValue.h"
+
 namespace JSC {
 
     class ArgList;
     class ExecState;
     class FunctionExecutable;
     class JSObject;
-    class JSValue;
     class ScopeChainNode;
 
     enum ConstructType {
@@ -44,7 +45,7 @@ namespace JSC {
         ConstructTypeJS
     };
 
-    typedef JSObject* (*NativeConstructor)(ExecState*, JSObject*, const ArgList&);
+    typedef EncodedJSValue (JSC_HOST_CALL *NativeConstructor)(ExecState*);
 
     union ConstructData {
         struct {
index ab95d0668d16f75afababea2872f155fbaeef276..8fb5aef44abc83d1c021c760a854dfb3e1b57bc6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -30,7 +30,6 @@
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
 #include <math.h>
 #include <time.h>
 #include <wtf/DateMath.h>
@@ -52,26 +51,47 @@ using namespace WTF;
 
 namespace JSC {
 
-ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+static EncodedJSValue JSC_HOST_CALL dateParse(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState*);
+
+}
+
+#include "DateConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo DateConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::dateConstructorTable };
 
-static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&);
+/* Source for DateConstructor.lut.h
+@begin dateConstructorTable
+  parse     dateParse   DontEnum|Function 1
+  UTC       dateUTC     DontEnum|Function 7
+  now       dateNow     DontEnum|Function 0
+@end
+*/
 
-DateConstructor::DateConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className))
+ASSERT_CLASS_FITS_IN_CELL(DateConstructor);
+
+DateConstructor::DateConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, DatePrototype* datePrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, datePrototype->classInfo()->className))
 {
-      putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, datePrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(7), ReadOnly | DontEnum | DontDelete);
+}
 
-      putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().parse, dateParse), DontEnum);
-      putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 7, exec->propertyNames().UTC, dateUTC), DontEnum);
-      putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().now, dateNow), DontEnum);
+bool DateConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::dateConstructorTable(exec), this, propertyName, slot);
+}
 
-      putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 7), ReadOnly | DontEnum | DontDelete);
+bool DateConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::dateConstructorTable(exec), this, propertyName, descriptor);
 }
 
 // ECMA 15.9.3
-JSObject* constructDate(ExecState* exec, const ArgList& args)
+JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
     int numArgs = args.size();
 
@@ -80,7 +100,7 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
     if (numArgs == 0) // new Date() ECMA 15.9.3.3
         value = jsCurrentTime();
     else if (numArgs == 1) {
-        if (args.at(0).inherits(&DateInstance::info))
+        if (args.at(0).inherits(&DateInstance::s_info))
             value = asDateInstance(args.at(0))->internalNumber();
         else {
             JSValue primitive = args.at(0).toPrimitive(exec);
@@ -90,35 +110,45 @@ JSObject* constructDate(ExecState* exec, const ArgList& args)
                 value = primitive.toNumber(exec);
         }
     } else {
-        if (isnan(args.at(0).toNumber(exec))
-                || isnan(args.at(1).toNumber(exec))
-                || (numArgs >= 3 && isnan(args.at(2).toNumber(exec)))
-                || (numArgs >= 4 && isnan(args.at(3).toNumber(exec)))
-                || (numArgs >= 5 && isnan(args.at(4).toNumber(exec)))
-                || (numArgs >= 6 && isnan(args.at(5).toNumber(exec)))
-                || (numArgs >= 7 && isnan(args.at(6).toNumber(exec))))
+        double doubleArguments[7] = {
+            args.at(0).toNumber(exec), 
+            args.at(1).toNumber(exec), 
+            args.at(2).toNumber(exec), 
+            args.at(3).toNumber(exec), 
+            args.at(4).toNumber(exec), 
+            args.at(5).toNumber(exec), 
+            args.at(6).toNumber(exec)
+        };
+        if (isnan(doubleArguments[0])
+                || isnan(doubleArguments[1])
+                || (numArgs >= 3 && isnan(doubleArguments[2]))
+                || (numArgs >= 4 && isnan(doubleArguments[3]))
+                || (numArgs >= 5 && isnan(doubleArguments[4]))
+                || (numArgs >= 6 && isnan(doubleArguments[5]))
+                || (numArgs >= 7 && isnan(doubleArguments[6])))
             value = NaN;
         else {
             GregorianDateTime t;
-            int year = args.at(0).toInt32(exec);
+            int year = JSC::toInt32(doubleArguments[0]);
             t.year = (year >= 0 && year <= 99) ? year : year - 1900;
-            t.month = args.at(1).toInt32(exec);
-            t.monthDay = (numArgs >= 3) ? args.at(2).toInt32(exec) : 1;
-            t.hour = args.at(3).toInt32(exec);
-            t.minute = args.at(4).toInt32(exec);
-            t.second = args.at(5).toInt32(exec);
+            t.month = JSC::toInt32(doubleArguments[1]);
+            t.monthDay = (numArgs >= 3) ? JSC::toInt32(doubleArguments[2]) : 1;
+            t.hour = JSC::toInt32(doubleArguments[3]);
+            t.minute = JSC::toInt32(doubleArguments[4]);
+            t.second = JSC::toInt32(doubleArguments[5]);
             t.isDST = -1;
-            double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0;
+            double ms = (numArgs >= 7) ? doubleArguments[6] : 0;
             value = gregorianDateTimeToMS(exec, t, ms, false);
         }
     }
 
-    return new (exec) DateInstance(exec, value);
+    return new (exec) DateInstance(exec, globalObject->dateStructure(), value);
 }
     
-static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithDateConstructor(ExecState* exec)
 {
-    return constructDate(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructDate(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 ConstructType DateConstructor::getConstructData(ConstructData& constructData)
@@ -128,7 +158,7 @@ ConstructType DateConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.9.2
-static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const ArgList&)
+static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec)
 {
     time_t localTime = time(0);
     tm localTM;
@@ -138,7 +168,7 @@ static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const
     DateConversionBuffer time;
     formatDate(ts, date);
     formatTime(ts, time);
-    return jsMakeNontrivialString(exec, date, " ", time);
+    return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
 }
 
 CallType DateConstructor::getCallData(CallData& callData)
@@ -147,38 +177,47 @@ CallType DateConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
-static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL dateParse(ExecState* exec)
 {
-    return jsNumber(exec, parseDate(exec, args.at(0).toString(exec)));
+    return JSValue::encode(jsNumber(parseDate(exec, exec->argument(0).toString(exec))));
 }
 
-static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&)
+static EncodedJSValue JSC_HOST_CALL dateNow(ExecState*)
 {
-    return jsNumber(exec, jsCurrentTime());
+    return JSValue::encode(jsNumber(jsCurrentTime()));
 }
 
-static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const ArgList& args
+static EncodedJSValue JSC_HOST_CALL dateUTC(ExecState* exec
 {
-    int n = args.size();
-    if (isnan(args.at(0).toNumber(exec))
-            || isnan(args.at(1).toNumber(exec))
-            || (n >= 3 && isnan(args.at(2).toNumber(exec)))
-            || (n >= 4 && isnan(args.at(3).toNumber(exec)))
-            || (n >= 5 && isnan(args.at(4).toNumber(exec)))
-            || (n >= 6 && isnan(args.at(5).toNumber(exec)))
-            || (n >= 7 && isnan(args.at(6).toNumber(exec))))
-        return jsNaN(exec);
+    double doubleArguments[7] = {
+        exec->argument(0).toNumber(exec), 
+        exec->argument(1).toNumber(exec), 
+        exec->argument(2).toNumber(exec), 
+        exec->argument(3).toNumber(exec), 
+        exec->argument(4).toNumber(exec), 
+        exec->argument(5).toNumber(exec), 
+        exec->argument(6).toNumber(exec)
+    };
+    int n = exec->argumentCount();
+    if (isnan(doubleArguments[0])
+            || isnan(doubleArguments[1])
+            || (n >= 3 && isnan(doubleArguments[2]))
+            || (n >= 4 && isnan(doubleArguments[3]))
+            || (n >= 5 && isnan(doubleArguments[4]))
+            || (n >= 6 && isnan(doubleArguments[5]))
+            || (n >= 7 && isnan(doubleArguments[6])))
+        return JSValue::encode(jsNaN());
 
     GregorianDateTime t;
-    int year = args.at(0).toInt32(exec);
+    int year = JSC::toInt32(doubleArguments[0]);
     t.year = (year >= 0 && year <= 99) ? year : year - 1900;
-    t.month = args.at(1).toInt32(exec);
-    t.monthDay = (n >= 3) ? args.at(2).toInt32(exec) : 1;
-    t.hour = args.at(3).toInt32(exec);
-    t.minute = args.at(4).toInt32(exec);
-    t.second = args.at(5).toInt32(exec);
-    double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0;
-    return jsNumber(exec, timeClip(gregorianDateTimeToMS(exec, t, ms, true)));
+    t.month = JSC::toInt32(doubleArguments[1]);
+    t.monthDay = (n >= 3) ? JSC::toInt32(doubleArguments[2]) : 1;
+    t.hour = JSC::toInt32(doubleArguments[3]);
+    t.minute = JSC::toInt32(doubleArguments[4]);
+    t.second = JSC::toInt32(doubleArguments[5]);
+    double ms = (n >= 7) ? doubleArguments[6] : 0;
+    return JSValue::encode(jsNumber(timeClip(gregorianDateTimeToMS(exec, t, ms, true))));
 }
 
 } // namespace JSC
index 10e450e7cd2b59d2acc3b5526e03a0f8fc2d5906..63e78cf9a1d02974cb5c57275008edb3f9223ecf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -29,14 +29,27 @@ namespace JSC {
 
     class DateConstructor : public InternalFunction {
     public:
-        DateConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*);
+        DateConstructor(ExecState*, JSGlobalObject*, Structure*, DatePrototype*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
+
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
-    JSObject* constructDate(ExecState*, const ArgList&);
+    JSObject* constructDate(ExecState*, JSGlobalObject*, const ArgList&);
 
 } // namespace JSC
 
index 70dbaa0306362cbb5d698336be7877f7f189ce48..1418876ed1492c1dce52ad9d7a80936a6ca8bc1e 100644 (file)
 #include "DateConversion.h"
 
 #include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 #include "UString.h"
 #include <wtf/DateMath.h>
 #include <wtf/StringExtras.h>
+#include <wtf/text/CString.h>
 
 using namespace WTF;
 
@@ -56,7 +59,9 @@ double parseDate(ExecState* exec, const UString &date)
 {
     if (date == exec->globalData().cachedDateString)
         return exec->globalData().cachedDateStringValue;
-    double value = parseDateFromNullTerminatedCharacters(exec, date.UTF8String().data());
+    double value = parseES5DateFromNullTerminatedCharacters(date.utf8().data());
+    if (isnan(value))
+        value = parseDateFromNullTerminatedCharacters(exec, date.utf8().data());
     exec->globalData().cachedDateString = date;
     exec->globalData().cachedDateStringValue = value;
     return value;
index b43b183e27ea3974066e1e2d3fab74d16e84d55c..d8ca072491b8583dfc81e1295a2d8b392a6447df 100644 (file)
@@ -32,24 +32,20 @@ using namespace WTF;
 
 namespace JSC {
 
-const ClassInfo DateInstance::info = {"Date", 0, 0, 0};
+const ClassInfo DateInstance::s_info = {"Date", &JSWrapperObject::s_info, 0, 0};
 
-DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure)
-    : JSWrapperObject(structure)
+DateInstance::DateInstance(ExecState* exec, Structure* structure)
+    : JSWrapperObject(exec->globalData(), structure)
 {
-    setInternalValue(jsNaN(exec));
+    ASSERT(inherits(&s_info));
+    setInternalValue(exec->globalData(), jsNaN());
 }
 
-DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure, double time)
-    : JSWrapperObject(structure)
+DateInstance::DateInstance(ExecState* exec, Structure* structure, double time)
+    : JSWrapperObject(exec->globalData(), structure)
 {
-    setInternalValue(jsNumber(exec, timeClip(time)));
-}
-
-DateInstance::DateInstance(ExecState* exec, double time)
-    : JSWrapperObject(exec->lexicalGlobalObject()->dateStructure())
-{
-    setInternalValue(jsNumber(exec, timeClip(time)));
+    ASSERT(inherits(&s_info));
+    setInternalValue(exec->globalData(), jsNumber(timeClip(time)));
 }
 
 const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
index 77d46de5df7d5e155e7e513359e38e02f149a0df..6195c8549f5534c575fe880ebfc1c7fdc2a93669 100644 (file)
@@ -31,13 +31,12 @@ namespace JSC {
 
     class DateInstance : public JSWrapperObject {
     public:
-        DateInstance(ExecState*, double);
-        DateInstance(ExecState*, NonNullPassRefPtr<Structure>, double);
-        explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>);
+        DateInstance(ExecState*, Structure*, double);
+        explicit DateInstance(ExecState*, Structure*);
 
         double internalNumber() const { return internalValue().uncheckedGetNumber(); }
 
-        static JS_EXPORTDATA const ClassInfo info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
         const GregorianDateTime* gregorianDateTime(ExecState* exec) const
         {
@@ -53,18 +52,14 @@ namespace JSC {
             return calculateGregorianDateTimeUTC(exec);
         }
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
-    protected:
-        static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
-
     private:
         const GregorianDateTime* calculateGregorianDateTime(ExecState*) const;
         const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const;
-        virtual const ClassInfo* classInfo() const { return &info; }
 
         mutable RefPtr<DateInstanceData> m_data;
     };
@@ -73,7 +68,7 @@ namespace JSC {
 
     inline DateInstance* asDateInstance(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&DateInstance::info));
+        ASSERT(asObject(value)->inherits(&DateInstance::s_info));
         return static_cast<DateInstance*>(asObject(value));
     }
 
index d208580a34ebd5e639eb6b1fde3cabb780650bf4..b60c29a60eed3d72b64d0430be285ae48bdf81ec 100644 (file)
@@ -86,7 +86,7 @@ namespace JSC {
 
         CacheEntry& lookup(double d) { return m_cache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
 
-        CacheEntry m_cache[cacheSize];
+        FixedArray<CacheEntry, cacheSize> m_cache;
     };
 
 } // namespace JSC
index 4ff3e7e55262cd63d655c38b800d4fe034be4354..0dd67460f45ae03f048153869b53bcd005c12546 100644 (file)
@@ -2,6 +2,7 @@
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
  *  Copyright (C) 2008, 2009 Torch Mobile, Inc. All rights reserved.
+ *  Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -38,6 +39,7 @@
 #include <limits.h>
 #include <locale.h>
 #include <math.h>
+#include <stdlib.h>
 #include <time.h>
 #include <wtf/Assertions.h>
 #include <wtf/DateMath.h>
@@ -69,52 +71,51 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
 
-static JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState*, JSObject*, JSValue, const ArgList&);
-
-static JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState*);
 
 }
 
@@ -126,7 +127,7 @@ enum LocaleDateTimeFormat { LocaleDateAndTime, LocaleDate, LocaleTime };
  
 
 // FIXME: Since this is superior to the strftime-based version, why limit this to PLATFORM(MAC)?
-// Instead we should consider using this whenever PLATFORM(CF) is true.
+// Instead we should consider using this whenever USE(CF) is true.
 
 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
 {
@@ -141,7 +142,7 @@ static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateForm
     return defaultStyle;
 }
 
-static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList& args)
+static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMilliseconds, LocaleDateTimeFormat format)
 {
     CFDateFormatterStyle dateStyle = (format != LocaleTime ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
     CFDateFormatterStyle timeStyle = (format != LocaleDate ? kCFDateFormatterLongStyle : kCFDateFormatterNoStyle);
@@ -149,16 +150,16 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     bool useCustomFormat = false;
     UString customFormatString;
 
-    UString arg0String = args.at(0).toString(exec);
-    if (arg0String == "custom" && !args.at(1).isUndefined()) {
+    UString arg0String = exec->argument(0).toString(exec);
+    if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
         useCustomFormat = true;
-        customFormatString = args.at(1).toString(exec);
-    } else if (format == LocaleDateAndTime && !args.at(1).isUndefined()) {
+        customFormatString = exec->argument(1).toString(exec);
+    } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
         dateStyle = styleFromArgString(arg0String, dateStyle);
-        timeStyle = styleFromArgString(args.at(1).toString(exec), timeStyle);
-    } else if (format != LocaleTime && !args.at(0).isUndefined())
+        timeStyle = styleFromArgString(exec->argument(1).toString(exec), timeStyle);
+    } else if (format != LocaleTime && !exec->argument(0).isUndefined())
         dateStyle = styleFromArgString(arg0String, dateStyle);
-    else if (format != LocaleDate && !args.at(0).isUndefined())
+    else if (format != LocaleDate && !exec->argument(0).isUndefined())
         timeStyle = styleFromArgString(arg0String, timeStyle);
 
     CFLocaleRef locale = CFLocaleCopyCurrent();
@@ -166,7 +167,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     CFRelease(locale);
 
     if (useCustomFormat) {
-        CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.data(), customFormatString.size());
+        CFStringRef customFormatCFString = CFStringCreateWithCharacters(0, customFormatString.characters(), customFormatString.length());
         CFDateFormatterSetFormat(formatter, customFormatCFString);
         CFRelease(customFormatCFString);
     }
@@ -178,7 +179,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     // We truncate the string returned from CFDateFormatter if it's absurdly long (> 200 characters).
     // That's not great error handling, but it just won't happen so it doesn't matter.
     UChar buffer[200];
-    const size_t bufferLength = sizeof(buffer) / sizeof(buffer[0]);
+    const size_t bufferLength = WTF_ARRAY_LENGTH(buffer);
     size_t length = CFStringGetLength(string);
     ASSERT(length <= bufferLength);
     if (length > bufferLength)
@@ -195,12 +196,12 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
 //
 // Format of member function: f([hour,] [min,] [sec,] [ms])
-static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, int maxArgs, double* ms, GregorianDateTime* t)
+static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms, GregorianDateTime* t)
 {
     double milliseconds = 0;
     bool ok = true;
     int idx = 0;
-    int numArgs = args.size();
+    int numArgs = exec->argumentCount();
     
     // JS allows extra trailing arguments -- ignore them
     if (numArgs > maxArgs)
@@ -209,19 +210,25 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in
     // hours
     if (maxArgs >= 4 && idx < numArgs) {
         t->hour = 0;
-        milliseconds += args.at(idx++).toInt32(exec, ok) * msPerHour;
+        double hours = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(hours);
+        milliseconds += hours * msPerHour;
     }
 
     // minutes
     if (maxArgs >= 3 && idx < numArgs && ok) {
         t->minute = 0;
-        milliseconds += args.at(idx++).toInt32(exec, ok) * msPerMinute;
+        double minutes = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(minutes);
+        milliseconds += minutes * msPerMinute;
     }
     
     // seconds
     if (maxArgs >= 2 && idx < numArgs && ok) {
         t->second = 0;
-        milliseconds += args.at(idx++).toInt32(exec, ok) * msPerSecond;
+        double seconds = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(seconds);
+        milliseconds += seconds * msPerSecond;
     }
     
     if (!ok)
@@ -229,7 +236,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in
         
     // milliseconds
     if (idx < numArgs) {
-        double millis = args.at(idx).toNumber(exec);
+        double millis = exec->argument(idx).toIntegerPreserveNaN(exec);
         ok = isfinite(millis);
         milliseconds += millis;
     } else
@@ -243,34 +250,40 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in
 // ms (representing milliseconds) and t (representing the rest of the date structure) appropriately.
 //
 // Format of member function: f([years,] [months,] [days])
-static bool fillStructuresUsingDateArgs(ExecState *exec, const ArgList& args, int maxArgs, double *ms, GregorianDateTime *t)
+static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms, GregorianDateTime *t)
 {
     int idx = 0;
     bool ok = true;
-    int numArgs = args.size();
+    int numArgs = exec->argumentCount();
   
     // JS allows extra trailing arguments -- ignore them
     if (numArgs > maxArgs)
         numArgs = maxArgs;
   
     // years
-    if (maxArgs >= 3 && idx < numArgs)
-        t->year = args.at(idx++).toInt32(exec, ok) - 1900;
-    
+    if (maxArgs >= 3 && idx < numArgs) {
+        double years = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(years);
+        t->year = toInt32(years - 1900);
+    }
     // months
-    if (maxArgs >= 2 && idx < numArgs && ok)   
-        t->month = args.at(idx++).toInt32(exec, ok);
-    
+    if (maxArgs >= 2 && idx < numArgs && ok) {
+        double months = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(months);
+        t->month = toInt32(months);
+    }
     // days
-    if (idx < numArgs && ok) {   
+    if (idx < numArgs && ok) {
+        double days = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(days);
         t->monthDay = 0;
-        *ms += args.at(idx).toInt32(exec, ok) * msPerDay;
+        *ms += days * msPerDay;
     }
     
     return ok;
 }
 
-const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState::dateTable};
+const ClassInfo DatePrototype::s_info = {"Date", &DateInstance::s_info, 0, ExecState::dateTable};
 
 /* Source for DatePrototype.lut.h
 @begin dateTable
@@ -319,16 +332,19 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState
   setUTCFullYear        dateProtoFuncSetUTCFullYear          DontEnum|Function       3
   setYear               dateProtoFuncSetYear                 DontEnum|Function       1
   getYear               dateProtoFuncGetYear                 DontEnum|Function       0
-  toJSON                dateProtoFuncToJSON                  DontEnum|Function       0
+  toJSON                dateProtoFuncToJSON                  DontEnum|Function       1
 @end
 */
 
 // ECMA 15.9.4
 
-DatePrototype::DatePrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
     : DateInstance(exec, structure)
 {
+    ASSERT(inherits(&s_info));
+
     // The constructor will be added later, after DateConstructor has been built.
+    putAnonymousValue(exec->globalData(), 0, globalObject);
 }
 
 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -344,390 +360,419 @@ bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier&
 
 // Functions
 
-JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, "Invalid Date");
+        return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     DateConversionBuffer date;
     DateConversionBuffer time;
     formatDate(*gregorianDateTime, date);
     formatTime(*gregorianDateTime, time);
-    return jsMakeNontrivialString(exec, date, " ", time);
+    return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, "Invalid Date");
+        return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     DateConversionBuffer date;
     DateConversionBuffer time;
     formatDateUTCVariant(*gregorianDateTime, date);
     formatTimeUTC(*gregorianDateTime, time);
-    return jsMakeNontrivialString(exec, date, " ", time);
+    return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
     
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, "Invalid Date");
+        return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
     // 6 for formatting and one for null termination = 27.  We add one extra character to allow us to force null termination.
     char buffer[28];
     snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000)));
     buffer[sizeof(buffer) - 1] = 0;
-    return jsNontrivialString(exec, buffer);
+    return JSValue::encode(jsNontrivialString(exec, buffer));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, "Invalid Date");
+        return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     DateConversionBuffer date;
     formatDate(*gregorianDateTime, date);
-    return jsNontrivialString(exec, date);
+    return JSValue::encode(jsNontrivialString(exec, date));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, "Invalid Date");
+        return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     DateConversionBuffer time;
     formatTime(*gregorianDateTime, time);
-    return jsNontrivialString(exec, time);
+    return JSValue::encode(jsNontrivialString(exec, time));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime, args);
+    return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate, args);
+    return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
-    return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime, args);
+    return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
-    return asDateInstance(thisValue)->internalValue(); 
+    return JSValue::encode(asDateInstance(thisValue)->internalValue());
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, 1900 + gregorianDateTime->year);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(1900 + gregorianDateTime->year));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, 1900 + gregorianDateTime->year);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(1900 + gregorianDateTime->year));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, "Invalid Date");
+        return JSValue::encode(jsNontrivialString(exec, "Invalid Date"));
     DateConversionBuffer date;
     DateConversionBuffer time;
     formatDateUTCVariant(*gregorianDateTime, date);
     formatTimeUTC(*gregorianDateTime, time);
-    return jsMakeNontrivialString(exec, date, " ", time);
+    return JSValue::encode(jsMakeNontrivialString(exec, date, " ", time));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->month);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->month));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->month);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->month));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->monthDay);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->monthDay));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->monthDay);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->monthDay));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->weekDay);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->weekDay));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->weekDay);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->weekDay));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->hour);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->hour));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->hour);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->hour));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->minute);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->minute));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->minute);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->minute));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->second);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->second));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, gregorianDateTime->second);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(gregorianDateTime->second));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     double milli = thisDateObj->internalNumber();
     if (isnan(milli))
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
 
     double secs = floor(milli / msPerSecond);
     double ms = milli - secs * msPerSecond;
-    return jsNumber(exec, ms);
+    return JSValue::encode(jsNumber(ms));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
     double milli = thisDateObj->internalNumber();
     if (isnan(milli))
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
 
     double secs = floor(milli / msPerSecond);
     double ms = milli - secs * msPerSecond;
-    return jsNumber(exec, ms);
+    return JSValue::encode(jsNumber(ms));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
-    return jsNumber(exec, -gregorianDateTime->utcOffset / minutesPerHour);
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(-gregorianDateTime->utcOffset / minutesPerHour));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
-    double milli = timeClip(args.at(0).toNumber(exec));
-    JSValue result = jsNumber(exec, milli);
-    thisDateObj->setInternalValue(result);
-    return result;
+    double milli = timeClip(exec->argument(0).toNumber(exec));
+    JSValue result = jsNumber(milli);
+    thisDateObj->setInternalValue(exec->globalData(), result);
+    return JSValue::encode(result);
 }
 
-static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);
     double milli = thisDateObj->internalNumber();
     
-    if (args.isEmpty() || isnan(milli)) {
-        JSValue result = jsNaN(exec);
-        thisDateObj->setInternalValue(result);
-        return result;
+    if (!exec->argumentCount() || isnan(milli)) {
+        JSValue result = jsNaN();
+        thisDateObj->setInternalValue(exec->globalData(), result);
+        return JSValue::encode(result);
     }
      
     double secs = floor(milli / msPerSecond);
@@ -737,31 +782,32 @@ static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const
         ? thisDateObj->gregorianDateTimeUTC(exec)
         : thisDateObj->gregorianDateTime(exec);
     if (!other)
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
 
     GregorianDateTime gregorianDateTime;
     gregorianDateTime.copyFrom(*other);
-    if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &gregorianDateTime)) {
-        JSValue result = jsNaN(exec);
-        thisDateObj->setInternalValue(result);
-        return result;
+    if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
+        JSValue result = jsNaN();
+        thisDateObj->setInternalValue(exec->globalData(), result);
+        return JSValue::encode(result);
     } 
     
-    JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
-    thisDateObj->setInternalValue(result);
-    return result;
+    JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
+    thisDateObj->setInternalValue(exec->globalData(), result);
+    return JSValue::encode(result);
 }
 
-static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const ArgList& args, int numArgsToUse, bool inputIsUTC)
+static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, bool inputIsUTC)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);
-    if (args.isEmpty()) {
-        JSValue result = jsNaN(exec);
-        thisDateObj->setInternalValue(result);
-        return result;
+    if (!exec->argumentCount()) {
+        JSValue result = jsNaN();
+        thisDateObj->setInternalValue(exec->globalData(), result);
+        return JSValue::encode(result);
     }      
     
     double milli = thisDateObj->internalNumber();
@@ -776,115 +822,116 @@ static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const
             ? thisDateObj->gregorianDateTimeUTC(exec)
             : thisDateObj->gregorianDateTime(exec);
         if (!other)
-            return jsNaN(exec);
+            return JSValue::encode(jsNaN());
         gregorianDateTime.copyFrom(*other);
     }
     
-    if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &gregorianDateTime)) {
-        JSValue result = jsNaN(exec);
-        thisDateObj->setInternalValue(result);
-        return result;
+    if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
+        JSValue result = jsNaN();
+        thisDateObj->setInternalValue(exec->globalData(), result);
+        return JSValue::encode(result);
     } 
            
-    JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
-    thisDateObj->setInternalValue(result);
-    return result;
+    JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC));
+    thisDateObj->setInternalValue(exec->globalData(), result);
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMilliSeconds(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMilliseconds(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 1, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 1, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetSeconds(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCSeconds(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 2, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 2, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMinutes(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMinutes(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 3, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 3, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetHours(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCHours(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromTimeArgs(exec, thisValue, args, 4, inputIsUTC);
+    return setNewValueFromTimeArgs(exec, 4, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetDate(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+    return setNewValueFromDateArgs(exec, 1, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCDate(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromDateArgs(exec, thisValue, args, 1, inputIsUTC);
+    return setNewValueFromDateArgs(exec, 1, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetMonth(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+    return setNewValueFromDateArgs(exec, 2, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCMonth(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromDateArgs(exec, thisValue, args, 2, inputIsUTC);
+    return setNewValueFromDateArgs(exec, 2, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetFullYear(ExecState* exec)
 {
     const bool inputIsUTC = false;
-    return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+    return setNewValueFromDateArgs(exec, 3, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec)
 {
     const bool inputIsUTC = true;
-    return setNewValueFromDateArgs(exec, thisValue, args, 3, inputIsUTC);
+    return setNewValueFromDateArgs(exec, 3, inputIsUTC);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue);     
-    if (args.isEmpty()) { 
-        JSValue result = jsNaN(exec);
-        thisDateObj->setInternalValue(result);
-        return result;
+    if (!exec->argumentCount()) { 
+        JSValue result = jsNaN();
+        thisDateObj->setInternalValue(exec->globalData(), result);
+        return JSValue::encode(result);
     }
     
     double milli = thisDateObj->internalNumber();
@@ -902,56 +949,57 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
             gregorianDateTime.copyFrom(*other);
     }
     
-    bool ok = true;
-    int32_t year = args.at(0).toInt32(exec, ok);
-    if (!ok) {
-        JSValue result = jsNaN(exec);
-        thisDateObj->setInternalValue(result);
-        return result;
+    double year = exec->argument(0).toIntegerPreserveNaN(exec);
+    if (!isfinite(year)) {
+        JSValue result = jsNaN();
+        thisDateObj->setInternalValue(exec->globalData(), result);
+        return JSValue::encode(result);
     }
             
-    gregorianDateTime.year = (year > 99 || year < 0) ? year - 1900 : year;
-    JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, false));
-    thisDateObj->setInternalValue(result);
-    return result;
+    gregorianDateTime.year = toInt32((year > 99 || year < 0) ? year - 1900 : year);
+    JSValue result = jsNumber(gregorianDateTimeToMS(exec, gregorianDateTime, ms, false));
+    thisDateObj->setInternalValue(exec->globalData(), result);
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
 {
-    if (!thisValue.inherits(&DateInstance::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&DateInstance::s_info))
+        return throwVMTypeError(exec);
 
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
 
     // NOTE: IE returns the full year even in getYear.
-    return jsNumber(exec, gregorianDateTime->year);
+    return JSValue::encode(jsNumber(gregorianDateTime->year));
 }
 
-JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     JSObject* object = thisValue.toThisObject(exec);
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
     
     JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString);
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
 
     CallData callData;
-    CallType callType = toISOValue.getCallData(callData);
+    CallType callType = getCallData(toISOValue, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError, "toISOString is not a function");
+        return throwVMError(exec, createTypeError(exec, "toISOString is not a function"));
 
     JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
     if (result.isObject())
-        return throwError(exec, TypeError, "toISOString did not return a primitive value");
-    return result;
+        return throwVMError(exec, createTypeError(exec, "toISOString did not return a primitive value"));
+    return JSValue::encode(result);
 }
 
 } // namespace JSC
index 612ca06a4e9ca871906c3646bab6b44d26a2a9ab..2e1030dffbd186973e2bb9d9406d4f04cd304312 100644 (file)
@@ -29,22 +29,23 @@ namespace JSC {
 
     class DatePrototype : public DateInstance {
     public:
-        DatePrototype(ExecState*, NonNullPassRefPtr<Structure>);
+        DatePrototype(ExecState*, JSGlobalObject*, Structure*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags;
 
+        COMPILE_ASSERT(!DateInstance::AnonymousSlotCount, DatePrototype_stomps_on_your_anonymous_slot);
+        static const unsigned AnonymousSlotCount = 1;
     };
 
 } // namespace JSC
index 69464b75fd5fc552987b84e34859d6c9301b8460..7eda19f54bc650f021b760a641a9f216bead74f8 100644 (file)
 #include "JSObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
+#include "SourceCode.h"
 
 namespace JSC {
 
-const char* expressionBeginOffsetPropertyName = "expressionBeginOffset";
-const char* expressionCaretOffsetPropertyName = "expressionCaretOffset";
-const char* expressionEndOffsetPropertyName = "expressionEndOffset";
-
-JSObject* Error::create(ExecState* exec, ErrorType type, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL)
-{
-    JSObject* constructor;
-    const char* name;
-    switch (type) {
-        case EvalError:
-            constructor = exec->lexicalGlobalObject()->evalErrorConstructor();
-            name = "Evaluation error";
-            break;
-        case RangeError:
-            constructor = exec->lexicalGlobalObject()->rangeErrorConstructor();
-            name = "Range error";
-            break;
-        case ReferenceError:
-            constructor = exec->lexicalGlobalObject()->referenceErrorConstructor();
-            name = "Reference error";
-            break;
-        case SyntaxError:
-            constructor = exec->lexicalGlobalObject()->syntaxErrorConstructor();
-            name = "Syntax error";
-            break;
-        case TypeError:
-            constructor = exec->lexicalGlobalObject()->typeErrorConstructor();
-            name = "Type error";
-            break;
-        case URIError:
-            constructor = exec->lexicalGlobalObject()->URIErrorConstructor();
-            name = "URI error";
-            break;
-        default:
-            constructor = exec->lexicalGlobalObject()->errorConstructor();
-            name = "Error";
-            break;
-    }
+static const char* linePropertyName = "line";
+static const char* sourceIdPropertyName = "sourceId";
+static const char* sourceURLPropertyName = "sourceURL";
+
+JSObject* createError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->errorStructure(), message);
+}
+
+JSObject* createEvalError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->evalErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createRangeError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->rangeErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createReferenceError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->referenceErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createSyntaxError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->syntaxErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createTypeError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->typeErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createURIError(JSGlobalObject* globalObject, const UString& message)
+{
+    ASSERT(!message.isEmpty());
+    return ErrorInstance::create(&globalObject->globalData(), globalObject->URIErrorConstructor()->errorStructure(), message);
+}
+
+JSObject* createError(ExecState* exec, const UString& message)
+{
+    return createError(exec->lexicalGlobalObject(), message);
+}
+
+JSObject* createEvalError(ExecState* exec, const UString& message)
+{
+    return createEvalError(exec->lexicalGlobalObject(), message);
+}
+
+JSObject* createRangeError(ExecState* exec, const UString& message)
+{
+    return createRangeError(exec->lexicalGlobalObject(), message);
+}
 
-    MarkedArgumentBuffer args;
-    if (message.isEmpty())
-        args.append(jsString(exec, name));
-    else
-        args.append(jsString(exec, message));
-    ConstructData constructData;
-    ConstructType constructType = constructor->getConstructData(constructData);
-    JSObject* error = construct(exec, constructor, constructType, constructData, args);
-
-    if (lineNumber != -1)
-        error->putWithAttributes(exec, Identifier(exec, "line"), jsNumber(exec, lineNumber), ReadOnly | DontDelete);
+JSObject* createReferenceError(ExecState* exec, const UString& message)
+{
+    return createReferenceError(exec->lexicalGlobalObject(), message);
+}
+
+JSObject* createSyntaxError(ExecState* exec, const UString& message)
+{
+    return createSyntaxError(exec->lexicalGlobalObject(), message);
+}
+
+JSObject* createTypeError(ExecState* exec, const UString& message)
+{
+    return createTypeError(exec->lexicalGlobalObject(), message);
+}
+
+JSObject* createURIError(ExecState* exec, const UString& message)
+{
+    return createURIError(exec->lexicalGlobalObject(), message);
+}
+
+JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source)
+{
+    intptr_t sourceID = source.provider()->asID();
+    const UString& sourceURL = source.provider()->url();
+
+    if (line != -1)
+        error->putWithAttributes(globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete);
     if (sourceID != -1)
-        error->putWithAttributes(exec, Identifier(exec, "sourceId"), jsNumber(exec, sourceID), ReadOnly | DontDelete);
+        error->putWithAttributes(globalData, Identifier(globalData, sourceIdPropertyName), jsNumber((double)sourceID), ReadOnly | DontDelete);
     if (!sourceURL.isNull())
-        error->putWithAttributes(exec, Identifier(exec, "sourceURL"), jsString(exec, sourceURL), ReadOnly | DontDelete);
+        error->putWithAttributes(globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete);
 
     return error;
 }
 
-JSObject* Error::create(ExecState* exec, ErrorType type, const char* message)
+JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source)
 {
-    return create(exec, type, message, -1, -1, UString());
+    return addErrorInfo(&exec->globalData(), error, line, source);
 }
 
-JSObject* throwError(ExecState* exec, JSObject* error)
+bool hasErrorInfo(ExecState* exec, JSObject* error)
 {
-    exec->setException(error);
-    return error;
+    return error->hasProperty(exec, Identifier(exec, linePropertyName))
+        || error->hasProperty(exec, Identifier(exec, sourceIdPropertyName))
+        || error->hasProperty(exec, Identifier(exec, sourceURLPropertyName));
 }
 
-JSObject* throwError(ExecState* exec, ErrorType type)
+JSValue throwError(ExecState* exec, JSValue error)
 {
-    JSObject* error = Error::create(exec, type, UString(), -1, -1, UString());
-    exec->setException(error);
+    exec->globalData().exception = error;
     return error;
 }
 
-JSObject* throwError(ExecState* exec, ErrorType type, const UString& message)
+JSObject* throwError(ExecState* exec, JSObject* error)
 {
-    JSObject* error = Error::create(exec, type, message, -1, -1, UString());
-    exec->setException(error);
+    exec->globalData().exception = error;
     return error;
 }
 
-JSObject* throwError(ExecState* exec, ErrorType type, const char* message)
+JSObject* throwTypeError(ExecState* exec)
 {
-    JSObject* error = Error::create(exec, type, message, -1, -1, UString());
-    exec->setException(error);
-    return error;
+    return throwError(exec, createTypeError(exec, "Type error"));
 }
 
-JSObject* throwError(ExecState* exec, ErrorType type, const UString& message, int line, intptr_t sourceID, const UString& sourceURL)
+JSObject* throwSyntaxError(ExecState* exec)
 {
-    JSObject* error = Error::create(exec, type, message, line, sourceID, sourceURL);
-    exec->setException(error);
-    return error;
+    return throwError(exec, createSyntaxError(exec, "Syntax error"));
+}
+
+class StrictModeTypeErrorFunction : public InternalFunction {
+public:
+    StrictModeTypeErrorFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& message)
+        : InternalFunction(&exec->globalData(), globalObject, structure, exec->globalData().propertyNames->emptyIdentifier)
+        , m_message(message)
+    {
+    }
+    
+    static EncodedJSValue JSC_HOST_CALL constructThrowTypeError(ExecState* exec)
+    {
+        throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message);
+        return JSValue::encode(jsNull());
+    }
+    
+    ConstructType getConstructData(ConstructData& constructData)
+    {
+        constructData.native.function = constructThrowTypeError;
+        return ConstructTypeHost;
+    }
+    
+    static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec)
+    {
+        throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message);
+        return JSValue::encode(jsNull());
+    }
+
+    CallType getCallData(CallData& callData)
+    {
+        callData.native.function = callThrowTypeError;
+        return CallTypeHost;
+    }
+
+private:
+    UString m_message;
+};
+
+ASSERT_CLASS_FITS_IN_CELL(StrictModeTypeErrorFunction);
+
+JSValue createTypeErrorFunction(ExecState* exec, const UString& message)
+{
+    return new (exec) StrictModeTypeErrorFunction(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->internalFunctionStructure(), message);
 }
 
 } // namespace JSC
index e959cff6a573b2cd5bfd79fbd8fec99bfda7a3ab..c0f9d32098b1666adf39bdb40d3f84bf100f7d8c 100644 (file)
 #ifndef Error_h
 #define Error_h
 
+#include "JSObject.h"
 #include <stdint.h>
 
 namespace JSC {
 
     class ExecState;
+    class JSGlobalData;
+    class JSGlobalObject;
     class JSObject;
+    class SourceCode;
+    class Structure;
     class UString;
 
-    /**
-     * Types of Native Errors available. For custom errors, GeneralError
-     * should be used.
-     */
-    enum ErrorType {
-        GeneralError   = 0,
-        EvalError      = 1,
-        RangeError     = 2,
-        ReferenceError = 3,
-        SyntaxError    = 4,
-        TypeError      = 5,
-        URIError       = 6
-    };
-    
-    extern const char* expressionBeginOffsetPropertyName;
-    extern const char* expressionCaretOffsetPropertyName;
-    extern const char* expressionEndOffsetPropertyName;
-    
-    class Error {
-    public:
-        static JSObject* create(ExecState*, ErrorType, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL);
-        static JSObject* create(ExecState*, ErrorType, const char* message);
-    };
+    // Methods to create a range of internal errors.
+    JSObject* createError(JSGlobalObject*, const UString&);
+    JSObject* createEvalError(JSGlobalObject*, const UString&);
+    JSObject* createRangeError(JSGlobalObject*, const UString&);
+    JSObject* createReferenceError(JSGlobalObject*, const UString&);
+    JSObject* createSyntaxError(JSGlobalObject*, const UString&);
+    JSObject* createTypeError(JSGlobalObject*, const UString&);
+    JSObject* createURIError(JSGlobalObject*, const UString&);
+    // ExecState wrappers.
+    JSObject* createError(ExecState*, const UString&);
+    JSObject* createEvalError(ExecState*, const UString&);
+    JSObject* createRangeError(ExecState*, const UString&);
+    JSObject* createReferenceError(ExecState*, const UString&);
+    JSObject* createSyntaxError(ExecState*, const UString&);
+    JSObject* createTypeError(ExecState*, const UString&);
+    JSObject* createURIError(ExecState*, const UString&);
+
+    // Methods to add 
+    bool hasErrorInfo(ExecState*, JSObject* error);
+    JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&);
+    // ExecState wrappers.
+    JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&);
 
-    JSObject* throwError(ExecState*, ErrorType, const UString& message, int lineNumber, intptr_t sourceID, const UString& sourceURL);
-    JSObject* throwError(ExecState*, ErrorType, const UString& message);
-    JSObject* throwError(ExecState*, ErrorType, const char* message);
-    JSObject* throwError(ExecState*, ErrorType);
+    // Methods to throw Errors.
+    JSValue throwError(ExecState*, JSValue);
     JSObject* throwError(ExecState*, JSObject*);
 
+    // Convenience wrappers, create an throw an exception with a default message.
+    JSObject* throwTypeError(ExecState*);
+    JSObject* throwSyntaxError(ExecState*);
+
+    // Convenience wrappers, wrap result as an EncodedJSValue.
+    inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); }
+    inline EncodedJSValue throwVMTypeError(ExecState* exec) { return JSValue::encode(throwTypeError(exec)); }
+
+    JSValue createTypeErrorFunction(ExecState* exec, const UString& message);
+    
 } // namespace JSC
 
 #endif // Error_h
index b9c3f586c298e4bb6af60ba0c24cf237c6241e61..df112dd2221f9c98f7bde90bc0bc8e913024be11 100644 (file)
@@ -29,26 +29,21 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
 
-ErrorConstructor::ErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ErrorPrototype* errorPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className))
+ErrorConstructor::ErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ErrorPrototype* errorPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, errorPrototype->classInfo()->className))
 {
     // ECMA 15.11.3.1 Error.prototype
-    putDirectWithoutTransition(exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, errorPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum);
 }
 
 // ECMA 15.9.3
-ErrorInstance* constructError(ExecState* exec, const ArgList& args)
-{
-    ErrorInstance* obj = new (exec) ErrorInstance(exec->lexicalGlobalObject()->errorStructure());
-    if (!args.at(0).isUndefined())
-        obj->putDirect(exec->propertyNames().message, jsString(exec, args.at(0).toString(exec)));
-    return obj;
-}
 
-static JSObject* constructWithErrorConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithErrorConstructor(ExecState* exec)
 {
-    return constructError(exec, args);
+    JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
+    Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure();
+    return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
 ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
@@ -57,11 +52,11 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
-// ECMA 15.9.2
-static JSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callErrorConstructor(ExecState* exec)
 {
-    // "Error()" gives the sames result as "new Error()"
-    return constructError(exec, args);
+    JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
+    Structure* errorStructure = asInternalFunction(exec->callee())->globalObject()->errorStructure();
+    return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
 CallType ErrorConstructor::getCallData(CallData& callData)
index e3d789b0d60864544ef5b4029fdf9418f06a452c..ceec005be802fd3529141146072bf21c537eaf82 100644 (file)
@@ -30,15 +30,13 @@ namespace JSC {
 
     class ErrorConstructor : public InternalFunction {
     public:
-        ErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, ErrorPrototype*);
+        ErrorConstructor(ExecState*, JSGlobalObject*, Structure*, ErrorPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
-    ErrorInstance* constructError(ExecState*, const ArgList&);
-
 } // namespace JSC
 
 #endif // ErrorConstructor_h
index 1cdb87a5a9169c925ffc67e4b47efa50184351aa..ed95ba4a1778def2a4aae986e40e2b0f82154791 100644 (file)
 
 namespace JSC {
 
-const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 };
+const ClassInfo ErrorInstance::s_info = { "Error", &JSNonFinalObject::s_info, 0, 0 };
 
-ErrorInstance::ErrorInstance(NonNullPassRefPtr<Structure> structure)
-    : JSObject(structure)
+ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure)
+    : JSNonFinalObject(*globalData, structure)
+    , m_appendSourceToMessage(false)
 {
+    ASSERT(inherits(&s_info));
+    putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, ""));
+}
+
+ErrorInstance::ErrorInstance(JSGlobalData* globalData, Structure* structure, const UString& message)
+    : JSNonFinalObject(*globalData, structure)
+    , m_appendSourceToMessage(false)
+{
+    ASSERT(inherits(&s_info));
+    putDirect(*globalData, globalData->propertyNames->message, jsString(globalData, message));
+}
+
+ErrorInstance* ErrorInstance::create(JSGlobalData* globalData, Structure* structure, const UString& message)
+{
+    return new (globalData) ErrorInstance(globalData, structure, message);
+}
+
+ErrorInstance* ErrorInstance::create(ExecState* exec, Structure* structure, JSValue message)
+{
+    if (message.isUndefined())
+        return new (exec) ErrorInstance(&exec->globalData(), structure);
+    return new (exec) ErrorInstance(&exec->globalData(), structure, message.toString(exec));
 }
 
 } // namespace JSC
index 9f53b5154a345d923a430a944ee901a5e23d33bf..afcf158ad3ae7e70ce384dca44c54e574ef9e85d 100644 (file)
 
 namespace JSC {
 
-    class ErrorInstance : public JSObject {
+    class ErrorInstance : public JSNonFinalObject {
     public:
-        explicit ErrorInstance(NonNullPassRefPtr<Structure>);
+        static const ClassInfo s_info;
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+        static ErrorInstance* create(JSGlobalData*, Structure*, const UString&);
+        static ErrorInstance* create(ExecState*, Structure*, JSValue message);
+
+
+        bool appendSourceToMessage() { return m_appendSourceToMessage; }
+        void setAppendSourceToMessage() { m_appendSourceToMessage = true; }
+        void clearAppendSourceToMessage() { m_appendSourceToMessage = false; }
+
+        virtual bool isErrorInstance() const { return true; }
+
+    protected:
+        explicit ErrorInstance(JSGlobalData*, Structure*);
+        explicit ErrorInstance(JSGlobalData*, Structure*, const UString&);
+
+        bool m_appendSourceToMessage;
     };
 
 } // namespace JSC
index eb357337ce22e2a7ca4f73e6b29810f443e52151..2a513d59c7ae9ff12695098d08f77fc4916656e1 100644 (file)
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
+#include "StringRecursionChecker.h"
 #include "UString.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
 
-static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*);
 
-// ECMA 15.9.4
-ErrorPrototype::ErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
-    : ErrorInstance(structure)
+}
+
+#include "ErrorPrototype.lut.h"
+
+namespace JSC {
+
+const ClassInfo ErrorPrototype::s_info = { "Error", &ErrorInstance::s_info, 0, ExecState::errorPrototypeTable };
+
+/* Source for ErrorPrototype.lut.h
+@begin errorPrototypeTable
+  toString          errorProtoFuncToString         DontEnum|Function 0
+@end
+*/
+
+ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype);
+
+ErrorPrototype::ErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+    : ErrorInstance(&exec->globalData(), structure)
 {
-    // The constructor will be added later in ErrorConstructor's constructor
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
 
-    putDirectWithoutTransition(exec->propertyNames().name, jsNontrivialString(exec, "Error"), DontEnum);
-    putDirectWithoutTransition(exec->propertyNames().message, jsNontrivialString(exec, "Unknown error"), DontEnum);
+    ASSERT(inherits(&s_info));
+    putAnonymousValue(globalObject->globalData(), 0, globalObject);
+}
+
+bool ErrorPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<ErrorInstance>(exec, ExecState::errorPrototypeTable(exec), this, propertyName, slot);
+}
 
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, errorProtoFuncToString), DontEnum);
+bool ErrorPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<ErrorInstance>(exec, ExecState::errorPrototypeTable(exec), this, propertyName, descriptor);
 }
 
-JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+// ------------------------------ Functions ---------------------------
+
+EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
 {
-    JSObject* thisObj = thisValue.toThisObject(exec);
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
+
+    StringRecursionChecker checker(exec, thisObj);
+    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+        return earlyReturnValue;
+
     JSValue name = thisObj->get(exec, exec->propertyNames().name);
     JSValue message = thisObj->get(exec, exec->propertyNames().message);
 
@@ -56,12 +86,12 @@ JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue
 
     if (!name.isUndefined()) {
         if (!message.isUndefined())
-            return jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec));
-        return jsNontrivialString(exec, name.toString(exec));
+            return JSValue::encode(jsMakeNontrivialString(exec, name.toString(exec), ": ", message.toString(exec)));
+        return JSValue::encode(jsNontrivialString(exec, name.toString(exec)));
     }
     if (!message.isUndefined())
-        return jsMakeNontrivialString(exec, "Error: ", message.toString(exec));
-    return jsNontrivialString(exec, "Error");
+        return JSValue::encode(jsMakeNontrivialString(exec, "Error: ", message.toString(exec)));
+    return JSValue::encode(jsNontrivialString(exec, "Error"));
 }
 
 } // namespace JSC
index a5615902d30142b953a8af2275162cd6ea957747..a5c88634fb7cfa1dcc18538641779654aefd577b 100644 (file)
@@ -29,7 +29,22 @@ namespace JSC {
 
     class ErrorPrototype : public ErrorInstance {
     public:
-        ErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        ErrorPrototype(ExecState*, JSGlobalObject*, Structure*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ErrorInstance::StructureFlags;
+        static const unsigned AnonymousSlotCount = ErrorInstance::AnonymousSlotCount + 1;
+
+    private:
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
index aee6f31255c734c36be9b83556319f2740f09386..1d743153ca176ae51513aacdffdb2d62887bc736 100644 (file)
 
 #include "CodeBlock.h"
 #include "CallFrame.h"
+#include "ErrorInstance.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSObject.h"
 #include "JSNotAnObject.h"
 #include "Interpreter.h"
 #include "Nodes.h"
+#include "UStringConcatenate.h"
 
 namespace JSC {
 
-class InterruptedExecutionError : public JSObject {
+class InterruptedExecutionError : public JSNonFinalObject {
 public:
     InterruptedExecutionError(JSGlobalData* globalData)
-        : JSObject(globalData->interruptedExecutionErrorStructure)
+        : JSNonFinalObject(*globalData, globalData->interruptedExecutionErrorStructure.get())
     {
     }
 
@@ -51,15 +53,15 @@ public:
     virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; }
 };
 
-JSValue createInterruptedExecutionException(JSGlobalData* globalData)
+JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
 {
     return new (globalData) InterruptedExecutionError(globalData);
 }
 
-class TerminatedExecutionError : public JSObject {
+class TerminatedExecutionError : public JSNonFinalObject {
 public:
     TerminatedExecutionError(JSGlobalData* globalData)
-        : JSObject(globalData->terminatedExecutionErrorStructure)
+        : JSNonFinalObject(*globalData, globalData->terminatedExecutionErrorStructure.get())
     {
     }
 
@@ -68,146 +70,81 @@ public:
     virtual UString toString(ExecState*) const { return "JavaScript execution terminated."; }
 };
 
-JSValue createTerminatedExecutionException(JSGlobalData* globalData)
+JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
 {
     return new (globalData) TerminatedExecutionError(globalData);
 }
 
-static JSValue createError(ExecState* exec, ErrorType e, const char* msg)
+JSObject* createStackOverflowError(ExecState* exec)
 {
-    return Error::create(exec, e, msg, -1, -1, UString());
+    return createRangeError(exec, "Maximum call stack size exceeded.");
 }
 
-JSValue createStackOverflowError(ExecState* exec)
+JSObject* createStackOverflowError(JSGlobalObject* globalObject)
 {
-    return createError(exec, RangeError, "Maximum call stack size exceeded.");
+    return createRangeError(globalObject, "Maximum call stack size exceeded.");
 }
 
-JSValue createTypeError(ExecState* exec, const char* message)
+JSObject* createUndefinedVariableError(ExecState* exec, const Identifier& ident)
 {
-    return createError(exec, TypeError, message);
-}
-
-JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
-{
-    int startOffset = 0;
-    int endOffset = 0;
-    int divotPoint = 0;
-    int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-    JSObject* exception = Error::create(exec, ReferenceError, makeString("Can't find variable: ", ident.ustring()), line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
-    exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
-    return exception;
+    UString message(makeUString("Can't find variable: ", ident.ustring()));
+    return createReferenceError(exec, message);
 }
     
-static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error)
+JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value)
 {
-    if (!expressionStop || expressionStart > codeBlock->source()->length())
-        return makeString(value.toString(exec), " is ", error);
-    if (expressionStart < expressionStop)
-        return makeString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, ".");
-
-    // No range information, so give a few characters of context
-    const UChar* data = codeBlock->source()->data();
-    int dataLength = codeBlock->source()->length();
-    int start = expressionStart;
-    int stop = expressionStart;
-    // Get up to 20 characters of context to the left and right of the divot, clamping to the line.
-    // then strip whitespace.
-    while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n')
-        start--;
-    while (start < (expressionStart - 1) && isStrWhiteSpace(data[start]))
-        start++;
-    while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n')
-        stop++;
-    while (stop > expressionStart && isStrWhiteSpace(data[stop]))
-        stop--;
-    return makeString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, ".");
+    UString errorMessage = makeUString("'", value.toString(exec), "' is not a valid argument for '", op, "'");
+    JSObject* exception = createTypeError(exec, errorMessage);
+    ASSERT(exception->isErrorInstance());
+    static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
+    return exception;
 }
 
-JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSObject* createNotAConstructorError(ExecState* exec, JSValue value)
 {
-    int startOffset = 0;
-    int endOffset = 0;
-    int divotPoint = 0;
-    int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-    UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, makeString("not a valid argument for '", op, "'"));
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
-    exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+    UString errorMessage = makeUString("'", value.toString(exec), "' is not a constructor");
+    JSObject* exception = createTypeError(exec, errorMessage);
+    ASSERT(exception->isErrorInstance());
+    static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     return exception;
 }
 
-JSObject* createNotAConstructorError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSObject* createNotAFunctionError(ExecState* exec, JSValue value)
 {
-    int startOffset = 0;
-    int endOffset = 0;
-    int divotPoint = 0;
-    int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-
-    // We're in a "new" expression, so we need to skip over the "new.." part
-    int startPoint = divotPoint - (startOffset ? startOffset - 4 : 0); // -4 for "new "
-    const UChar* data = codeBlock->source()->data();
-    while (startPoint < divotPoint && isStrWhiteSpace(data[startPoint]))
-        startPoint++;
-    
-    UString errorMessage = createErrorMessage(exec, codeBlock, line, startPoint, divotPoint, value, "not a constructor");
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
-    exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+    UString errorMessage = makeUString("'", value.toString(exec), "' is not a function");
+    JSObject* exception = createTypeError(exec, errorMessage);
+    ASSERT(exception->isErrorInstance());
+    static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     return exception;
 }
 
-JSValue createNotAFunctionError(ExecState* exec, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSObject* createNotAnObjectError(ExecState* exec, JSValue value)
 {
-    int startOffset = 0;
-    int endOffset = 0;
-    int divotPoint = 0;
-    int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-    UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, value, "not a function");
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());    
-    exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
+    UString errorMessage = makeUString("'", value.toString(exec), "' is not an object");
+    JSObject* exception = createTypeError(exec, errorMessage);
+    ASSERT(exception->isErrorInstance());
+    static_cast<ErrorInstance*>(exception)->setAppendSourceToMessage();
     return exception;
 }
 
-JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState* exec, bool isNull)
+JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName)
 {
-    return new (exec) JSNotAnObjectErrorStub(exec, isNull);
+    return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'"));
 }
 
-JSObject* createNotAnObjectError(ExecState* exec, JSNotAnObjectErrorStub* error, unsigned bytecodeOffset, CodeBlock* codeBlock)
+JSObject* createOutOfMemoryError(JSGlobalObject* globalObject)
 {
-    // Both op_construct and op_instanceof require a use of op_get_by_id to get
-    // the prototype property from an object. The exception messages for exceptions
-    // thrown by these instances op_get_by_id need to reflect this.
-    OpcodeID followingOpcodeID;
-    if (codeBlock->getByIdExceptionInfoForBytecodeOffset(exec, bytecodeOffset, followingOpcodeID)) {
-        ASSERT(followingOpcodeID == op_construct || followingOpcodeID == op_instanceof);
-        if (followingOpcodeID == op_construct)
-            return createNotAConstructorError(exec, error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock);
-        return createInvalidParamError(exec, "instanceof", error->isNull() ? jsNull() : jsUndefined(), bytecodeOffset, codeBlock);
-    }
+    return createError(globalObject, "Out of memory");
+}
 
-    int startOffset = 0;
-    int endOffset = 0;
-    int divotPoint = 0;
-    int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset);
-    UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint - startOffset, divotPoint, error->isNull() ? jsNull() : jsUndefined(), "not an object");
-    JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL());
-    exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete);
-    exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete);
-    return exception;
+JSObject* throwOutOfMemoryError(ExecState* exec)
+{
+    return throwError(exec, createOutOfMemoryError(exec->lexicalGlobalObject()));
 }
 
-JSValue throwOutOfMemoryError(ExecState* exec)
+JSObject* throwStackOverflowError(ExecState* exec)
 {
-    return throwError(exec, GeneralError, "Out of memory");
+    return throwError(exec, createStackOverflowError(exec));
 }
 
 } // namespace JSC
index b15243922c543b142a712bbd0962cf121f9b3c32..5f1ec6f1c24443558239ff69e804a5f7249c1480 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef ExceptionHelpers_h
 #define ExceptionHelpers_h
 
+#include "JSValue.h"
 
 namespace JSC {
 
@@ -36,23 +37,26 @@ namespace JSC {
     class ExecState;
     class Identifier;
     class JSGlobalData;
+    class JSGlobalObject;
     class JSNotAnObjectErrorStub;
     class JSObject;
-    class JSValue;
     class Node;
     struct Instruction;
     
-    JSValue createInterruptedExecutionException(JSGlobalData*);
-    JSValue createTerminatedExecutionException(JSGlobalData*);
-    JSValue createStackOverflowError(ExecState*);
-    JSValue createTypeError(ExecState*, const char* message);
-    JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
-    JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
-    JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
-    JSObject* createNotAConstructorError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
-    JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
-    JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*);
-    JSValue throwOutOfMemoryError(ExecState*);
+    JSObject* createInterruptedExecutionException(JSGlobalData*);
+    JSObject* createTerminatedExecutionException(JSGlobalData*);
+    JSObject* createStackOverflowError(ExecState*);
+    JSObject* createStackOverflowError(JSGlobalObject*);
+    JSObject* createOutOfMemoryError(JSGlobalObject*);
+    JSObject* createUndefinedVariableError(ExecState*, const Identifier&);
+    JSObject* createNotAnObjectError(ExecState*, JSValue);
+    JSObject* createInvalidParamError(ExecState*, const char* op, JSValue);
+    JSObject* createNotAConstructorError(ExecState*, JSValue);
+    JSObject* createNotAFunctionError(ExecState*, JSValue);
+    JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const UString&);
+
+    JSObject* throwOutOfMemoryError(ExecState*);
+    JSObject* throwStackOverflowError(ExecState*);
 
 } // namespace JSC
 
index 765bd99173f44c05751cae7274709d7912428ab9..5fa560eee8ec45fcce07ba19db9cc9e0689b0909 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "CodeBlock.h"
 #include "JIT.h"
 #include "Parser.h"
-#include "StringBuilder.h"
+#include "UStringBuilder.h"
 #include "Vector.h"
 
+#if ENABLE(DFG_JIT)
+#include "DFGByteCodeParser.h"
+#include "DFGJITCompiler.h"
+#endif
+
 namespace JSC {
 
+const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 };
+
 #if ENABLE(JIT)
-NativeExecutable::~NativeExecutable()
+class ExecutableFinalizer : public WeakHandleOwner {
+    virtual void finalize(Handle<Unknown> handle, void*)
+    {
+        Weak<ExecutableBase> executable(Weak<ExecutableBase>::Adopt, handle);
+        executable->clearExecutableCode();
+    }
+};
+
+WeakHandleOwner* ExecutableBase::executableFinalizer()
 {
+    DEFINE_STATIC_LOCAL(ExecutableFinalizer, finalizer, ());
+    return &finalizer;
 }
 #endif
+    
+const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0 };
 
-VPtrHackExecutable::~VPtrHackExecutable()
+NativeExecutable::~NativeExecutable()
+{
+}
+
+const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0 };
+
+const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, 0 };
+
+EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
+    : ScriptExecutable(exec->globalData().evalExecutableStructure.get(), exec, source, inStrictContext)
 {
 }
 
 EvalExecutable::~EvalExecutable()
 {
-    delete m_evalCodeBlock;
+}
+
+const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, 0 };
+
+ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
+    : ScriptExecutable(exec->globalData().programExecutableStructure.get(), exec, source, false)
+{
 }
 
 ProgramExecutable::~ProgramExecutable()
 {
-    delete m_programCodeBlock;
 }
 
-FunctionExecutable::~FunctionExecutable()
+const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, 0 };
+
+FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
+    : ScriptExecutable(globalData->functionExecutableStructure.get(), globalData, source, inStrictContext)
+    , m_numCapturedVariables(0)
+    , m_forceUsesArguments(forceUsesArguments)
+    , m_parameters(parameters)
+    , m_name(name)
+    , m_symbolTable(0)
 {
-    delete m_codeBlock;
+    m_firstLine = firstLine;
+    m_lastLine = lastLine;
 }
 
-JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool inStrictContext, int firstLine, int lastLine)
+    : ScriptExecutable(exec->globalData().functionExecutableStructure.get(), exec, source, inStrictContext)
+    , m_numCapturedVariables(0)
+    , m_forceUsesArguments(forceUsesArguments)
+    , m_parameters(parameters)
+    , m_name(name)
+    , m_symbolTable(0)
 {
-    int errLine;
-    UString errMsg;
-    RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
-    if (!evalNode)
-        return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
-    recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
+    m_firstLine = firstLine;
+    m_lastLine = lastLine;
+}
 
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
+
+JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
+{
+    JSObject* exception = 0;
+    JSGlobalData* globalData = &exec->globalData();
+    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
+    if (!lexicalGlobalObject->isEvalEnabled())
+        return throwError(exec, createEvalError(exec, "Eval is disabled"));
+    RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
+    if (!evalNode) {
+        ASSERT(exception);
+        return exception;
+    }
+    recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine());
+
+    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
 
     ASSERT(!m_evalCodeBlock);
-    m_evalCodeBlock = new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth());
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock));
-    generator->generate();
-    
+    m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChainNode->localDepth()));
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChainNode, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get())));
+    if ((exception = generator->generate())) {
+        m_evalCodeBlock.clear();
+        evalNode->destroyData();
+        return exception;
+    }
+
     evalNode->destroyData();
+
+#if ENABLE(JIT)
+    if (exec->globalData().canUseJIT()) {
+        m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock.get());
+#if !ENABLE(OPCODE_SAMPLING)
+        if (!BytecodeGenerator::dumpsGeneratedCode())
+            m_evalCodeBlock->discardBytecode();
+#endif
+    }
+#endif
+
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+    if (!m_jitCodeForCall)
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
+    else
+#endif
+    Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size());
+#else
+    Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock));
+#endif
+
     return 0;
 }
 
-JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
+void EvalExecutable::visitChildren(SlotVisitor& visitor)
 {
-    int errLine;
-    UString errMsg;
-    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
-    if (!programNode)
-        return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
-    return 0;
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    ScriptExecutable::visitChildren(visitor);
+    if (m_evalCodeBlock)
+        m_evalCodeBlock->visitAggregate(visitor);
 }
 
-JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+void EvalExecutable::unlinkCalls()
 {
-    int errLine;
-    UString errMsg;
-    RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
-    if (!programNode)
-        return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
-    recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine());
-
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
-    
-    ASSERT(!m_programCodeBlock);
-    m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider());
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock));
-    generator->generate();
+#if ENABLE(JIT)
+    if (!m_jitCodeForCall)
+        return;
+    ASSERT(m_evalCodeBlock);
+    m_evalCodeBlock->unlinkCalls();
+#endif
+}
 
-    programNode->destroyData();
-    return 0;
+JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
+{
+    JSObject* exception = 0;
+    JSGlobalData* globalData = &exec->globalData();
+    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
+    RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, JSParseNormal, &exception);
+    if (programNode)
+        return 0;
+    ASSERT(exception);
+    return exception;
 }
 
-void FunctionExecutable::compile(ExecState*, ScopeChainNode* scopeChainNode)
+JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
 {
-    JSGlobalData* globalData = scopeChainNode->globalData;
-    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
-    if (m_forceUsesArguments)
-        body->setUsesArguments();
-    body->finishParsing(m_parameters, m_name);
-    recordParse(body->features(), body->lineNo(), body->lastLine());
+    ASSERT(!m_programCodeBlock);
 
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
+    JSObject* exception = 0;
+    JSGlobalData* globalData = &exec->globalData();
+    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
+    RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
+    if (!programNode) {
+        ASSERT(exception);
+        return exception;
+    }
+    recordParse(programNode->features(), programNode->hasCapturedVariables(), programNode->lineNo(), programNode->lastLine());
 
-    ASSERT(!m_codeBlock);
-    m_codeBlock = new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset());
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlock->symbolTable(), m_codeBlock));
-    generator->generate();
-    m_numParameters = m_codeBlock->m_numParameters;
-    ASSERT(m_numParameters);
-    m_numVariables = m_codeBlock->m_numVars;
+    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
+    
+    m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), scopeChainNode, &globalObject->symbolTable(), m_programCodeBlock.get())));
+    if ((exception = generator->generate())) {
+        m_programCodeBlock.clear();
+        programNode->destroyData();
+        return exception;
+    }
 
-    body->destroyData();
-}
+    programNode->destroyData();
 
 #if ENABLE(JIT)
+    if (exec->globalData().canUseJIT()) {
+        m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get());
+#if !ENABLE(OPCODE_SAMPLING)
+        if (!BytecodeGenerator::dumpsGeneratedCode())
+            m_programCodeBlock->discardBytecode();
+#endif
+    }
+#endif
 
-void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
-{
+#if ENABLE(JIT)
 #if ENABLE(INTERPRETER)
-    ASSERT(scopeChainNode->globalData->canUseJIT());
+    if (!m_jitCodeForCall)
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
+    else
 #endif
-    CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
-    m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
-
-#if !ENABLE(OPCODE_SAMPLING)
-    if (!BytecodeGenerator::dumpsGeneratedCode())
-        codeBlock->discardBytecode();
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock) + m_jitCodeForCall.size());
+#else
+    Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
 #endif
+
+    return 0;
 }
 
-void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+void ProgramExecutable::unlinkCalls()
 {
-#if ENABLE(INTERPRETER)
-    ASSERT(scopeChainNode->globalData->canUseJIT());
-#endif
-    CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
-    m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
-
-#if !ENABLE(OPCODE_SAMPLING)
-    if (!BytecodeGenerator::dumpsGeneratedCode())
-        codeBlock->discardBytecode();
+#if ENABLE(JIT)
+    if (!m_jitCodeForCall)
+        return;
+    ASSERT(m_programCodeBlock);
+    m_programCodeBlock->unlinkCalls();
 #endif
 }
 
-void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+#if ENABLE(JIT)
+static bool tryDFGCompile(JSGlobalData* globalData, CodeBlock* codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck)
 {
-#if ENABLE(INTERPRETER)
-    ASSERT(scopeChainNode->globalData->canUseJIT());
+#if ENABLE(DFG_JIT)
+#if ENABLE(DFG_JIT_RESTRICTIONS)
+    // FIXME: No flow control yet supported, don't bother scanning the bytecode if there are any jump targets.
+    // FIXME: temporarily disable property accesses until we fix regressions.
+    if (codeBlock->numberOfJumpTargets() || codeBlock->numberOfStructureStubInfos())
+        return false;
 #endif
-    CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
-    m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
 
-#if !ENABLE(OPCODE_SAMPLING)
-    if (!BytecodeGenerator::dumpsGeneratedCode())
-        codeBlock->discardBytecode();
+    DFG::Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
+    if (!parse(dfg, globalData, codeBlock))
+        return false;
+
+    DFG::JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
+    dataFlowJIT.compileFunction(jitCode, jitCodeWithArityCheck);
+    return true;
+#else
+    UNUSED_PARAM(globalData);
+    UNUSED_PARAM(codeBlock);
+    UNUSED_PARAM(jitCode);
+    UNUSED_PARAM(jitCodeWithArityCheck);
+    return false;
 #endif
 }
-
 #endif
 
-void FunctionExecutable::markAggregate(MarkStack& markStack)
+void ProgramExecutable::visitChildren(SlotVisitor& visitor)
 {
-    if (m_codeBlock)
-        m_codeBlock->markAggregate(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    ScriptExecutable::visitChildren(visitor);
+    if (m_programCodeBlock)
+        m_programCodeBlock->visitAggregate(visitor);
 }
 
-ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
 {
-    RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+    JSObject* exception = 0;
+    JSGlobalData* globalData = scopeChainNode->globalData;
+    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
+    if (!body) {
+        ASSERT(exception);
+        return exception;
+    }
     if (m_forceUsesArguments)
-        newFunctionBody->setUsesArguments();
-    newFunctionBody->finishParsing(m_parameters, m_name);
+        body->setUsesArguments();
+    body->finishParsing(m_parameters, m_name);
+    recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
 
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
+    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
 
-    OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
-    globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
+    ASSERT(!m_codeBlockForCall);
+    m_codeBlockForCall = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), false));
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChainNode, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get())));
+    if ((exception = generator->generate())) {
+        m_codeBlockForCall.clear();
+        body->destroyData();
+        return exception;
+    }
 
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
-    generator->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock*>(codeBlock));
-    generator->generate();
+    m_numParametersForCall = m_codeBlockForCall->m_numParameters;
+    ASSERT(m_numParametersForCall);
+    m_numCapturedVariables = m_codeBlockForCall->m_numCapturedVars;
+    m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
 
-    ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
+    body->destroyData();
 
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
-    if (globalData->canUseJIT())
+    if (exec->globalData().canUseJIT()) {
+        bool dfgCompiled = tryDFGCompile(&exec->globalData(), m_codeBlockForCall.get(), m_jitCodeForCall, m_jitCodeForCallWithArityCheck);
+        if (!dfgCompiled)
+            m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
+
+#if !ENABLE(OPCODE_SAMPLING)
+        if (!BytecodeGenerator::dumpsGeneratedCode())
+            m_codeBlockForCall->discardBytecode();
 #endif
-    {
-        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), generatedJITCode().start());
-        ASSERT(newJITCode.size() == generatedJITCode().size());
     }
 #endif
 
-    globalData->functionCodeBlockBeingReparsed = 0;
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+    if (!m_jitCodeForCall)
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
+    else
+#endif
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall) + m_jitCodeForCall.size());
+#else
+    Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForCall));
+#endif
 
-    return newCodeBlock->extractExceptionInfo();
+    return 0;
 }
 
-ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
+JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
 {
-    RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
+    JSObject* exception = 0;
+    JSGlobalData* globalData = scopeChainNode->globalData;
+    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(exec->lexicalGlobalObject(), 0, 0, m_source, m_parameters.get(), isStrictMode() ? JSParseStrict : JSParseNormal, &exception);
+    if (!body) {
+        ASSERT(exception);
+        return exception;
+    }
+    if (m_forceUsesArguments)
+        body->setUsesArguments();
+    body->finishParsing(m_parameters, m_name);
+    recordParse(body->features(), body->hasCapturedVariables(), body->lineNo(), body->lastLine());
 
-    ScopeChain scopeChain(scopeChainNode);
-    JSGlobalObject* globalObject = scopeChain.globalObject();
+    JSGlobalObject* globalObject = scopeChainNode->globalObject.get();
 
-    OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
+    ASSERT(!m_codeBlockForConstruct);
+    m_codeBlockForConstruct = adoptPtr(new FunctionCodeBlock(this, FunctionCode, globalObject, source().provider(), source().startOffset(), true));
+    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), scopeChainNode, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get())));
+    if ((exception = generator->generate())) {
+        m_codeBlockForConstruct.clear();
+        body->destroyData();
+        return exception;
+    }
 
-    OwnPtr<BytecodeGenerator> generator(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get()));
-    generator->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock*>(codeBlock));
-    generator->generate();
+    m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters;
+    ASSERT(m_numParametersForConstruct);
+    m_numCapturedVariables = m_codeBlockForConstruct->m_numCapturedVars;
+    m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
 
-    ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
+    body->destroyData();
 
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
-    if (globalData->canUseJIT())
+    if (exec->globalData().canUseJIT()) {
+        m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, m_codeBlockForConstruct.get(), &m_jitCodeForConstructWithArityCheck);
+#if !ENABLE(OPCODE_SAMPLING)
+        if (!BytecodeGenerator::dumpsGeneratedCode())
+            m_codeBlockForConstruct->discardBytecode();
 #endif
-    {
-        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), generatedJITCode().start());
-        ASSERT(newJITCode.size() == generatedJITCode().size());
     }
 #endif
 
-    return newCodeBlock->extractExceptionInfo();
+#if ENABLE(JIT)
+#if ENABLE(INTERPRETER)
+    if (!m_jitCodeForConstruct)
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
+    else
+#endif
+    Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct) + m_jitCodeForConstruct.size());
+#else
+    Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_codeBlockForConstruct));
+#endif
+
+    return 0;
+}
+
+void FunctionExecutable::visitChildren(SlotVisitor& visitor)
+{
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    ScriptExecutable::visitChildren(visitor);
+    if (m_codeBlockForCall)
+        m_codeBlockForCall->visitAggregate(visitor);
+    if (m_codeBlockForConstruct)
+        m_codeBlockForConstruct->visitAggregate(visitor);
 }
 
-void FunctionExecutable::recompile()
+void FunctionExecutable::discardCode()
 {
-    delete m_codeBlock;
-    m_codeBlock = 0;
-    m_numParameters = NUM_PARAMETERS_NOT_COMPILED;
 #if ENABLE(JIT)
-    m_jitCode = JITCode();
+    // These first two checks are to handle the rare case where
+    // we are trying to evict code for a function during its
+    // codegen.
+    if (!m_jitCodeForCall && m_codeBlockForCall)
+        return;
+    if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
+        return;
+    m_jitCodeForCall = JITCode();
+    m_jitCodeForConstruct = JITCode();
+    m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();
+    m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();
 #endif
+    if (m_codeBlockForCall)
+        m_codeBlockForCall->clearEvalCache();
+    m_codeBlockForCall.clear();
+    if (m_codeBlockForConstruct)
+        m_codeBlockForConstruct->clearEvalCache();
+    m_codeBlockForConstruct.clear();
+    m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
+    m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
+
 }
 
-PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
+void FunctionExecutable::unlinkCalls()
 {
-    RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg);
-    if (!program)
+#if ENABLE(JIT)
+    if (!!m_jitCodeForCall) {
+        ASSERT(m_codeBlockForCall);
+        m_codeBlockForCall->unlinkCalls();
+    }
+    if (!!m_jitCodeForConstruct) {
+        ASSERT(m_codeBlockForConstruct);
+        m_codeBlockForConstruct->unlinkCalls();
+    }
+#endif
+}
+
+FunctionExecutable* FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
+{
+    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
+    RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(lexicalGlobalObject, debugger, exec, source, 0, JSParseNormal, exception);
+    if (!program) {
+        ASSERT(*exception);
         return 0;
+    }
 
+    // Uses of this function that would not result in a single function expression are invalid.
     StatementNode* exprStatement = program->singleStatement();
     ASSERT(exprStatement);
     ASSERT(exprStatement->isExprStatement());
-    if (!exprStatement || !exprStatement->isExprStatement())
-        return 0;
-
     ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
     ASSERT(funcExpr);
     ASSERT(funcExpr->isFuncExprNode());
-    if (!funcExpr || !funcExpr->isFuncExprNode())
-        return 0;
-
     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
     ASSERT(body);
-    return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
+
+    return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
 }
 
 UString FunctionExecutable::paramString() const
 {
     FunctionParameters& parameters = *m_parameters;
-    StringBuilder builder;
+    UStringBuilder builder;
     for (size_t pos = 0; pos < parameters.size(); ++pos) {
         if (!builder.isEmpty())
             builder.append(", ");
         builder.append(parameters[pos].ustring());
     }
-    return builder.build();
+    return builder.toUString();
 }
 
-};
-
-
+}
index dec841a0ef4b28cf1ab7ae55544eb3421748997d..e795fbfc3123e3f72b25f7aa320832b5d2a22520 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #ifndef Executable_h
 #define Executable_h
 
+#include "CallData.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "Nodes.h"
 #include "SamplingTool.h"
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
     class CodeBlock;
     class Debugger;
     class EvalCodeBlock;
+    class FunctionCodeBlock;
     class ProgramCodeBlock;
     class ScopeChainNode;
 
     struct ExceptionInfo;
 
-    class ExecutableBase : public RefCounted<ExecutableBase> {
+    class ExecutableBase : public JSCell {
         friend class JIT;
 
     protected:
@@ -49,67 +52,124 @@ namespace JSC {
         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
     
     public:
-        ExecutableBase(int numParameters)
-            : m_numParameters(numParameters)
+        ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters)
+            : JSCell(globalData, structure)
+            , m_numParametersForCall(numParameters)
+            , m_numParametersForConstruct(numParameters)
         {
+#if ENABLE(JIT)
+            Weak<ExecutableBase> finalizer(globalData, this, executableFinalizer());
+            finalizer.leakHandle();
+#endif
         }
 
-        virtual ~ExecutableBase() {}
+        bool isHostFunction() const
+        {
+            ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
+            return m_numParametersForCall == NUM_PARAMETERS_IS_HOST;
+        }
 
-        bool isHostFunction() const { return m_numParameters == NUM_PARAMETERS_IS_HOST; }
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
+        
+        static const ClassInfo s_info;
 
     protected:
-        int m_numParameters;
+        static const unsigned StructureFlags = 0;
+        int m_numParametersForCall;
+        int m_numParametersForConstruct;
 
 #if ENABLE(JIT)
     public:
-        JITCode& generatedJITCode()
+        JITCode& generatedJITCodeForCall()
         {
-            ASSERT(m_jitCode);
-            return m_jitCode;
+            ASSERT(m_jitCodeForCall);
+            return m_jitCodeForCall;
         }
 
-        ExecutablePool* getExecutablePool()
+        JITCode& generatedJITCodeForConstruct()
         {
-            return m_jitCode.getExecutablePool();
+            ASSERT(m_jitCodeForConstruct);
+            return m_jitCodeForConstruct;
+        }
+
+        void clearExecutableCode()
+        {
+            m_jitCodeForCall.clear();
+            m_jitCodeForConstruct.clear();
         }
 
     protected:
-        JITCode m_jitCode;
+        JITCode m_jitCodeForCall;
+        JITCode m_jitCodeForConstruct;
+        MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
+        MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
+        
+    private:
+        static WeakHandleOwner* executableFinalizer();
 #endif
     };
 
-#if ENABLE(JIT)
     class NativeExecutable : public ExecutableBase {
+        friend class JIT;
     public:
-        NativeExecutable(JITCode thunk)
-            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+#if ENABLE(JIT)
+        static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodePtr callThunk, NativeFunction function, MacroAssemblerCodePtr constructThunk, NativeFunction constructor)
         {
-            m_jitCode = thunk;
+            if (!callThunk)
+                return new (&globalData) NativeExecutable(globalData, JITCode(), function, JITCode(), constructor);
+            return new (&globalData) NativeExecutable(globalData, JITCode::HostFunction(callThunk), function, JITCode::HostFunction(constructThunk), constructor);
         }
+#else
+        static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
+        {
+            return new (&globalData) NativeExecutable(globalData, function, constructor);
+        }
+#endif
 
         ~NativeExecutable();
-    };
-#endif
 
-    class VPtrHackExecutable : public ExecutableBase {
-    public:
-        VPtrHackExecutable()
-            : ExecutableBase(NUM_PARAMETERS_IS_HOST)
+        NativeFunction function() { return m_function; }
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(LeafType, StructureFlags), AnonymousSlotCount, &s_info); }
+        
+        static const ClassInfo s_info;
+    
+    private:
+#if ENABLE(JIT)
+        NativeExecutable(JSGlobalData& globalData, JITCode callThunk, NativeFunction function, JITCode constructThunk, NativeFunction constructor)
+            : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
+            , m_function(function)
+            , m_constructor(constructor)
+        {
+            m_jitCodeForCall = callThunk;
+            m_jitCodeForConstruct = constructThunk;
+            m_jitCodeForCallWithArityCheck = callThunk.addressForCall();
+            m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall();
+        }
+#else
+        NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
+            : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
+            , m_function(function)
+            , m_constructor(constructor)
         {
         }
+#endif
 
-        ~VPtrHackExecutable();
+        NativeFunction m_function;
+        // Probably should be a NativeConstructor, but this will currently require rewriting the JIT
+        // trampoline. It may be easier to make NativeFunction be passed 'this' as a part of the ArgList.
+        NativeFunction m_constructor;
     };
 
     class ScriptExecutable : public ExecutableBase {
     public:
-        ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
-            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+        ScriptExecutable(Structure* structure, JSGlobalData* globalData, const SourceCode& source, bool isInStrictContext)
+            : ExecutableBase(*globalData, structure, NUM_PARAMETERS_NOT_COMPILED)
             , m_source(source)
-            , m_features(0)
+            , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
 #if ENABLE(CODEBLOCK_SAMPLING)
+            relaxAdoptionRequirement();
             if (SamplingTool* sampler = globalData->interpreter->sampler())
                 sampler->notifyOfScope(this);
 #else
@@ -117,12 +177,13 @@ namespace JSC {
 #endif
         }
 
-        ScriptExecutable(ExecState* exec, const SourceCode& source)
-            : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
+        ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
+            : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED)
             , m_source(source)
-            , m_features(0)
+            , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
 #if ENABLE(CODEBLOCK_SAMPLING)
+            relaxAdoptionRequirement();
             if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
                 sampler->notifyOfScope(this);
 #else
@@ -138,20 +199,24 @@ namespace JSC {
 
         bool usesEval() const { return m_features & EvalFeature; }
         bool usesArguments() const { return m_features & ArgumentsFeature; }
-        bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
-
-        virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
+        bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); }
+        bool isStrictMode() const { return m_features & StrictModeFeature; }
 
+        virtual void unlinkCalls() = 0;
+        
+        static const ClassInfo s_info;
     protected:
-        void recordParse(CodeFeatures features, int firstLine, int lastLine)
+        void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
         {
             m_features = features;
+            m_hasCapturedVariables = hasCapturedVariables;
             m_firstLine = firstLine;
             m_lastLine = lastLine;
         }
 
         SourceCode m_source;
         CodeFeatures m_features;
+        bool m_hasCapturedVariables;
         int m_firstLine;
         int m_lastLine;
     };
@@ -161,182 +226,219 @@ namespace JSC {
 
         ~EvalExecutable();
 
-        EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
-            if (!m_evalCodeBlock) {
-                JSObject* error = compile(exec, scopeChainNode);
-                ASSERT_UNUSED(!error, error);
-            }
-            return *m_evalCodeBlock;
+            ASSERT(exec->globalData().dynamicGlobalObject);
+            JSObject* error = 0;
+            if (!m_evalCodeBlock)
+                error = compileInternal(exec, scopeChainNode);
+            ASSERT(!error == !!m_evalCodeBlock);
+            return error;
         }
 
-        JSObject* compile(ExecState*, ScopeChainNode*);
-
-        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
-        static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
-
-    private:
-        EvalExecutable(ExecState* exec, const SourceCode& source)
-            : ScriptExecutable(exec, source)
-            , m_evalCodeBlock(0)
+        EvalCodeBlock& generatedBytecode()
         {
+            ASSERT(m_evalCodeBlock);
+            return *m_evalCodeBlock;
         }
-        EvalCodeBlock* m_evalCodeBlock;
+
+        static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) { return new (exec) EvalExecutable(exec, source, isInStrictContext); }
 
 #if ENABLE(JIT)
-    public:
-        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        JITCode& generatedJITCode()
         {
-            if (!m_jitCode)
-                generateJITCode(exec, scopeChainNode);
-            return m_jitCode;
+            return generatedJITCodeForCall();
         }
-
-    private:
-        void generateJITCode(ExecState*, ScopeChainNode*);
 #endif
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        {
+            return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+        
+        static const ClassInfo s_info;
+    private:
+        static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
+        EvalExecutable(ExecState*, const SourceCode&, bool);
+
+        JSObject* compileInternal(ExecState*, ScopeChainNode*);
+        virtual void visitChildren(SlotVisitor&);
+        void unlinkCalls();
+
+        OwnPtr<EvalCodeBlock> m_evalCodeBlock;
     };
 
     class ProgramExecutable : public ScriptExecutable {
     public:
-        static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
+        static ProgramExecutable* create(ExecState* exec, const SourceCode& source)
         {
-            return adoptRef(new ProgramExecutable(exec, source));
+            return new (exec) ProgramExecutable(exec, source);
         }
 
         ~ProgramExecutable();
 
-        ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            ASSERT(exec->globalData().dynamicGlobalObject);
+            JSObject* error = 0;
+            if (!m_programCodeBlock)
+                error = compileInternal(exec, scopeChainNode);
+            ASSERT(!error == !!m_programCodeBlock);
+            return error;
+        }
+
+        ProgramCodeBlock& generatedBytecode()
         {
-            if (!m_programCodeBlock) {
-                JSObject* error = compile(exec, scopeChainNode);
-                ASSERT_UNUSED(!error, error);
-            }
+            ASSERT(m_programCodeBlock);
             return *m_programCodeBlock;
         }
 
         JSObject* checkSyntax(ExecState*);
-        JSObject* compile(ExecState*, ScopeChainNode*);
-
-        // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
-        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; }
 
-    private:
-        ProgramExecutable(ExecState* exec, const SourceCode& source)
-            : ScriptExecutable(exec, source)
-            , m_programCodeBlock(0)
+#if ENABLE(JIT)
+        JITCode& generatedJITCode()
         {
+            return generatedJITCodeForCall();
         }
-        ProgramCodeBlock* m_programCodeBlock;
-
-#if ENABLE(JIT)
-    public:
-        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+#endif
+        
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
         {
-            if (!m_jitCode)
-                generateJITCode(exec, scopeChainNode);
-            return m_jitCode;
+            return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
 
     private:
-        void generateJITCode(ExecState*, ScopeChainNode*);
-#endif
+        static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
+        ProgramExecutable(ExecState*, const SourceCode&);
+
+        JSObject* compileInternal(ExecState*, ScopeChainNode*);
+        virtual void visitChildren(SlotVisitor&);
+        void unlinkCalls();
+
+        OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
 
     class FunctionExecutable : public ScriptExecutable {
         friend class JIT;
     public:
-        static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+        static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+            return new (exec) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
         }
 
-        static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
+        static FunctionExecutable* create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine)
         {
-            return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
+            return new (globalData) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext, firstLine, lastLine);
         }
 
-        ~FunctionExecutable();
-
         JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
         {
             return new (exec) JSFunction(exec, this, scopeChain);
         }
-
-        CodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) 
+        
+        // Returns either call or construct bytecode. This can be appropriate
+        // for answering questions that that don't vary between call and construct --
+        // for example, argumentsRegister().
+        FunctionCodeBlock& generatedBytecode()
         {
-            ASSERT(scopeChainNode);
-            if (!m_codeBlock)
-                compile(exec, scopeChainNode);
-            return *m_codeBlock;
+            if (m_codeBlockForCall)
+                return *m_codeBlockForCall;
+            ASSERT(m_codeBlockForConstruct);
+            return *m_codeBlockForConstruct;
         }
 
-        bool isGenerated() const
+        JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
         {
-            return m_codeBlock;
+            ASSERT(exec->globalData().dynamicGlobalObject);
+            JSObject* error = 0;
+            if (!m_codeBlockForCall)
+                error = compileForCallInternal(exec, scopeChainNode);
+            ASSERT(!error == !!m_codeBlockForCall);
+            return error;
         }
 
-        CodeBlock& generatedBytecode()
+        bool isGeneratedForCall() const
         {
-            ASSERT(m_codeBlock);
-            return *m_codeBlock;
+            return m_codeBlockForCall;
         }
 
-        const Identifier& name() { return m_name; }
-        size_t parameterCount() const { return m_parameters->size(); }
-        unsigned variableCount() const { return m_numVariables; }
-        UString paramString() const;
+        FunctionCodeBlock& generatedBytecodeForCall()
+        {
+            ASSERT(m_codeBlockForCall);
+            return *m_codeBlockForCall;
+        }
 
-        void recompile();
-        ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
-        void markAggregate(MarkStack& markStack);
-        static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
+        JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
+        {
+            ASSERT(exec->globalData().dynamicGlobalObject);
+            JSObject* error = 0;
+            if (!m_codeBlockForConstruct)
+                error = compileForConstructInternal(exec, scopeChainNode);
+            ASSERT(!error == !!m_codeBlockForConstruct);
+            return error;
+        }
 
-    private:
-        FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
-            : ScriptExecutable(globalData, source)
-            , m_numVariables(0)
-            , m_forceUsesArguments(forceUsesArguments)
-            , m_parameters(parameters)
-            , m_codeBlock(0)
-            , m_name(name)
+        bool isGeneratedForConstruct() const
         {
-            m_firstLine = firstLine;
-            m_lastLine = lastLine;
+            return m_codeBlockForConstruct;
         }
 
-        FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
-            : ScriptExecutable(exec, source)
-            , m_numVariables(0)
-            , m_forceUsesArguments(forceUsesArguments)
-            , m_parameters(parameters)
-            , m_codeBlock(0)
-            , m_name(name)
+        FunctionCodeBlock& generatedBytecodeForConstruct()
         {
-            m_firstLine = firstLine;
-            m_lastLine = lastLine;
+            ASSERT(m_codeBlockForConstruct);
+            return *m_codeBlockForConstruct;
         }
 
-        void compile(ExecState*, ScopeChainNode*);
+        const Identifier& name() { return m_name; }
+        size_t parameterCount() const { return m_parameters->size(); }
+        unsigned capturedVariableCount() const { return m_numCapturedVariables; }
+        UString paramString() const;
+        SharedSymbolTable* symbolTable() const { return m_symbolTable; }
+
+        void discardCode();
+        void visitChildren(SlotVisitor&);
+        static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        {
+            return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+        
+        static const ClassInfo s_info;
 
-        unsigned m_numVariables : 31;
+    private:
+        FunctionExecutable(JSGlobalData*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
+        FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool, int firstLine, int lastLine);
+
+        JSObject* compileForCallInternal(ExecState*, ScopeChainNode*);
+        JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*);
+        
+        static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
+        unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
+        void unlinkCalls();
 
         RefPtr<FunctionParameters> m_parameters;
-        CodeBlock* m_codeBlock;
+        OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
+        OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
         Identifier m_name;
+        SharedSymbolTable* m_symbolTable;
 
 #if ENABLE(JIT)
     public:
-        JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
+        MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck()
         {
-            if (!m_jitCode)
-                generateJITCode(exec, scopeChainNode);
-            return m_jitCode;
+            ASSERT(m_jitCodeForCall);
+            ASSERT(m_jitCodeForCallWithArityCheck);
+            return m_jitCodeForCallWithArityCheck;
         }
 
-    private:
-        void generateJITCode(ExecState*, ScopeChainNode*);
+        MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck()
+        {
+            ASSERT(m_jitCodeForConstruct);
+            ASSERT(m_jitCodeForConstructWithArityCheck);
+            return m_jitCodeForConstructWithArityCheck;
+        }
 #endif
     };
 
@@ -352,6 +454,11 @@ namespace JSC {
         return m_executable->isHostFunction();
     }
 
+    inline NativeFunction JSFunction::nativeFunction()
+    {
+        ASSERT(isHostFunction());
+        return static_cast<NativeExecutable*>(m_executable.get())->function();
+    }
 }
 
 #endif
index 9b0b1bbe46cbd8e03b630a79c1095f47ca5d876f..348d04ea4fe3b23b94604c41d3b18c8a61e641b8 100644 (file)
@@ -22,6 +22,7 @@
 #include "FunctionConstructor.h"
 
 #include "Debugger.h"
+#include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Lexer.h"
 #include "Nodes.h"
 #include "Parser.h"
-#include "StringBuilder.h"
+#include "UStringBuilder.h"
+#include "UStringConcatenate.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor);
 
-FunctionConstructor::FunctionConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className))
+FunctionConstructor::FunctionConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, functionPrototype->classInfo()->className))
 {
-    putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly);
 
     // Number of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontDelete | DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontDelete | DontEnum);
 }
 
-static JSObject* constructWithFunctionConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithFunctionConstructor(ExecState* exec)
 {
-    return constructFunction(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
@@ -55,9 +58,10 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData
     return ConstructTypeHost;
 }
 
-static JSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callFunctionConstructor(ExecState* exec)
 {
-    return constructFunction(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructFunction(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 // ECMA 15.3.1 The Function Constructor Called as a Function
@@ -68,7 +72,14 @@ CallType FunctionConstructor::getCallData(CallData& callData)
 }
 
 // ECMA 15.3.2 The Function Constructor
-JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
+JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
+{
+    if (!globalObject->isEvalEnabled())
+        return throwError(exec, createEvalError(exec, "Function constructor is disabled"));
+    return constructFunctionSkippingEvalEnabledCheck(exec, globalObject, args, functionName, sourceURL, lineNumber);
+}
+
+JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, const Identifier& functionName, const UString& sourceURL, int lineNumber)
 {
     // Functions need to have a space following the opening { due to for web compatibility
     // see https://bugs.webkit.org/show_bug.cgi?id=24350
@@ -77,9 +88,9 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
     if (args.isEmpty())
         program = "(function() { \n})";
     else if (args.size() == 1)
-        program = makeString("(function() { ", args.at(0).toString(exec), "\n})");
+        program = makeUString("(function() { ", args.at(0).toString(exec), "\n})");
     else {
-        StringBuilder builder;
+        UStringBuilder builder;
         builder.append("(function(");
         builder.append(args.at(0).toString(exec));
         for (size_t i = 1; i < args.size() - 1; i++) {
@@ -89,25 +100,26 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi
         builder.append(") { ");
         builder.append(args.at(args.size() - 1).toString(exec));
         builder.append("\n})");
-        program = builder.build();
+        program = builder.toUString();
     }
 
-    int errLine;
-    UString errMsg;
+    JSGlobalData& globalData = globalObject->globalData();
     SourceCode source = makeSource(program, sourceURL, lineNumber);
-    RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &errLine, &errMsg);
-    if (!function)
-        return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url());
+    JSObject* exception = 0;
+    FunctionExecutable* function = FunctionExecutable::fromGlobalCode(functionName, exec, exec->dynamicGlobalObject()->debugger(), source, &exception);
+    if (!function) {
+        ASSERT(exception);
+        return throwError(exec, exception);
+    }
 
-    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
-    ScopeChain scopeChain(globalObject, globalObject->globalData(), globalObject, exec->globalThisValue());
-    return new (exec) JSFunction(exec, function, scopeChain.node());
+    ScopeChainNode* scopeChain = new (exec) ScopeChainNode(0, globalObject, &globalData, globalObject, exec->globalThisValue());
+    return new (exec) JSFunction(exec, function, scopeChain);
 }
 
 // ECMA 15.3.2 The Function Constructor
-JSObject* constructFunction(ExecState* exec, const ArgList& args)
+JSObject* constructFunction(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
-    return constructFunction(exec, args, Identifier(exec, "anonymous"), UString(), 1);
+    return constructFunction(exec, globalObject, args, Identifier(exec, "anonymous"), UString(), 1);
 }
 
 } // namespace JSC
index 197f320c2896627872741ebf57ca1e94b0043263..ba112b9fc7951571ed1cc700a26bbb7c80921e0e 100644 (file)
@@ -29,15 +29,17 @@ namespace JSC {
 
     class FunctionConstructor : public InternalFunction {
     public:
-        FunctionConstructor(ExecState*, NonNullPassRefPtr<Structure>, FunctionPrototype*);
+        FunctionConstructor(ExecState*, JSGlobalObject*, Structure*, FunctionPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
-    JSObject* constructFunction(ExecState*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
-    JSObject* constructFunction(ExecState*, const ArgList&);
+    JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, int lineNumber);
+    JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&);
+
+    JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, int lineNumber);
 
 } // namespace JSC
 
index a77b5b27e9d1a856b4e808701274887375e1946d..e2a49416ddee3c4b75f1fa326075583517957f2b 100644 (file)
 #include "JSStringBuilder.h"
 #include "Interpreter.h"
 #include "Lexer.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
 
-static JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*);
 
-FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
-    : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
+FunctionPrototype::FunctionPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+    : InternalFunction(&exec->globalData(), globalObject, structure, exec->propertyNames().nullIdentifier)
 {
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
-void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction)
+void FunctionPrototype::addFunctionProperties(ExecState* exec, JSGlobalObject* globalObject, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction)
 {
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
-    *applyFunction = new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
+    putDirectFunctionWithoutTransition(exec, new (exec) JSFunction(exec, globalObject, functionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
+    *applyFunction = new (exec) JSFunction(exec, globalObject, functionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply);
     putDirectFunctionWithoutTransition(exec, *applyFunction, DontEnum);
-    *callFunction = new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
+    *callFunction = new (exec) JSFunction(exec, globalObject, functionStructure, 1, exec->propertyNames().call, functionProtoFuncCall);
     putDirectFunctionWithoutTransition(exec, *callFunction, DontEnum);
 }
 
-static JSValue JSC_HOST_CALL callFunctionPrototype(ExecState*, JSObject*, JSValue, const ArgList&)
+static EncodedJSValue JSC_HOST_CALL callFunctionPrototype(ExecState*)
 {
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
 }
 
 // ECMA 15.3.4
@@ -71,76 +70,80 @@ CallType FunctionPrototype::getCallData(CallData& callData)
 static inline void insertSemicolonIfNeeded(UString& functionBody)
 {
     ASSERT(functionBody[0] == '{');
-    ASSERT(functionBody[functionBody.size() - 1] == '}');
+    ASSERT(functionBody[functionBody.length() - 1] == '}');
 
-    for (size_t i = functionBody.size() - 2; i > 0; --i) {
+    for (size_t i = functionBody.length() - 2; i > 0; --i) {
         UChar ch = functionBody[i];
         if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) {
             if (ch != ';' && ch != '}')
-                functionBody = makeString(functionBody.substr(0, i + 1), ";", functionBody.substr(i + 1, functionBody.size() - (i + 1)));
+                functionBody = makeUString(functionBody.substringSharingImpl(0, i + 1), ";", functionBody.substringSharingImpl(i + 1, functionBody.length() - (i + 1)));
             return;
         }
     }
 }
 
-JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
 {
-    if (thisValue.inherits(&JSFunction::info)) {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.inherits(&JSFunction::s_info)) {
         JSFunction* function = asFunction(thisValue);
-        if (!function->isHostFunction()) {
-            FunctionExecutable* executable = function->jsExecutable();
-            UString sourceString = executable->source().toString();
-            insertSemicolonIfNeeded(sourceString);
-            return jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString);
-        }
+        if (function->isHostFunction())
+            return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
+        FunctionExecutable* executable = function->jsExecutable();
+        UString sourceString = executable->source().toString();
+        insertSemicolonIfNeeded(sourceString);
+        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "(", executable->paramString(), ") ", sourceString));
     }
 
-    if (thisValue.inherits(&InternalFunction::info)) {
+    if (thisValue.inherits(&InternalFunction::s_info)) {
         InternalFunction* function = asInternalFunction(thisValue);
-        return jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}");
+        return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n    [native code]\n}"));
     }
 
-    return throwError(exec, TypeError);
+    return throwVMTypeError(exec);
 }
 
-JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     CallData callData;
-    CallType callType = thisValue.getCallData(callData);
+    CallType callType = getCallData(thisValue, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSValue array = args.at(1);
+    JSValue array = exec->argument(1);
 
     MarkedArgumentBuffer applyArgs;
     if (!array.isUndefinedOrNull()) {
         if (!array.isObject())
-            return throwError(exec, TypeError);
-        if (asObject(array)->classInfo() == &Arguments::info)
+            return throwVMTypeError(exec);
+        if (asObject(array)->classInfo() == &Arguments::s_info)
             asArguments(array)->fillArgList(exec, applyArgs);
         else if (isJSArray(&exec->globalData(), array))
             asArray(array)->fillArgList(exec, applyArgs);
-        else if (asObject(array)->inherits(&JSArray::info)) {
+        else if (asObject(array)->inherits(&JSArray::s_info)) {
             unsigned length = asArray(array)->get(exec, exec->propertyNames().length).toUInt32(exec);
             for (unsigned i = 0; i < length; ++i)
                 applyArgs.append(asArray(array)->get(exec, i));
         } else
-            return throwError(exec, TypeError);
+            return throwVMTypeError(exec);
     }
 
-    return call(exec, thisValue, callType, callData, args.at(0), applyArgs);
+    return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), applyArgs));
 }
 
-JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     CallData callData;
-    CallType callType = thisValue.getCallData(callData);
+    CallType callType = getCallData(thisValue, callData);
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
+    ArgList args(exec);
     ArgList callArgs;
     args.getSlice(1, callArgs);
-    return call(exec, thisValue, callType, callData, args.at(0), callArgs);
+    return JSValue::encode(call(exec, thisValue, callType, callData, exec->argument(0), callArgs));
 }
 
 } // namespace JSC
index af783f7b2b3be2678d79ed25bf273714c0488cbd..ab708dd7de33a1900a43b0aa58ec6caa6d5117b5 100644 (file)
 
 namespace JSC {
 
-    class PrototypeFunction;
-
     class FunctionPrototype : public InternalFunction {
     public:
-        FunctionPrototype(ExecState*, NonNullPassRefPtr<Structure>);
-        void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction);
+        FunctionPrototype(ExecState*, JSGlobalObject*, Structure*);
+        void addFunctionProperties(ExecState*, JSGlobalObject*, Structure* functionStructure, JSFunction** callFunction, JSFunction** applyFunction);
 
-        static PassRefPtr<Structure> createStructure(JSValue proto)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
         {
-            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     private:
diff --git a/runtime/GCActivityCallback.cpp b/runtime/GCActivityCallback.cpp
new file mode 100644 (file)
index 0000000..308d245
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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.
+ */
+
+#include "config.h"
+#include "GCActivityCallback.h"
+
+namespace JSC {
+
+struct DefaultGCActivityCallbackPlatformData {
+};
+
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap*)
+{
+}
+
+DefaultGCActivityCallback::~DefaultGCActivityCallback()
+{
+}
+
+void DefaultGCActivityCallback::operator()()
+{
+}
+
+void DefaultGCActivityCallback::synchronize()
+{
+}
+
+}
+
diff --git a/runtime/GCActivityCallback.h b/runtime/GCActivityCallback.h
new file mode 100644 (file)
index 0000000..f40ebee
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 GCActivityCallback_h
+#define GCActivityCallback_h
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+#if USE(CF)
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace JSC {
+
+class Heap;
+
+class GCActivityCallback {
+public:
+    virtual ~GCActivityCallback() {}
+    virtual void operator()() {}
+    virtual void synchronize() {}
+
+protected:
+    GCActivityCallback() {}
+};
+
+struct DefaultGCActivityCallbackPlatformData;
+
+class DefaultGCActivityCallback : public GCActivityCallback {
+public:
+    static PassOwnPtr<DefaultGCActivityCallback> create(Heap*);
+
+    DefaultGCActivityCallback(Heap*);
+    ~DefaultGCActivityCallback();
+
+    void operator()();
+    void synchronize();
+
+#if USE(CF)
+protected:
+    DefaultGCActivityCallback(Heap*, CFRunLoopRef);
+    void commonConstructor(Heap*, CFRunLoopRef);
+#endif
+
+private:
+    OwnPtr<DefaultGCActivityCallbackPlatformData> d;
+};
+
+inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap)
+{
+    return adoptPtr(new DefaultGCActivityCallback(heap));
+}
+
+}
+
+#endif
diff --git a/runtime/GCActivityCallbackCF.cpp b/runtime/GCActivityCallbackCF.cpp
new file mode 100644 (file)
index 0000000..2e878bf
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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.
+ */
+
+#include "config.h"
+#include "GCActivityCallback.h"
+
+#include "APIShims.h"
+#include "Heap.h"
+#include "JSGlobalData.h"
+#include "JSLock.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
+#include <wtf/RetainPtr.h>
+#include <wtf/WTFThreadData.h>
+
+#if !USE(CF)
+#error "This file should only be used on CF platforms."
+#endif
+
+namespace JSC {
+
+struct DefaultGCActivityCallbackPlatformData {
+    static void trigger(CFRunLoopTimerRef, void *info);
+
+    RetainPtr<CFRunLoopTimerRef> timer;
+    RetainPtr<CFRunLoopRef> runLoop;
+    CFRunLoopTimerContext context;
+};
+
+const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
+const CFTimeInterval triggerInterval = 2; // seconds
+
+void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info)
+{
+    Heap* heap = static_cast<Heap*>(info);
+    APIEntryShim shim(heap->globalData());
+    heap->collectAllGarbage();
+    CFRunLoopTimerSetNextFireDate(timer, CFAbsoluteTimeGetCurrent() + decade);
+}
+
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap)
+{
+    commonConstructor(heap, CFRunLoopGetCurrent());
+}
+
+DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap, CFRunLoopRef runLoop)
+{
+    commonConstructor(heap, runLoop);
+}
+
+DefaultGCActivityCallback::~DefaultGCActivityCallback()
+{
+    CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
+    CFRunLoopTimerInvalidate(d->timer.get());
+    d->context.info = 0;
+    d->runLoop = 0;
+    d->timer = 0;
+}
+
+void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLoop)
+{
+    d = adoptPtr(new DefaultGCActivityCallbackPlatformData);
+
+    memset(&d->context, 0, sizeof(CFRunLoopTimerContext));
+    d->context.info = heap;
+    d->runLoop = runLoop;
+    d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::trigger, &d->context));
+    CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
+}
+
+void DefaultGCActivityCallback::operator()()
+{
+    CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval);
+}
+
+void DefaultGCActivityCallback::synchronize()
+{
+    if (CFRunLoopGetCurrent() == d->runLoop.get())
+        return;
+    CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
+    d->runLoop = CFRunLoopGetCurrent();
+    CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes);
+}
+
+}
index 7e54053f96cce73b5560a82e5e810e1e5d280f6c..04193ea3d5314c2239c152fa607ce5adc0fe4ebd 100644 (file)
 
 namespace JSC {
 
-void GetterSetter::markChildren(MarkStack& markStack)
+const ClassInfo GetterSetter::s_info = { "GetterSetter", 0, 0, 0 };
+
+void GetterSetter::visitChildren(SlotVisitor& visitor)
 {
-    JSCell::markChildren(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSCell::visitChildren(visitor);
 
     if (m_getter)
-        markStack.append(m_getter);
+        visitor.append(&m_getter);
     if (m_setter)
-        markStack.append(m_setter);
+        visitor.append(&m_setter);
 }
 
 bool GetterSetter::isGetterSetter() const
index 27ffbe78a76294e1cb1b566645ce56787a7a67ab..aca7e3cbb0272f1ff9dea99c60fe5cdbd309a1d2 100644 (file)
@@ -26,6 +26,7 @@
 #include "JSCell.h"
 
 #include "CallFrame.h"
+#include "Structure.h"
 
 namespace JSC {
 
@@ -37,35 +38,36 @@ namespace JSC {
         friend class JIT;
     public:
         GetterSetter(ExecState* exec)
-            : JSCell(exec->globalData().getterSetterStructure.get())
-            , m_getter(0)
-            , m_setter(0)
+            : JSCell(exec->globalData(), exec->globalData().getterSetterStructure.get())
         {
         }
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
-        JSObject* getter() const { return m_getter; }
-        void setGetter(JSObject* getter) { m_getter = getter; }
-        JSObject* setter() const { return m_setter; }
-        void setSetter(JSObject* setter) { m_setter = setter; }
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        JSObject* getter() const { return m_getter.get(); }
+        void setGetter(JSGlobalData& globalData, JSObject* getter) { m_getter.set(globalData, this, getter); }
+        JSObject* setter() const { return m_setter.get(); }
+        void setSetter(JSGlobalData& globalData, JSObject* setter) { m_setter.set(globalData, this, setter); }
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(GetterSetterType, OverridesVisitChildren), AnonymousSlotCount, &s_info);
         }
+        
+        static const ClassInfo s_info;
+
     private:
         virtual bool isGetterSetter() const;
 
-        JSObject* m_getter;
-        JSObject* m_setter;  
+        WriteBarrier<JSObject> m_getter;
+        WriteBarrier<JSObject> m_setter;  
     };
 
     GetterSetter* asGetterSetter(JSValue);
 
     inline GetterSetter* asGetterSetter(JSValue value)
     {
-        ASSERT(asCell(value)->isGetterSetter());
-        return static_cast<GetterSetter*>(asCell(value));
+        ASSERT(value.asCell()->isGetterSetter());
+        return static_cast<GetterSetter*>(value.asCell());
     }
 
 
diff --git a/runtime/GlobalEvalFunction.cpp b/runtime/GlobalEvalFunction.cpp
deleted file mode 100644 (file)
index c26002b..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *  Copyright (C) 2007 Maks Orlovich
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "GlobalEvalFunction.h"
-
-#include "JSGlobalObject.h"
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
-ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction);
-
-GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)
-    : PrototypeFunction(exec, structure, len, name, function)
-    , m_cachedGlobalObject(cachedGlobalObject)
-{
-    ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);
-}
-
-void GlobalEvalFunction::markChildren(MarkStack& markStack)
-{
-    PrototypeFunction::markChildren(markStack);
-    markStack.append(m_cachedGlobalObject);
-}
-
-} // namespace JSC
diff --git a/runtime/GlobalEvalFunction.h b/runtime/GlobalEvalFunction.h
deleted file mode 100644 (file)
index a14ce4d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *  Copyright (C) 2007 Maks Orlovich
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef GlobalEvalFunction_h
-#define GlobalEvalFunction_h
-
-#include "PrototypeFunction.h"
-
-namespace JSC {
-
-    class JSGlobalObject;
-
-    class GlobalEvalFunction : public PrototypeFunction {
-    public:
-        GlobalEvalFunction(ExecState*, NonNullPassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject);
-        JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; }
-
-        static PassRefPtr<Structure> createStructure(JSValue prototype) 
-        { 
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
-        }
-
-    protected:
-        static const unsigned StructureFlags = ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | PrototypeFunction::StructureFlags;
-
-    private:
-        virtual void markChildren(MarkStack&);
-
-        JSGlobalObject* m_cachedGlobalObject;
-    };
-
-} // namespace JSC
-
-#endif // GlobalEvalFunction_h
index f2642a93f13bba05b437fe056ce9c95c78ca1d1f..b07341c95c8e0e7574bccd9310284b1f1c4fc82f 100644 (file)
@@ -22,7 +22,9 @@
 #include "Identifier.h"
 
 #include "CallFrame.h"
+#include "JSObject.h"
 #include "NumericStrings.h"
+#include "ScopeChain.h"
 #include <new> // for placement new
 #include <string.h> // for strlen
 #include <wtf/Assertions.h>
@@ -65,7 +67,7 @@ void deleteIdentifierTable(IdentifierTable* table)
     delete table;
 }
 
-bool Identifier::equal(const UString::Rep* r, const char* s)
+bool Identifier::equal(const StringImpl* r, const char* s)
 {
     int length = r->length();
     const UChar* d = r->characters();
@@ -75,33 +77,22 @@ bool Identifier::equal(const UString::Rep* r, const char* s)
     return s[length] == 0;
 }
 
-bool Identifier::equal(const UString::Rep* r, const UChar* s, unsigned length)
-{
-    if (r->length() != length)
-        return false;
-    const UChar* d = r->characters();
-    for (unsigned i = 0; i != length; ++i)
-        if (d[i] != s[i])
-            return false;
-    return true;
-}
-
 struct IdentifierCStringTranslator {
     static unsigned hash(const char* c)
     {
-        return UString::Rep::computeHash(c);
+        return StringHasher::computeHash<char>(c);
     }
 
-    static bool equal(UString::Rep* r, const char* s)
+    static bool equal(StringImpl* r, const char* s)
     {
         return Identifier::equal(r, s);
     }
 
-    static void translate(UString::Rep*& location, const char* c, unsigned hash)
+    static void translate(StringImpl*& location, const char* c, unsigned hash)
     {
         size_t length = strlen(c);
         UChar* d;
-        UString::Rep* r = UString::Rep::createUninitialized(length, d).releaseRef();
+        StringImpl* r = StringImpl::createUninitialized(length, d).leakRef();
         for (size_t i = 0; i != length; i++)
             d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend
         r->setHash(hash);
@@ -109,12 +100,12 @@ struct IdentifierCStringTranslator {
     }
 };
 
-PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c)
+PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c)
 {
     if (!c)
-        return UString::null().rep();
+        return 0;
     if (!c[0])
-        return UString::Rep::empty();
+        return StringImpl::empty();
     if (!c[1])
         return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0])));
 
@@ -125,18 +116,18 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c
     if (iter != literalIdentifierTable.end())
         return iter->second;
 
-    pair<HashSet<UString::Rep*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c);
+    pair<HashSet<StringImpl*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c);
 
     // If the string is newly-translated, then we need to adopt it.
     // The boolean in the pair tells us if that is so.
-    RefPtr<UString::Rep> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+    RefPtr<StringImpl> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first;
 
     literalIdentifierTable.add(c, addedString.get());
 
     return addedString.release();
 }
 
-PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const char* c)
+PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const char* c)
 {
     return add(&exec->globalData(), c);
 }
@@ -149,18 +140,18 @@ struct UCharBuffer {
 struct IdentifierUCharBufferTranslator {
     static unsigned hash(const UCharBuffer& buf)
     {
-        return UString::Rep::computeHash(buf.s, buf.length);
+        return StringHasher::computeHash<UChar>(buf.s, buf.length);
     }
 
-    static bool equal(UString::Rep* str, const UCharBuffer& buf)
+    static bool equal(StringImpl* str, const UCharBuffer& buf)
     {
         return Identifier::equal(str, buf.s, buf.length);
     }
 
-    static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash)
+    static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
     {
         UChar* d;
-        UString::Rep* r = UString::Rep::createUninitialized(buf.length, d).releaseRef();
+        StringImpl* r = StringImpl::createUninitialized(buf.length, d).leakRef();
         for (unsigned i = 0; i != buf.length; i++)
             d[i] = buf.s[i];
         r->setHash(hash);
@@ -168,29 +159,72 @@ struct IdentifierUCharBufferTranslator {
     }
 };
 
-PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
+uint32_t Identifier::toUInt32(const UString& string, bool& ok)
+{
+    ok = false;
+
+    unsigned length = string.length();
+    const UChar* characters = string.characters();
+
+    // An empty string is not a number.
+    if (!length)
+        return 0;
+
+    // Get the first character, turning it into a digit.
+    uint32_t value = characters[0] - '0';
+    if (value > 9)
+        return 0;
+
+    // Check for leading zeros. If the first characher is 0, then the
+    // length of the string must be one - e.g. "042" is not equal to "42".
+    if (!value && length > 1)
+        return 0;
+
+    while (--length) {
+        // Multiply value by 10, checking for overflow out of 32 bits.
+        if (value > 0xFFFFFFFFU / 10)
+            return 0;
+        value *= 10;
+
+        // Get the next character, turning it into a digit.
+        uint32_t newValue = *(++characters) - '0';
+        if (newValue > 9)
+            return 0;
+
+        // Add in the old value, checking for overflow out of 32 bits.
+        newValue += value;
+        if (newValue < value)
+            return 0;
+        value = newValue;
+    }
+
+    ok = true;
+    return value;
+}
+
+PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const UChar* s, int length)
 {
     if (length == 1) {
         UChar c = s[0];
-        if (c <= 0xFF)
+        if (c <= maxSingleCharacterString)
             return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
     }
     if (!length)
-        return UString::Rep::empty();
+        return StringImpl::empty();
     UCharBuffer buf = {s, length}; 
-    pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, IdentifierUCharBufferTranslator>(buf);
+    pair<HashSet<StringImpl*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, IdentifierUCharBufferTranslator>(buf);
 
     // If the string is newly-translated, then we need to adopt it.
     // The boolean in the pair tells us if that is so.
     return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
 }
 
-PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int length)
+PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const UChar* s, int length)
 {
     return add(&exec->globalData(), s, length);
 }
 
-PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r)
+PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringImpl* r)
 {
     ASSERT(!r->isIdentifier());
     // The empty & null strings are static singletons, and static strings are handled
@@ -199,7 +233,7 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UStri
 
     if (r->length() == 1) {
         UChar c = r->characters()[0];
-        if (c <= 0xFF)
+        if (c <= maxSingleCharacterString)
             r = globalData->smallStrings.singleCharacterStringRep(c);
             if (r->isIdentifier())
                 return r;
@@ -208,7 +242,7 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UStri
     return *globalData->identifierTable->add(r).first;
 }
 
-PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* r)
+PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r)
 {
     return addSlowCase(&exec->globalData(), r);
 }
@@ -228,6 +262,21 @@ Identifier Identifier::from(ExecState* exec, double value)
     return Identifier(exec, exec->globalData().numericStrings.add(value));
 }
 
+Identifier Identifier::from(JSGlobalData* globalData, unsigned value)
+{
+    return Identifier(globalData, globalData->numericStrings.add(value));
+}
+
+Identifier Identifier::from(JSGlobalData* globalData, int value)
+{
+    return Identifier(globalData, globalData->numericStrings.add(value));
+}
+
+Identifier Identifier::from(JSGlobalData* globalData, double value)
+{
+    return Identifier(globalData, globalData->numericStrings.add(value));
+}
+
 #ifndef NDEBUG
 
 void Identifier::checkCurrentIdentifierTable(JSGlobalData* globalData)
index 2f16bbf52cac13c038067bf85826c3f3808f534d..36b336ef49241bc9331724facd93ab4da75d6d9a 100644 (file)
@@ -24,6 +24,7 @@
 #include "JSGlobalData.h"
 #include "ThreadSpecific.h"
 #include "UString.h"
+#include <wtf/text/CString.h>
 
 namespace JSC {
 
@@ -34,38 +35,37 @@ namespace JSC {
     public:
         Identifier() { }
 
-        Identifier(ExecState* exec, const char* s) : _ustring(add(exec, s)) { } // Only to be used with string literals.
-        Identifier(ExecState* exec, const UChar* s, int length) : _ustring(add(exec, s, length)) { }
-        Identifier(ExecState* exec, UString::Rep* rep) : _ustring(add(exec, rep)) { } 
-        Identifier(ExecState* exec, const UString& s) : _ustring(add(exec, s.rep())) { }
+        Identifier(ExecState* exec, const char* s) : m_string(add(exec, s)) { } // Only to be used with string literals.
+        Identifier(ExecState* exec, const UChar* s, int length) : m_string(add(exec, s, length)) { }
+        Identifier(ExecState* exec, StringImpl* rep) : m_string(add(exec, rep)) { } 
+        Identifier(ExecState* exec, const UString& s) : m_string(add(exec, s.impl())) { }
 
-        Identifier(JSGlobalData* globalData, const char* s) : _ustring(add(globalData, s)) { } // Only to be used with string literals.
-        Identifier(JSGlobalData* globalData, const UChar* s, int length) : _ustring(add(globalData, s, length)) { }
-        Identifier(JSGlobalData* globalData, UString::Rep* rep) : _ustring(add(globalData, rep)) { } 
-        Identifier(JSGlobalData* globalData, const UString& s) : _ustring(add(globalData, s.rep())) { }
+        Identifier(JSGlobalData* globalData, const char* s) : m_string(add(globalData, s)) { } // Only to be used with string literals.
+        Identifier(JSGlobalData* globalData, const UChar* s, int length) : m_string(add(globalData, s, length)) { }
+        Identifier(JSGlobalData* globalData, StringImpl* rep) : m_string(add(globalData, rep)) { } 
+        Identifier(JSGlobalData* globalData, const UString& s) : m_string(add(globalData, s.impl())) { }
 
-        // Special constructor for cases where we overwrite an object in place.
-        Identifier(PlacementNewAdoptType) : _ustring(PlacementNewAdopt) { }
+        const UString& ustring() const { return m_string; }
+        StringImpl* impl() const { return m_string.impl(); }
         
-        const UString& ustring() const { return _ustring; }
+        const UChar* characters() const { return m_string.characters(); }
+        int length() const { return m_string.length(); }
         
-        const UChar* data() const { return _ustring.data(); }
-        int size() const { return _ustring.size(); }
-        
-        const char* ascii() const { return _ustring.ascii(); }
+        CString ascii() const { return m_string.ascii(); }
         
         static Identifier from(ExecState* exec, unsigned y);
         static Identifier from(ExecState* exec, int y);
         static Identifier from(ExecState* exec, double y);
-        
-        bool isNull() const { return _ustring.isNull(); }
-        bool isEmpty() const { return _ustring.isEmpty(); }
-        
-        uint32_t toUInt32(bool* ok) const { return _ustring.toUInt32(ok); }
-        uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const { return _ustring.toUInt32(ok, tolerateEmptyString); };
-        uint32_t toStrictUInt32(bool* ok) const { return _ustring.toStrictUInt32(ok); }
-        unsigned toArrayIndex(bool* ok) const { return _ustring.toArrayIndex(ok); }
-        double toDouble() const { return _ustring.toDouble(); }
+        static Identifier from(JSGlobalData*, unsigned y);
+        static Identifier from(JSGlobalData*, int y);
+        static Identifier from(JSGlobalData*, double y);
+
+        static uint32_t toUInt32(const UString&, bool& ok);
+        uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); }
+        unsigned toArrayIndex(bool& ok) const;
+
+        bool isNull() const { return m_string.isNull(); }
+        bool isEmpty() const { return m_string.isEmpty(); }
         
         friend bool operator==(const Identifier&, const Identifier&);
         friend bool operator!=(const Identifier&, const Identifier&);
@@ -73,23 +73,23 @@ namespace JSC {
         friend bool operator==(const Identifier&, const char*);
         friend bool operator!=(const Identifier&, const char*);
     
-        static bool equal(const UString::Rep*, const char*);
-        static bool equal(const UString::Rep*, const UChar*, unsigned length);
-        static bool equal(const UString::Rep* a, const UString::Rep* b) { return ::equal(a, b); }
+        static bool equal(const StringImpl*, const char*);
+        static bool equal(const StringImpl*, const UChar*, unsigned length);
+        static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); }
 
-        static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals.
-        static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals.
+        static PassRefPtr<StringImpl> add(ExecState*, const char*); // Only to be used with string literals.
+        static PassRefPtr<StringImpl> add(JSGlobalData*, const char*); // Only to be used with string literals.
 
     private:
-        UString _ustring;
+        UString m_string;
         
-        static bool equal(const Identifier& a, const Identifier& b) { return a._ustring.rep() == b._ustring.rep(); }
-        static bool equal(const Identifier& a, const char* b) { return equal(a._ustring.rep(), b); }
+        static bool equal(const Identifier& a, const Identifier& b) { return a.m_string.impl() == b.m_string.impl(); }
+        static bool equal(const Identifier& a, const char* b) { return equal(a.m_string.impl(), b); }
 
-        static PassRefPtr<UString::Rep> add(ExecState*, const UChar*, int length);
-        static PassRefPtr<UString::Rep> add(JSGlobalData*, const UChar*, int length);
+        static PassRefPtr<StringImpl> add(ExecState*, const UChar*, int length);
+        static PassRefPtr<StringImpl> add(JSGlobalData*, const UChar*, int length);
 
-        static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r)
+        static PassRefPtr<StringImpl> add(ExecState* exec, StringImpl* r)
         {
 #ifndef NDEBUG
             checkCurrentIdentifierTable(exec);
@@ -98,7 +98,7 @@ namespace JSC {
                 return r;
             return addSlowCase(exec, r);
         }
-        static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r)
+        static PassRefPtr<StringImpl> add(JSGlobalData* globalData, StringImpl* r)
         {
 #ifndef NDEBUG
             checkCurrentIdentifierTable(globalData);
@@ -108,8 +108,8 @@ namespace JSC {
             return addSlowCase(globalData, r);
         }
 
-        static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r);
-        static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r);
+        static PassRefPtr<StringImpl> addSlowCase(ExecState*, StringImpl* r);
+        static PassRefPtr<StringImpl> addSlowCase(JSGlobalData*, StringImpl* r);
 
         static void checkCurrentIdentifierTable(ExecState*);
         static void checkCurrentIdentifierTable(JSGlobalData*);
@@ -135,9 +135,25 @@ namespace JSC {
         return !Identifier::equal(a, b);
     }
 
+    inline bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length)
+    {
+        if (r->length() != length)
+            return false;
+        const UChar* d = r->characters();
+        for (unsigned i = 0; i != length; ++i)
+            if (d[i] != s[i])
+                return false;
+        return true;
+    }
+    
     IdentifierTable* createIdentifierTable();
     void deleteIdentifierTable(IdentifierTable*);
 
+    struct IdentifierRepHash : PtrHash<RefPtr<StringImpl> > {
+        static unsigned hash(const RefPtr<StringImpl>& key) { return key->existingHash(); }
+        static unsigned hash(StringImpl* key) { return key->existingHash(); }
+    };
+
 } // namespace JSC
 
 #endif // Identifier_h
index 51d43ee224c3b42d178392a8a784dac0e6d72965..27611b757b34be5c564ce03bb0553ba736e64660 100644 (file)
@@ -29,7 +29,7 @@
 #include "config.h"
 #include "InitializeThreading.h"
 
-#include "Collector.h"
+#include "Heap.h"
 #include "dtoa.h"
 #include "Identifier.h"
 #include "JSGlobalObject.h"
@@ -48,13 +48,17 @@ static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT;
 
 static void initializeThreadingOnce()
 {
+    // StringImpl::empty() does not construct its static string in a threadsafe fashion,
+    // so ensure it has been initialized from here.
+    StringImpl::empty();
+
     WTF::initializeThreading();
     wtfThreadData();
-    initializeUString();
     JSGlobalData::storeVPtrs();
 #if ENABLE(JSC_MULTIPLE_THREADS)
     s_dtoaP5Mutex = new Mutex;
     initializeDates();
+    RegisterFile::initializeThreading();
 #endif
 }
 
index f68e795f31cbd8b0a298a35c31e5a26b056f8f22..c3b07f8297028e96f2ff503d95178f1ccf98f6ae 100644 (file)
 #include "InternalFunction.h"
 
 #include "FunctionPrototype.h"
+#include "JSGlobalObject.h"
 #include "JSString.h"
 
 namespace JSC {
 
+// Ensure the compiler generates a vtable for InternalFunction!
+void InternalFunction::vtableAnchor() {}
+
 ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
 
-const ClassInfo InternalFunction::info = { "Function", 0, 0, 0 };
+const ClassInfo InternalFunction::s_info = { "Function", &JSObjectWithGlobalObject::s_info, 0, 0 };
 
-const ClassInfo* InternalFunction::classInfo() const
+InternalFunction::InternalFunction(VPtrStealingHackType)
+    : JSObjectWithGlobalObject(VPtrStealingHack)
 {
-    return &info;
 }
 
-InternalFunction::InternalFunction(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const Identifier& name)
-    : JSObject(structure)
+InternalFunction::InternalFunction(JSGlobalData* globalData, JSGlobalObject* globalObject, Structure* structure, const Identifier& name)
+    : JSObjectWithGlobalObject(globalObject, structure)
 {
-    putDirect(globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
+    ASSERT(inherits(&s_info));
+    putDirect(*globalData, globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
 }
 
 const UString& InternalFunction::name(ExecState* exec)
 {
-    return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue();
+    return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
 }
 
 const UString InternalFunction::displayName(ExecState* exec)
 {
-    JSValue displayName = getDirect(exec->globalData().propertyNames->displayName);
+    JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
     
     if (displayName && isJSString(&exec->globalData(), displayName))
         return asString(displayName)->tryGetValue();
     
-    return UString::null();
+    return UString();
 }
 
 const UString InternalFunction::calculatedDisplayName(ExecState* exec)
index d19b82b38aae2332cf86420aa7b5a0308f309918..28e260e30130ddd8c0ae796d663337298fe9cfa1 100644 (file)
 #ifndef InternalFunction_h
 #define InternalFunction_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 #include "Identifier.h"
 
 namespace JSC {
 
     class FunctionPrototype;
 
-    class InternalFunction : public JSObject {
+    class InternalFunction : public JSObjectWithGlobalObject {
     public:
-        virtual const ClassInfo* classInfo() const; 
-        static JS_EXPORTDATA const ClassInfo info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
         const UString& name(ExecState*);
         const UString displayName(ExecState*);
         const UString calculatedDisplayName(ExecState*);
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
         { 
-            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
         }
 
     protected:
         static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags;
 
-        InternalFunction(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { }
-        InternalFunction(JSGlobalData*, NonNullPassRefPtr<Structure>, const Identifier&);
+        // Only used to allow us to determine the JSFunction vptr
+        InternalFunction(VPtrStealingHackType);
+
+        InternalFunction(JSGlobalData*, JSGlobalObject*, Structure*, const Identifier&);
 
     private:
         virtual CallType getCallData(CallData&) = 0;
+
+        virtual void vtableAnchor();
     };
 
     InternalFunction* asInternalFunction(JSValue);
 
     inline InternalFunction* asInternalFunction(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&InternalFunction::info));
+        ASSERT(asObject(value)->inherits(&InternalFunction::s_info));
         return static_cast<InternalFunction*>(asObject(value));
     }
 
index e83724a1da19391ead6accbb8f0653e96c547327..9a92a9311cea954139a7c0620f89c8c756e7bc57 100644 (file)
@@ -28,4 +28,6 @@
 
 namespace JSC {
 
+const ClassInfo JSAPIValueWrapper::s_info = { "API Wrapper", 0, 0, 0 };
+
 } // namespace JSC
index 10ded4cd4418bd9bcd8f3c10c57d9bae50f6f81f..38cbb569e3691eadd8fe1a3289f5285e8d1b0cce 100644 (file)
 
 #include "JSCell.h"
 #include "CallFrame.h"
+#include "Structure.h"
 
 namespace JSC {
 
     class JSAPIValueWrapper : public JSCell {
         friend JSValue jsAPIValueWrapper(ExecState*, JSValue);
     public:
-        JSValue value() const { return m_value; }
+        JSValue value() const { return m_value.get(); }
 
         virtual bool isAPIValueWrapper() const { return true; }
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren | OverridesGetPropertyNames), AnonymousSlotCount, &s_info);
         }
-
         
+        static const ClassInfo s_info;
+
     private:
         JSAPIValueWrapper(ExecState* exec, JSValue value)
-            : JSCell(exec->globalData().apiWrapperStructure.get())
-            , m_value(value)
+            : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get())
         {
+            m_value.set(exec->globalData(), this, value);
             ASSERT(!value.isCell());
         }
 
-        JSValue m_value;
+        WriteBarrier<Unknown> m_value;
     };
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
index f468ff1e745c0578d56db4aa604d0a5ee437a615..09d985afbcfb593d5fbd04599a2a682b5f17f05d 100644 (file)
@@ -37,53 +37,119 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSActivation);
 
-const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 };
-
-JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable)
-    : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers()))
+const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0 };
+
+JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
+    : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
+    , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount()))
+    , m_numCapturedVars(functionExecutable->capturedVariableCount())
+    , m_requiresDynamicChecks(functionExecutable->usesEval())
+    , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
 {
+    ASSERT(inherits(&s_info));
+
+    // We have to manually ref and deref the symbol table as JSVariableObject
+    // doesn't know about SharedSymbolTable
+    static_cast<SharedSymbolTable*>(m_symbolTable)->ref();
 }
 
 JSActivation::~JSActivation()
 {
-    delete d();
+    static_cast<SharedSymbolTable*>(m_symbolTable)->deref();
 }
 
-void JSActivation::markChildren(MarkStack& markStack)
+void JSActivation::visitChildren(SlotVisitor& visitor)
 {
-    Base::markChildren(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(visitor);
 
-    Register* registerArray = d()->registerArray.get();
+    // No need to mark our registers if they're still in the RegisterFile.
+    WriteBarrier<Unknown>* registerArray = m_registerArray.get();
     if (!registerArray)
         return;
 
-    size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
+    visitor.appendValues(registerArray, m_numParametersMinusThis);
 
-    size_t count = numParametersMinusThis;
-    markStack.appendValues(registerArray, count);
+    // Skip the call frame, which sits between the parameters and vars.
+    visitor.appendValues(registerArray + m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, m_numCapturedVars, MayContainNullValues);
+}
 
-    size_t numVars = d()->functionExecutable->variableCount();
+inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
+{
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+    if (entry.isNull())
+        return false;
+    if (entry.getIndex() >= m_numCapturedVars)
+        return false;
 
-    // Skip the call frame, which sits between the parameters and vars.
-    markStack.appendValues(registerArray + count + RegisterFile::CallFrameHeaderSize, numVars, MayContainNullValues);
+    slot.setValue(registerAt(entry.getIndex()).get());
+    return true;
 }
 
-bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
 {
-    if (symbolTableGet(propertyName, slot))
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+    if (entry.isNull())
+        return false;
+    if (entry.isReadOnly())
         return true;
+    if (entry.getIndex() >= m_numCapturedVars)
+        return false;
 
-    if (JSValue* location = getDirectLocation(propertyName)) {
-        slot.setValueSlot(location);
-        return true;
+    registerAt(entry.getIndex()).set(globalData, this, value);
+    return true;
+}
+
+void JSActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    SymbolTable::const_iterator end = symbolTable().end();
+    for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) {
+        if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
+            continue;
+        if (it->second.getIndex() >= m_numCapturedVars)
+            continue;
+        propertyNames.add(Identifier(exec, it->first.get()));
     }
+    // Skip the JSVariableObject implementation of getOwnPropertyNames
+    JSObject::getOwnPropertyNames(exec, propertyNames, mode);
+}
+
+inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+    ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
+    
+    SymbolTable::iterator iter = symbolTable().find(propertyName.impl());
+    if (iter == symbolTable().end())
+        return false;
+    SymbolTableEntry& entry = iter->second;
+    ASSERT(!entry.isNull());
+    if (entry.getIndex() >= m_numCapturedVars)
+        return false;
+
+    entry.setAttributes(attributes);
+    registerAt(entry.getIndex()).set(globalData, this, value);
+    return true;
+}
 
-    // Only return the built-in arguments object if it wasn't overridden above.
+bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
     if (propertyName == exec->propertyNames().arguments) {
         slot.setCustom(this, getArgumentsGetter());
         return true;
     }
 
+    if (symbolTableGet(propertyName, slot))
+        return true;
+
+    if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
+        slot.setValue(location->get());
+        return true;
+    }
+
     // We don't call through to JSObject because there's no way to give an 
     // activation object getter properties or a prototype.
     ASSERT(!hasGetterSetterProperties());
@@ -91,18 +157,18 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert
     return false;
 }
 
-void JSActivation::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+void JSActivation::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (symbolTablePut(propertyName, value))
+    if (symbolTablePut(exec->globalData(), propertyName, value))
         return;
 
     // We don't call through to JSObject because __proto__ and getter/setter 
     // properties are non-standard extensions that other implementations do not
     // expose in the activation object.
     ASSERT(!hasGetterSetterProperties());
-    putDirect(propertyName, value, 0, true, slot);
+    putDirect(exec->globalData(), propertyName, value, 0, true, slot);
 }
 
 // FIXME: Make this function honor ReadOnly (const) and DontEnum
@@ -110,7 +176,7 @@ void JSActivation::putWithAttributes(ExecState* exec, const Identifier& property
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (symbolTablePutWithAttributes(propertyName, value, attributes))
+    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
 
     // We don't call through to JSObject because __proto__ and getter/setter 
@@ -134,32 +200,32 @@ JSObject* JSActivation::toThisObject(ExecState* exec) const
     return exec->globalThisValue();
 }
 
+JSValue JSActivation::toStrictThisObject(ExecState*) const
+{
+    return jsNull();
+}
+    
 bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
 {
-    requiresDynamicChecks = d()->functionExecutable->usesEval();
+    requiresDynamicChecks = m_requiresDynamicChecks;
     return false;
 }
 
-JSValue JSActivation::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
+JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
     JSActivation* activation = asActivation(slotBase);
-
-    if (activation->d()->functionExecutable->usesArguments()) {
-        PropertySlot slot;
-        activation->symbolTableGet(exec->propertyNames().arguments, slot);
-        return slot.getValue(exec, exec->propertyNames().arguments);
-    }
-
-    CallFrame* callFrame = CallFrame::create(activation->d()->registers);
-    Arguments* arguments = callFrame->optionalCalleeArguments();
-    if (!arguments) {
-        arguments = new (callFrame) Arguments(callFrame);
-        arguments->copyRegisters();
-        callFrame->setCalleeArguments(arguments);
-    }
-    ASSERT(arguments->inherits(&Arguments::info));
-
-    return arguments;
+    CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers));
+    int argumentsRegister = activation->m_argumentsRegister;
+    if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
+        return arguments;
+    int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
+
+    JSValue arguments = JSValue(new (callFrame) Arguments(callFrame));
+    callFrame->uncheckedR(argumentsRegister) = arguments;
+    callFrame->uncheckedR(realArgumentsRegister) = arguments;
+    
+    ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(&Arguments::s_info));
+    return callFrame->uncheckedR(realArgumentsRegister).jsValue();
 }
 
 // These two functions serve the purpose of isolating the common case from a
index 10a8dbd1176deb6e4737b37dd5cf734bcc1ea072..5f4c9351c5e3dee41ea10ddb6a87a34aa4d2dd8a 100644 (file)
@@ -42,16 +42,17 @@ namespace JSC {
     class JSActivation : public JSVariableObject {
         typedef JSVariableObject Base;
     public:
-        JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>);
+        JSActivation(CallFrame*, FunctionExecutable*);
         virtual ~JSActivation();
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
         virtual bool isDynamicScope(bool& requiresDynamicChecks) const;
 
         virtual bool isActivationObject() const { return true; }
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode);
 
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
 
@@ -59,48 +60,45 @@ namespace JSC {
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
 
         virtual JSObject* toThisObject(ExecState*) const;
+        virtual JSValue toStrictThisObject(ExecState*) const;
 
-        void copyRegisters(Arguments* arguments);
+        void copyRegisters(JSGlobalData&);
         
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); }
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
-        struct JSActivationData : public JSVariableObjectData {
-            JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers)
-                : JSVariableObjectData(_functionExecutable->generatedBytecode().symbolTable(), registers)
-                , functionExecutable(_functionExecutable)
-            {
-                // We have to manually ref and deref the symbol table as JSVariableObjectData
-                // doesn't know about SharedSymbolTable
-                functionExecutable->generatedBytecode().sharedSymbolTable()->ref();
-            }
-            ~JSActivationData()
-            {
-                static_cast<SharedSymbolTable*>(symbolTable)->deref();
-            }
-
-            RefPtr<FunctionExecutable> functionExecutable;
-        };
-        
+        bool symbolTableGet(const Identifier&, PropertySlot&);
+        bool symbolTableGet(const Identifier&, PropertyDescriptor&);
+        bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
+        bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
+        bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
+
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
 
-        JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); }
+        int m_numParametersMinusThis;
+        int m_numCapturedVars : 31;
+        bool m_requiresDynamicChecks : 1;
+        int m_argumentsRegister;
     };
 
     JSActivation* asActivation(JSValue);
 
     inline JSActivation* asActivation(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&JSActivation::info));
+        ASSERT(asObject(value)->inherits(&JSActivation::s_info));
         return static_cast<JSActivation*>(asObject(value));
     }
+    
+    ALWAYS_INLINE JSActivation* Register::activation() const
+    {
+        return asActivation(jsValue());
+    }
 
 } // namespace JSC
 
index eb778ed2a12af2ef10f6d46ab4098df0cc42248e..6bc316363ad3ee98dd6c969a4be1a7c32115579b 100644 (file)
@@ -33,8 +33,6 @@
 #include <wtf/OwnPtr.h>
 #include <Operations.h>
 
-#define CHECK_ARRAY_CONSISTENCY 0
-
 using namespace std;
 using namespace WTF;
 
@@ -80,13 +78,26 @@ ASSERT_CLASS_FITS_IN_CELL(JSArray);
 // 0xFFFFFFFF is a bit weird -- is not an array index even though it's an integer.
 #define MAX_ARRAY_INDEX 0xFFFFFFFEU
 
+// The value BASE_VECTOR_LEN is the maximum number of vector elements we'll allocate
+// for an array that was created with a sepcified length (e.g. a = new Array(123))
+#define BASE_VECTOR_LEN 4U
+    
+// The upper bound to the size we'll grow a zero length array when the first element
+// is added.
+#define FIRST_VECTOR_GROW 4U
+
 // Our policy for when to use a vector and when to use a sparse map.
 // For all array indices under MIN_SPARSE_ARRAY_INDEX, we always use a vector.
 // When indices greater than MIN_SPARSE_ARRAY_INDEX are involved, we use a vector
 // as long as it is 1/8 full. If more sparse than that, we use a map.
 static const unsigned minDensityMultiplier = 8;
 
-const ClassInfo JSArray::info = {"Array", 0, 0, 0};
+const ClassInfo JSArray::s_info = {"Array", &JSNonFinalObject::s_info, 0, 0};
+
+// 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.
+static unsigned lastArraySize = 0;
 
 static inline size_t storageSize(unsigned vectorLength)
 {
@@ -102,21 +113,6 @@ static inline size_t storageSize(unsigned vectorLength)
     return size;
 }
 
-static inline unsigned increasedVectorLength(unsigned newLength)
-{
-    ASSERT(newLength <= MAX_STORAGE_VECTOR_LENGTH);
-
-    // Mathematically equivalent to:
-    //   increasedLength = (newLength * 3 + 1) / 2;
-    // or:
-    //   increasedLength = (unsigned)ceil(newLength * 1.5));
-    // This form is not prone to internal overflow.
-    unsigned increasedLength = newLength + (newLength >> 1) + (newLength & 1);
-    ASSERT(increasedLength >= newLength);
-
-    return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
-}
-
 static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
 {
     return length / minDensityMultiplier <= numValues;
@@ -130,60 +126,109 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
 
 #endif
 
-JSArray::JSArray(NonNullPassRefPtr<Structure> structure)
-    : JSObject(structure)
+JSArray::JSArray(VPtrStealingHackType)
+    : JSNonFinalObject(VPtrStealingHack)
 {
+}
+
+JSArray::JSArray(JSGlobalData& globalData, Structure* structure)
+    : JSNonFinalObject(globalData, structure)
+{
+    ASSERT(inherits(&s_info));
+
     unsigned initialCapacity = 0;
 
     m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+    m_storage->m_allocBase = m_storage;
+    m_indexBias = 0;
     m_vectorLength = initialCapacity;
 
     checkConsistency();
+
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(0));
 }
 
-JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength)
-    : JSObject(structure)
+JSArray::JSArray(JSGlobalData& globalData, Structure* structure, unsigned initialLength, ArrayCreationMode creationMode)
+    : JSNonFinalObject(globalData, structure)
 {
-    unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX);
+    ASSERT(inherits(&s_info));
 
+    unsigned initialCapacity;
+    if (creationMode == CreateCompact)
+        initialCapacity = initialLength;
+    else
+        initialCapacity = min(BASE_VECTOR_LEN, MIN_SPARSE_ARRAY_INDEX);
+    
     m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
+    m_storage->m_allocBase = m_storage;
     m_storage->m_length = initialLength;
+    m_indexBias = 0;
     m_vectorLength = initialCapacity;
-    m_storage->m_numValuesInVector = 0;
     m_storage->m_sparseValueMap = 0;
     m_storage->subclassData = 0;
     m_storage->reportedMapCapacity = 0;
 
-    JSValue* vector = m_storage->m_vector;
-    for (size_t i = 0; i < initialCapacity; ++i)
-        vector[i] = JSValue();
+    if (creationMode == CreateCompact) {
+#if CHECK_ARRAY_CONSISTENCY
+        m_storage->m_inCompactInitialization = !!initialCapacity;
+#endif
+        m_storage->m_length = 0;
+        m_storage->m_numValuesInVector = initialCapacity;
+    } else {
+#if CHECK_ARRAY_CONSISTENCY
+        storage->m_inCompactInitialization = false;
+#endif
+        m_storage->m_length = initialLength;
+        m_storage->m_numValuesInVector = 0;
+        WriteBarrier<Unknown>* vector = m_storage->m_vector;
+        for (size_t i = 0; i < initialCapacity; ++i)
+            vector[i].clear();
+    }
 
     checkConsistency();
-
-    Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue));
+    
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
 }
 
-JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list)
-    : JSObject(structure)
+JSArray::JSArray(JSGlobalData& globalData, Structure* structure, const ArgList& list)
+    : JSNonFinalObject(globalData, structure)
 {
-    unsigned initialCapacity = list.size();
+    ASSERT(inherits(&s_info));
 
-    m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
+    unsigned initialCapacity = list.size();
+    unsigned initialStorage;
+    
+    // If the ArgList is empty, allocate space for 3 entries.  This value empirically
+    // works well for benchmarks.
+    if (!initialCapacity)
+        initialStorage = 3;
+    else
+        initialStorage = initialCapacity;
+    
+    m_storage = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialStorage)));
+    m_storage->m_allocBase = m_storage;
+    m_indexBias = 0;
     m_storage->m_length = initialCapacity;
-    m_vectorLength = initialCapacity;
+    m_vectorLength = initialStorage;
     m_storage->m_numValuesInVector = initialCapacity;
     m_storage->m_sparseValueMap = 0;
     m_storage->subclassData = 0;
     m_storage->reportedMapCapacity = 0;
+#if CHECK_ARRAY_CONSISTENCY
+    m_storage->m_inCompactInitialization = false;
+#endif
 
     size_t i = 0;
+    WriteBarrier<Unknown>* vector = m_storage->m_vector;
     ArgList::const_iterator end = list.end();
     for (ArgList::const_iterator it = list.begin(); it != end; ++it, ++i)
-        m_storage->m_vector[i] = *it;
+        vector[i].set(globalData, this, *it);
+    for (; i < initialStorage; i++)
+        vector[i].clear();
 
     checkConsistency();
 
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialStorage));
 }
 
 JSArray::~JSArray()
@@ -192,13 +237,13 @@ JSArray::~JSArray()
     checkConsistency(DestructorConsistencyCheck);
 
     delete m_storage->m_sparseValueMap;
-    fastFree(m_storage);
+    fastFree(m_storage->m_allocBase);
 }
 
 bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
 {
     ArrayStorage* storage = m_storage;
-
+    
     if (i >= storage->m_length) {
         if (i > MAX_ARRAY_INDEX)
             return getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
@@ -206,16 +251,16 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
     }
 
     if (i < m_vectorLength) {
-        JSValue& valueSlot = storage->m_vector[i];
-        if (valueSlot) {
-            slot.setValueSlot(&valueSlot);
+        JSValue value = storage->m_vector[i].get();
+        if (value) {
+            slot.setValue(value);
             return true;
         }
     } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
         if (i >= MIN_SPARSE_ARRAY_INDEX) {
             SparseArrayValueMap::iterator it = map->find(i);
             if (it != map->end()) {
-                slot.setValueSlot(&it->second);
+                slot.setValue(it->second.get());
                 return true;
             }
         }
@@ -227,12 +272,12 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot
 bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     if (propertyName == exec->propertyNames().length) {
-        slot.setValue(jsNumber(exec, length()));
+        slot.setValue(jsNumber(length()));
         return true;
     }
 
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
         return JSArray::getOwnPropertySlot(exec, i, slot);
 
@@ -242,26 +287,28 @@ bool JSArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName
 bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
     if (propertyName == exec->propertyNames().length) {
-        descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum);
+        descriptor.setDescriptor(jsNumber(length()), DontDelete | DontEnum);
         return true;
     }
+
+    ArrayStorage* storage = m_storage;
     
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
-        if (i >= m_storage->m_length)
+        if (i >= storage->m_length)
             return false;
         if (i < m_vectorLength) {
-            JSValue& value = m_storage->m_vector[i];
+            WriteBarrier<Unknown>& value = storage->m_vector[i];
             if (value) {
-                descriptor.setDescriptor(value, 0);
+                descriptor.setDescriptor(value.get(), 0);
                 return true;
             }
-        } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+        } else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
             if (i >= MIN_SPARSE_ARRAY_INDEX) {
                 SparseArrayValueMap::iterator it = map->find(i);
                 if (it != map->end()) {
-                    descriptor.setDescriptor(it->second, 0);
+                    descriptor.setDescriptor(it->second.get(), 0);
                     return true;
                 }
             }
@@ -274,7 +321,7 @@ bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& proper
 void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
         put(exec, i, value);
         return;
@@ -283,7 +330,7 @@ void JSArray::put(ExecState* exec, const Identifier& propertyName, JSValue value
     if (propertyName == exec->propertyNames().length) {
         unsigned newLength = value.toUInt32(exec);
         if (value.toNumber(exec) != static_cast<double>(newLength)) {
-            throwError(exec, RangeError, "Invalid array length.");
+            throwError(exec, createRangeError(exec, "Invalid array length."));
             return;
         }
         setLength(newLength);
@@ -297,21 +344,23 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
 {
     checkConsistency();
 
-    unsigned length = m_storage->m_length;
+    ArrayStorage* storage = m_storage;
+
+    unsigned length = storage->m_length;
     if (i >= length && i <= MAX_ARRAY_INDEX) {
         length = i + 1;
-        m_storage->m_length = length;
+        storage->m_length = length;
     }
 
     if (i < m_vectorLength) {
-        JSValue& valueSlot = m_storage->m_vector[i];
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
         if (valueSlot) {
-            valueSlot = value;
+            valueSlot.set(exec->globalData(), this, value);
             checkConsistency();
             return;
         }
-        valueSlot = value;
-        ++m_storage->m_numValuesInVector;
+        valueSlot.set(exec->globalData(), this, value);
+        ++storage->m_numValuesInVector;
         checkConsistency();
         return;
     }
@@ -322,6 +371,7 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
 NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue value)
 {
     ArrayStorage* storage = m_storage;
+    
     SparseArrayValueMap* map = storage->m_sparseValueMap;
 
     if (i >= MIN_SPARSE_ARRAY_INDEX) {
@@ -339,11 +389,11 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
                 storage->m_sparseValueMap = map;
             }
 
-            pair<SparseArrayValueMap::iterator, bool> result = map->add(i, value);
-            if (!result.second) { // pre-existing entry
-                result.first->second = value;
+            WriteBarrier<Unknown> temp;
+            pair<SparseArrayValueMap::iterator, bool> result = map->add(i, temp);
+            result.first->second.set(exec->globalData(), this, value);
+            if (!result.second) // pre-existing entry
                 return;
-            }
 
             size_t capacity = map->capacity();
             if (capacity != storage->reportedMapCapacity) {
@@ -359,7 +409,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
     if (!map || map->isEmpty()) {
         if (increaseVectorLength(i + 1)) {
             storage = m_storage;
-            storage->m_vector[i] = value;
+            storage->m_vector[i].set(exec->globalData(), this, value);
             ++storage->m_numValuesInVector;
             checkConsistency();
         } else
@@ -369,16 +419,17 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
 
     // Decide how many values it would be best to move from the map.
     unsigned newNumValuesInVector = storage->m_numValuesInVector + 1;
-    unsigned newVectorLength = increasedVectorLength(i + 1);
+    unsigned newVectorLength = getNewVectorLength(i + 1);
     for (unsigned j = max(m_vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
         newNumValuesInVector += map->contains(j);
     if (i >= MIN_SPARSE_ARRAY_INDEX)
         newNumValuesInVector -= map->contains(i);
     if (isDenseEnoughForVector(newVectorLength, newNumValuesInVector)) {
+        unsigned needLength = max(i + 1, storage->m_length);
         unsigned proposedNewNumValuesInVector = newNumValuesInVector;
         // If newVectorLength is already the maximum - MAX_STORAGE_VECTOR_LENGTH - then do not attempt to grow any further.
-        while (newVectorLength < MAX_STORAGE_VECTOR_LENGTH) {
-            unsigned proposedNewVectorLength = increasedVectorLength(newVectorLength + 1);
+        while ((newVectorLength < needLength) && (newVectorLength < MAX_STORAGE_VECTOR_LENGTH)) {
+            unsigned proposedNewVectorLength = getNewVectorLength(newVectorLength + 1);
             for (unsigned j = max(newVectorLength, MIN_SPARSE_ARRAY_INDEX); j < proposedNewVectorLength; ++j)
                 proposedNewNumValuesInVector += map->contains(j);
             if (!isDenseEnoughForVector(proposedNewVectorLength, proposedNewNumValuesInVector))
@@ -388,31 +439,39 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
         }
     }
 
-    if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) {
+    void* baseStorage = storage->m_allocBase;
+    
+    if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage)) {
         throwOutOfMemoryError(exec);
         return;
     }
 
+    m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue));
+    m_storage->m_allocBase = baseStorage;
+    storage = m_storage;
+    
     unsigned vectorLength = m_vectorLength;
+    WriteBarrier<Unknown>* vector = storage->m_vector;
 
     if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
         for (unsigned j = vectorLength; j < newVectorLength; ++j)
-            storage->m_vector[j] = JSValue();
+            vector[j].clear();
         if (i > MIN_SPARSE_ARRAY_INDEX)
             map->remove(i);
     } else {
         for (unsigned j = vectorLength; j < max(vectorLength, MIN_SPARSE_ARRAY_INDEX); ++j)
-            storage->m_vector[j] = JSValue();
+            vector[j].clear();
+        JSGlobalData& globalData = exec->globalData();
         for (unsigned j = max(vectorLength, MIN_SPARSE_ARRAY_INDEX); j < newVectorLength; ++j)
-            storage->m_vector[j] = map->take(j);
+            vector[j].set(globalData, this, map->take(j).get());
     }
 
-    storage->m_vector[i] = value;
+    ASSERT(i < newVectorLength);
 
     m_vectorLength = newVectorLength;
     storage->m_numValuesInVector = newNumValuesInVector;
 
-    m_storage = storage;
+    storage->m_vector[i].set(exec->globalData(), this, value);
 
     checkConsistency();
 
@@ -422,7 +481,7 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu
 bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName)
 {
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
         return deleteProperty(exec, i);
 
@@ -437,14 +496,14 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
     checkConsistency();
 
     ArrayStorage* storage = m_storage;
-
+    
     if (i < m_vectorLength) {
-        JSValue& valueSlot = storage->m_vector[i];
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
         if (!valueSlot) {
             checkConsistency();
             return false;
         }
-        valueSlot = JSValue();
+        valueSlot.clear();
         --storage->m_numValuesInVector;
         checkConsistency();
         return true;
@@ -476,7 +535,7 @@ void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNa
     // which almost certainly means a different structure for PropertyNameArray.
 
     ArrayStorage* storage = m_storage;
-
+    
     unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
     for (unsigned i = 0; i < usedVectorLength; ++i) {
         if (storage->m_vector[i])
@@ -495,6 +554,33 @@ void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNa
     JSObject::getOwnPropertyNames(exec, propertyNames, mode);
 }
 
+ALWAYS_INLINE unsigned JSArray::getNewVectorLength(unsigned desiredLength)
+{
+    ASSERT(desiredLength <= MAX_STORAGE_VECTOR_LENGTH);
+
+    unsigned increasedLength;
+    unsigned maxInitLength = min(m_storage->m_length, 100000U);
+
+    if (desiredLength < maxInitLength)
+        increasedLength = maxInitLength;
+    else if (!m_vectorLength)
+        increasedLength = max(desiredLength, lastArraySize);
+    else {
+        // Mathematically equivalent to:
+        //   increasedLength = (newLength * 3 + 1) / 2;
+        // or:
+        //   increasedLength = (unsigned)ceil(newLength * 1.5));
+        // This form is not prone to internal overflow.
+        increasedLength = desiredLength + (desiredLength >> 1) + (desiredLength & 1);
+    }
+
+    ASSERT(increasedLength >= desiredLength);
+
+    lastArraySize = min(increasedLength, FIRST_VECTOR_GROW);
+
+    return min(increasedLength, MAX_STORAGE_VECTOR_LENGTH);
+}
+
 bool JSArray::increaseVectorLength(unsigned newLength)
 {
     // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
@@ -505,37 +591,82 @@ bool JSArray::increaseVectorLength(unsigned newLength)
     unsigned vectorLength = m_vectorLength;
     ASSERT(newLength > vectorLength);
     ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
-    unsigned newVectorLength = increasedVectorLength(newLength);
+    unsigned newVectorLength = getNewVectorLength(newLength);
+    void* baseStorage = storage->m_allocBase;
 
-    if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage))
+    if (!tryFastRealloc(baseStorage, storageSize(newVectorLength + m_indexBias)).getValue(baseStorage))
         return false;
 
-    m_vectorLength = newVectorLength;
+    storage = m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + m_indexBias * sizeof(JSValue));
+    m_storage->m_allocBase = baseStorage;
 
+    WriteBarrier<Unknown>* vector = storage->m_vector;
     for (unsigned i = vectorLength; i < newVectorLength; ++i)
-        storage->m_vector[i] = JSValue();
-
-    m_storage = storage;
+        vector[i].clear();
 
+    m_vectorLength = newVectorLength;
+    
     Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
 
     return true;
 }
 
-void JSArray::setLength(unsigned newLength)
+bool JSArray::increaseVectorPrefixLength(unsigned newLength)
 {
-    checkConsistency();
+    // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map
+    // to the vector. Callers have to account for that, because they can do it more efficiently.
+    
+    ArrayStorage* storage = m_storage;
+    
+    unsigned vectorLength = m_vectorLength;
+    ASSERT(newLength > vectorLength);
+    ASSERT(newLength <= MAX_STORAGE_VECTOR_INDEX);
+    unsigned newVectorLength = getNewVectorLength(newLength);
 
+    void* newBaseStorage = fastMalloc(storageSize(newVectorLength + m_indexBias));
+    if (!newBaseStorage)
+        return false;
+    
+    m_indexBias += newVectorLength - newLength;
+    
+    m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(newBaseStorage) + m_indexBias * sizeof(JSValue));
+
+    memcpy(m_storage, storage, storageSize(0));
+    memcpy(&m_storage->m_vector[newLength - m_vectorLength], &storage->m_vector[0], vectorLength * sizeof(JSValue));
+    
+    m_storage->m_allocBase = newBaseStorage;
+    m_vectorLength = newLength;
+    
+    fastFree(storage->m_allocBase);
+    ASSERT(newLength > vectorLength);
+    unsigned delta = newLength - vectorLength;
+    for (unsigned i = 0; i < delta; i++)
+        m_storage->m_vector[i].clear();
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength));
+    
+    return true;
+}
+    
+
+void JSArray::setLength(unsigned newLength)
+{
     ArrayStorage* storage = m_storage;
+    
+#if CHECK_ARRAY_CONSISTENCY
+    if (!storage->m_inCompactInitialization)
+        checkConsistency();
+    else
+        storage->m_inCompactInitialization = false;
+#endif
 
-    unsigned length = m_storage->m_length;
+    unsigned length = storage->m_length;
 
     if (newLength < length) {
         unsigned usedVectorLength = min(length, m_vectorLength);
         for (unsigned i = newLength; i < usedVectorLength; ++i) {
-            JSValue& valueSlot = storage->m_vector[i];
+            WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
             bool hadValue = valueSlot;
-            valueSlot = JSValue();
+            valueSlot.clear();
             storage->m_numValuesInVector -= hadValue;
         }
 
@@ -553,7 +684,7 @@ void JSArray::setLength(unsigned newLength)
         }
     }
 
-    m_storage->m_length = newLength;
+    storage->m_length = newLength;
 
     checkConsistency();
 }
@@ -562,7 +693,9 @@ JSValue JSArray::pop()
 {
     checkConsistency();
 
-    unsigned length = m_storage->m_length;
+    ArrayStorage* storage = m_storage;
+    
+    unsigned length = storage->m_length;
     if (!length)
         return jsUndefined();
 
@@ -571,29 +704,29 @@ JSValue JSArray::pop()
     JSValue result;
 
     if (length < m_vectorLength) {
-        JSValue& valueSlot = m_storage->m_vector[length];
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[length];
         if (valueSlot) {
-            --m_storage->m_numValuesInVector;
-            result = valueSlot;
-            valueSlot = JSValue();
+            --storage->m_numValuesInVector;
+            result = valueSlot.get();
+            valueSlot.clear();
         } else
             result = jsUndefined();
     } else {
         result = jsUndefined();
-        if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+        if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
             SparseArrayValueMap::iterator it = map->find(length);
             if (it != map->end()) {
-                result = it->second;
+                result = it->second.get();
                 map->remove(it);
                 if (map->isEmpty()) {
                     delete map;
-                    m_storage->m_sparseValueMap = 0;
+                    storage->m_sparseValueMap = 0;
                 }
             }
         }
     }
 
-    m_storage->m_length = length;
+    storage->m_length = length;
 
     checkConsistency();
 
@@ -603,22 +736,25 @@ JSValue JSArray::pop()
 void JSArray::push(ExecState* exec, JSValue value)
 {
     checkConsistency();
+    
+    ArrayStorage* storage = m_storage;
 
-    if (m_storage->m_length < m_vectorLength) {
-        m_storage->m_vector[m_storage->m_length] = value;
-        ++m_storage->m_numValuesInVector;
-        ++m_storage->m_length;
+    if (storage->m_length < m_vectorLength) {
+        storage->m_vector[storage->m_length].set(exec->globalData(), this, value);
+        ++storage->m_numValuesInVector;
+        ++storage->m_length;
         checkConsistency();
         return;
     }
 
-    if (m_storage->m_length < MIN_SPARSE_ARRAY_INDEX) {
-        SparseArrayValueMap* map = m_storage->m_sparseValueMap;
+    if (storage->m_length < MIN_SPARSE_ARRAY_INDEX) {
+        SparseArrayValueMap* map = storage->m_sparseValueMap;
         if (!map || map->isEmpty()) {
-            if (increaseVectorLength(m_storage->m_length + 1)) {
-                m_storage->m_vector[m_storage->m_length] = value;
-                ++m_storage->m_numValuesInVector;
-                ++m_storage->m_length;
+            if (increaseVectorLength(storage->m_length + 1)) {
+                storage = m_storage;
+                storage->m_vector[storage->m_length].set(exec->globalData(), this, value);
+                ++storage->m_numValuesInVector;
+                ++storage->m_length;
                 checkConsistency();
                 return;
             }
@@ -628,12 +764,108 @@ void JSArray::push(ExecState* exec, JSValue value)
         }
     }
 
-    putSlowCase(exec, m_storage->m_length++, value);
+    putSlowCase(exec, storage->m_length++, value);
+}
+
+void JSArray::shiftCount(ExecState* exec, int count)
+{
+    ASSERT(count > 0);
+    
+    ArrayStorage* storage = m_storage;
+    
+    unsigned oldLength = storage->m_length;
+    
+    if (!oldLength)
+        return;
+    
+    if (oldLength != storage->m_numValuesInVector) {
+        // If m_length and m_numValuesInVector aren't the same, we have a sparse vector
+        // which means we need to go through each entry looking for the the "empty"
+        // slots and then fill them with possible properties.  See ECMA spec.
+        // 15.4.4.9 steps 11 through 13.
+        for (unsigned i = count; i < oldLength; ++i) {
+            if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) {
+                PropertySlot slot(this);
+                JSValue p = prototype();
+                if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot)))
+                    put(exec, i, slot.getValue(exec, i));
+            }
+        }
+
+        storage = m_storage; // The put() above could have grown the vector and realloc'ed storage.
+
+        // Need to decrement numValuesInvector based on number of real entries
+        for (unsigned i = 0; i < (unsigned)count; ++i)
+            if ((i < m_vectorLength) && (storage->m_vector[i]))
+                --storage->m_numValuesInVector;
+    } else
+        storage->m_numValuesInVector -= count;
+    
+    storage->m_length -= count;
+    
+    if (m_vectorLength) {
+        count = min(m_vectorLength, (unsigned)count);
+        
+        m_vectorLength -= count;
+        
+        if (m_vectorLength) {
+            char* newBaseStorage = reinterpret_cast<char*>(storage) + count * sizeof(JSValue);
+            memmove(newBaseStorage, storage, storageSize(0));
+            m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
+
+            m_indexBias += count;
+        }
+    }
+}
+    
+void JSArray::unshiftCount(ExecState* exec, int count)
+{
+    ArrayStorage* storage = m_storage;
+
+    ASSERT(m_indexBias >= 0);
+    ASSERT(count >= 0);
+    
+    unsigned length = storage->m_length;
+    
+    if (length != storage->m_numValuesInVector) {
+        // If m_length and m_numValuesInVector aren't the same, we have a sparse vector
+        // which means we need to go through each entry looking for the the "empty"
+        // slots and then fill them with possible properties.  See ECMA spec.
+        // 15.4.4.13 steps 8 through 10.
+        for (unsigned i = 0; i < length; ++i) {
+            if ((i >= m_vectorLength) || (!m_storage->m_vector[i])) {
+                PropertySlot slot(this);
+                JSValue p = prototype();
+                if ((!p.isNull()) && (asObject(p)->getPropertySlot(exec, i, slot)))
+                    put(exec, i, slot.getValue(exec, i));
+            }
+        }
+    }
+    
+    storage = m_storage; // The put() above could have grown the vector and realloc'ed storage.
+    
+    if (m_indexBias >= count) {
+        m_indexBias -= count;
+        char* newBaseStorage = reinterpret_cast<char*>(storage) - count * sizeof(JSValue);
+        memmove(newBaseStorage, storage, storageSize(0));
+        m_storage = reinterpret_cast_ptr<ArrayStorage*>(newBaseStorage);
+        m_vectorLength += count;
+    } else if (!increaseVectorPrefixLength(m_vectorLength + count)) {
+        throwOutOfMemoryError(exec);
+        return;
+    }
+
+    WriteBarrier<Unknown>* vector = m_storage->m_vector;
+    for (int i = 0; i < count; i++)
+        vector[i].clear();
 }
 
-void JSArray::markChildren(MarkStack& markStack)
+void JSArray::visitChildren(SlotVisitor& visitor)
 {
-    markChildrenDirect(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    visitChildrenDirect(visitor);
 }
 
 static int compareNumbersForQSort(const void* a, const void* b)
@@ -647,13 +879,15 @@ static int compareByStringPairForQSort(const void* a, const void* b)
 {
     const ValueStringPair* va = static_cast<const ValueStringPair*>(a);
     const ValueStringPair* vb = static_cast<const ValueStringPair*>(b);
-    return compare(va->second, vb->second);
+    return codePointCompare(va->second, vb->second);
 }
 
 void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
 {
+    ArrayStorage* storage = m_storage;
+
     unsigned lengthNotIncludingUndefined = compactForSorting();
-    if (m_storage->m_sparseValueMap) {
+    if (storage->m_sparseValueMap) {
         throwOutOfMemoryError(exec);
         return;
     }
@@ -662,9 +896,9 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
         return;
         
     bool allValuesAreNumbers = true;
-    size_t size = m_storage->m_numValuesInVector;
+    size_t size = storage->m_numValuesInVector;
     for (size_t i = 0; i < size; ++i) {
-        if (!m_storage->m_vector[i].isNumber()) {
+        if (!storage->m_vector[i].isNumber()) {
             allValuesAreNumbers = false;
             break;
         }
@@ -676,15 +910,17 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
     // For numeric comparison, which is fast, qsort is faster than mergesort. We
     // also don't require mergesort's stability, since there's no user visible
     // side-effect from swapping the order of equal primitive values.
-    qsort(m_storage->m_vector, size, sizeof(JSValue), compareNumbersForQSort);
+    qsort(storage->m_vector, size, sizeof(JSValue), compareNumbersForQSort);
 
     checkConsistency(SortConsistencyCheck);
 }
 
 void JSArray::sort(ExecState* exec)
 {
+    ArrayStorage* storage = m_storage;
+
     unsigned lengthNotIncludingUndefined = compactForSorting();
-    if (m_storage->m_sparseValueMap) {
+    if (storage->m_sparseValueMap) {
         throwOutOfMemoryError(exec);
         return;
     }
@@ -706,7 +942,7 @@ void JSArray::sort(ExecState* exec)
     Heap::heap(this)->pushTempSortVector(&values);
 
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++) {
-        JSValue value = m_storage->m_vector[i];
+        JSValue value = storage->m_vector[i].get();
         ASSERT(!value.isUndefined());
         values[i].first = value;
     }
@@ -737,11 +973,12 @@ void JSArray::sort(ExecState* exec)
     // increase the length to handle the orignal number of actual values.
     if (m_vectorLength < lengthNotIncludingUndefined)
         increaseVectorLength(lengthNotIncludingUndefined);
-    if (m_storage->m_length < lengthNotIncludingUndefined)
-        m_storage->m_length = lengthNotIncludingUndefined;
-        
+    if (storage->m_length < lengthNotIncludingUndefined)
+        storage->m_length = lengthNotIncludingUndefined;
+
+    JSGlobalData& globalData = exec->globalData();
     for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
-        m_storage->m_vector[i] = values[i].first;
+        storage->m_vector[i].set(globalData, this, values[i].first);
 
     Heap::heap(this)->popTempSortVector(&values);
     
@@ -830,18 +1067,21 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 {
     checkConsistency();
 
+    ArrayStorage* storage = m_storage;
+
     // FIXME: This ignores exceptions raised in the compare function or in toNumber.
 
     // The maximum tree depth is compiled in - but the caller is clearly up to no good
     // if a larger array is passed.
-    ASSERT(m_storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
-    if (m_storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
+    ASSERT(storage->m_length <= static_cast<unsigned>(std::numeric_limits<int>::max()));
+    if (storage->m_length > static_cast<unsigned>(std::numeric_limits<int>::max()))
         return;
 
-    if (!m_storage->m_length)
-        return;
+    unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
+    unsigned nodeCount = usedVectorLength + (storage->m_sparseValueMap ? storage->m_sparseValueMap->size() : 0);
 
-    unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
+    if (!nodeCount)
+        return;
 
     AVLTree<AVLTreeAbstractorForArrayCompare, 44> tree; // Depth 44 is enough for 2^31 items
     tree.abstractor().m_exec = exec;
@@ -849,10 +1089,10 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
     tree.abstractor().m_compareCallType = callType;
     tree.abstractor().m_compareCallData = &callData;
     tree.abstractor().m_globalThisValue = exec->globalThisValue();
-    tree.abstractor().m_nodes.resize(usedVectorLength + (m_storage->m_sparseValueMap ? m_storage->m_sparseValueMap->size() : 0));
+    tree.abstractor().m_nodes.grow(nodeCount);
 
     if (callType == CallTypeJS)
-        tree.abstractor().m_cachedCall.set(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot()));
+        tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2));
 
     if (!tree.abstractor().m_nodes.begin()) {
         throwOutOfMemoryError(exec);
@@ -867,14 +1107,14 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 
     // Iterate over the array, ignoring missing values, counting undefined ones, and inserting all other ones into the tree.
     for (; numDefined < usedVectorLength; ++numDefined) {
-        JSValue v = m_storage->m_vector[numDefined];
+        JSValue v = storage->m_vector[numDefined].get();
         if (!v || v.isUndefined())
             break;
         tree.abstractor().m_nodes[numDefined].value = v;
         tree.insert(numDefined);
     }
     for (unsigned i = numDefined; i < usedVectorLength; ++i) {
-        JSValue v = m_storage->m_vector[i];
+        JSValue v = storage->m_vector[i].get();
         if (v) {
             if (v.isUndefined())
                 ++numUndefined;
@@ -888,7 +1128,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 
     unsigned newUsedVectorLength = numDefined + numUndefined;
 
-    if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
+    if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
         newUsedVectorLength += map->size();
         if (newUsedVectorLength > m_vectorLength) {
             // Check that it is possible to allocate an array large enough to hold all the entries.
@@ -897,16 +1137,18 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
                 return;
             }
         }
+        
+        storage = m_storage;
 
         SparseArrayValueMap::iterator end = map->end();
         for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
-            tree.abstractor().m_nodes[numDefined].value = it->second;
+            tree.abstractor().m_nodes[numDefined].value = it->second.get();
             tree.insert(numDefined);
             ++numDefined;
         }
 
         delete map;
-        m_storage->m_sparseValueMap = 0;
+        storage->m_sparseValueMap = 0;
     }
 
     ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
@@ -917,37 +1159,40 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
     // Copy the values back into m_storage.
     AVLTree<AVLTreeAbstractorForArrayCompare, 44>::Iterator iter;
     iter.start_iter_least(tree);
+    JSGlobalData& globalData = exec->globalData();
     for (unsigned i = 0; i < numDefined; ++i) {
-        m_storage->m_vector[i] = tree.abstractor().m_nodes[*iter].value;
+        storage->m_vector[i].set(globalData, this, tree.abstractor().m_nodes[*iter].value);
         ++iter;
     }
 
     // Put undefined values back in.
     for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
-        m_storage->m_vector[i] = jsUndefined();
+        storage->m_vector[i].setUndefined();
 
     // Ensure that unused values in the vector are zeroed out.
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
-        m_storage->m_vector[i] = JSValue();
+        storage->m_vector[i].clear();
 
-    m_storage->m_numValuesInVector = newUsedVectorLength;
+    storage->m_numValuesInVector = newUsedVectorLength;
 
     checkConsistency(SortConsistencyCheck);
 }
 
 void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
 {
-    JSValue* vector = m_storage->m_vector;
-    unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
+    ArrayStorage* storage = m_storage;
+
+    WriteBarrier<Unknown>* vector = storage->m_vector;
+    unsigned vectorEnd = min(storage->m_length, m_vectorLength);
     unsigned i = 0;
     for (; i < vectorEnd; ++i) {
-        JSValue& v = vector[i];
+        WriteBarrier<Unknown>& v = vector[i];
         if (!v)
             break;
-        args.append(v);
+        args.append(v.get());
     }
 
-    for (; i < m_storage->m_length; ++i)
+    for (; i < storage->m_length; ++i)
         args.append(get(exec, i));
 }
 
@@ -955,14 +1200,14 @@ void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSiz
 {
     ASSERT(m_storage->m_length >= maxSize);
     UNUSED_PARAM(maxSize);
-    JSValue* vector = m_storage->m_vector;
+    WriteBarrier<Unknown>* vector = m_storage->m_vector;
     unsigned vectorEnd = min(maxSize, m_vectorLength);
     unsigned i = 0;
     for (; i < vectorEnd; ++i) {
-        JSValue& v = vector[i];
+        WriteBarrier<Unknown>& v = vector[i];
         if (!v)
             break;
-        buffer[i] = v;
+        buffer[i] = v.get();
     }
 
     for (; i < maxSize; ++i)
@@ -975,23 +1220,24 @@ unsigned JSArray::compactForSorting()
 
     ArrayStorage* storage = m_storage;
 
-    unsigned usedVectorLength = min(m_storage->m_length, m_vectorLength);
+    unsigned usedVectorLength = min(storage->m_length, m_vectorLength);
 
     unsigned numDefined = 0;
     unsigned numUndefined = 0;
 
     for (; numDefined < usedVectorLength; ++numDefined) {
-        JSValue v = storage->m_vector[numDefined];
+        JSValue v = storage->m_vector[numDefined].get();
         if (!v || v.isUndefined())
             break;
     }
+
     for (unsigned i = numDefined; i < usedVectorLength; ++i) {
-        JSValue v = storage->m_vector[i];
+        JSValue v = storage->m_vector[i].get();
         if (v) {
             if (v.isUndefined())
                 ++numUndefined;
             else
-                storage->m_vector[numDefined++] = v;
+                storage->m_vector[numDefined++].setWithoutWriteBarrier(v);
         }
     }
 
@@ -1004,21 +1250,22 @@ unsigned JSArray::compactForSorting()
             // exception is thrown by caller.
             if ((newUsedVectorLength > MAX_STORAGE_VECTOR_LENGTH) || !increaseVectorLength(newUsedVectorLength))
                 return 0;
+
             storage = m_storage;
         }
 
         SparseArrayValueMap::iterator end = map->end();
         for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
-            storage->m_vector[numDefined++] = it->second;
+            storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.get());
 
         delete map;
         storage->m_sparseValueMap = 0;
     }
 
     for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
-        storage->m_vector[i] = jsUndefined();
+        storage->m_vector[i].setUndefined();
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
-        storage->m_vector[i] = JSValue();
+        storage->m_vector[i].clear();
 
     storage->m_numValuesInVector = newUsedVectorLength;
 
@@ -1041,35 +1288,37 @@ void JSArray::setSubclassData(void* d)
 
 void JSArray::checkConsistency(ConsistencyCheckType type)
 {
-    ASSERT(m_storage);
+    ArrayStorage* storage = m_storage;
+
+    ASSERT(storage);
     if (type == SortConsistencyCheck)
-        ASSERT(!m_storage->m_sparseValueMap);
+        ASSERT(!storage->m_sparseValueMap);
 
     unsigned numValuesInVector = 0;
     for (unsigned i = 0; i < m_vectorLength; ++i) {
-        if (JSValue value = m_storage->m_vector[i]) {
-            ASSERT(i < m_storage->m_length);
+        if (JSValue value = storage->m_vector[i]) {
+            ASSERT(i < storage->m_length);
             if (type != DestructorConsistencyCheck)
-                value->type(); // Likely to crash if the object was deallocated.
+                value.isUndefined(); // Likely to crash if the object was deallocated.
             ++numValuesInVector;
         } else {
             if (type == SortConsistencyCheck)
-                ASSERT(i >= m_storage->m_numValuesInVector);
+                ASSERT(i >= storage->m_numValuesInVector);
         }
     }
-    ASSERT(numValuesInVector == m_storage->m_numValuesInVector);
-    ASSERT(numValuesInVector <= m_storage->m_length);
+    ASSERT(numValuesInVector == storage->m_numValuesInVector);
+    ASSERT(numValuesInVector <= storage->m_length);
 
-    if (m_storage->m_sparseValueMap) {
-        SparseArrayValueMap::iterator end = m_storage->m_sparseValueMap->end();
-        for (SparseArrayValueMap::iterator it = m_storage->m_sparseValueMap->begin(); it != end; ++it) {
+    if (storage->m_sparseValueMap) {
+        SparseArrayValueMap::iterator end = storage->m_sparseValueMap->end();
+        for (SparseArrayValueMap::iterator it = storage->m_sparseValueMap->begin(); it != end; ++it) {
             unsigned index = it->first;
-            ASSERT(index < m_storage->m_length);
-            ASSERT(index >= m_vectorLength);
+            ASSERT(index < storage->m_length);
+            ASSERT(index >= storage->m_vectorLength);
             ASSERT(index <= MAX_ARRAY_INDEX);
             ASSERT(it->second);
             if (type != DestructorConsistencyCheck)
-                it->second->type(); // Likely to crash if the object was deallocated.
+                it->second.isUndefined(); // Likely to crash if the object was deallocated.
         }
     }
 }
index f65f2bcf70ebf9869f7b7c42c86aac3777b10d88..3cb8aadeae342874e7990235e52aba17f3f5d44e 100644 (file)
 
 #include "JSObject.h"
 
+#define CHECK_ARRAY_CONSISTENCY 0
+
 namespace JSC {
 
-    typedef HashMap<unsigned, JSValue> SparseArrayValueMap;
+    typedef HashMap<unsigned, WriteBarrier<Unknown> > SparseArrayValueMap;
 
+    // This struct holds the actual data values of an array.  A JSArray object points to it's contained ArrayStorage
+    // struct by pointing to m_vector.  To access the contained ArrayStorage struct, use the getStorage() and 
+    // setStorage() methods.  It is important to note that there may be space before the ArrayStorage that 
+    // is used to quick unshift / shift operation.  The actual allocated pointer is available by using:
+    //     getStorage() - m_indexBias * sizeof(JSValue)
     struct ArrayStorage {
-        unsigned m_length;
+        unsigned m_length; // The "length" property on the array
         unsigned m_numValuesInVector;
         SparseArrayValueMap* m_sparseValueMap;
         void* subclassData; // A JSArray subclass can use this to fill the vector lazily.
+        void* m_allocBase; // Pointer to base address returned by malloc().  Keeping this pointer does eliminate false positives from the leak detector.
         size_t reportedMapCapacity;
-        JSValue m_vector[1];
+#if CHECK_ARRAY_CONSISTENCY
+        bool m_inCompactInitialization;
+#endif
+        WriteBarrier<Unknown> m_vector[1];
     };
 
-    class JSArray : public JSObject {
-        friend class JIT;
+    // The CreateCompact creation mode is used for fast construction of arrays
+    // whose size and contents are known at time of creation.
+    //
+    // There are two obligations when using this mode:
+    //
+    //   - uncheckedSetIndex() must be used when initializing the array.
+    //   - setLength() must be called after initialization.
+
+    enum ArrayCreationMode { CreateCompact, CreateInitialized };
+
+    class JSArray : public JSNonFinalObject {
         friend class Walker;
 
     public:
-        explicit JSArray(NonNullPassRefPtr<Structure>);
-        JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength);
-        JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues);
+        JSArray(VPtrStealingHackType);
+
+        explicit JSArray(JSGlobalData&, Structure*);
+        JSArray(JSGlobalData&, Structure*, unsigned initialLength, ArrayCreationMode);
+        JSArray(JSGlobalData&, Structure*, const ArgList& initialValues);
         virtual ~JSArray();
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -51,8 +73,8 @@ namespace JSC {
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
 
-        static JS_EXPORTDATA const ClassInfo info;
-
+        static JS_EXPORTDATA const ClassInfo s_info;
+        
         unsigned length() const { return m_storage->m_length; }
         void setLength(unsigned); // OK to use on new arrays, but not if it might be a RegExpMatchArray.
 
@@ -63,69 +85,95 @@ namespace JSC {
         void push(ExecState*, JSValue);
         JSValue pop();
 
+        void shiftCount(ExecState*, int count);
+        void unshiftCount(ExecState*, int count);
+
         bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; }
         JSValue getIndex(unsigned i)
         {
             ASSERT(canGetIndex(i));
-            return m_storage->m_vector[i];
+            return m_storage->m_vector[i].get();
         }
 
         bool canSetIndex(unsigned i) { return i < m_vectorLength; }
-        void setIndex(unsigned i, JSValue v)
+        void setIndex(JSGlobalData& globalData, unsigned i, JSValue v)
         {
             ASSERT(canSetIndex(i));
-            JSValue& x = m_storage->m_vector[i];
+            
+            WriteBarrier<Unknown>& x = m_storage->m_vector[i];
             if (!x) {
-                ++m_storage->m_numValuesInVector;
-                if (i >= m_storage->m_length)
-                    m_storage->m_length = i + 1;
+                ArrayStorage *storage = m_storage;
+                ++storage->m_numValuesInVector;
+                if (i >= storage->m_length)
+                    storage->m_length = i + 1;
             }
-            x = v;
+            x.set(globalData, this, v);
+        }
+        
+        void uncheckedSetIndex(JSGlobalData& globalData, unsigned i, JSValue v)
+        {
+            ASSERT(canSetIndex(i));
+            ArrayStorage *storage = m_storage;
+#if CHECK_ARRAY_CONSISTENCY
+            ASSERT(storage->m_inCompactInitialization);
+#endif
+            storage->m_vector[i].set(globalData, this, v);
         }
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
         void copyToRegisters(ExecState*, Register*, uint32_t);
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
         
-        inline void markChildrenDirect(MarkStack& markStack);
+        inline void visitChildrenDirect(SlotVisitor&);
+
+        static ptrdiff_t storageOffset()
+        {
+            return OBJECT_OFFSETOF(JSArray, m_storage);
+        }
+
+        static ptrdiff_t vectorLengthOffset()
+        {
+            return OBJECT_OFFSETOF(JSArray, m_vectorLength);
+        }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
         void* subclassData() const;
         void setSubclassData(void*);
 
     private:
-        virtual const ClassInfo* classInfo() const { return &info; }
-
         bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
         void putSlowCase(ExecState*, unsigned propertyName, JSValue);
 
+        unsigned getNewVectorLength(unsigned desiredLength);
         bool increaseVectorLength(unsigned newLength);
+        bool increaseVectorPrefixLength(unsigned newLength);
         
         unsigned compactForSorting();
 
         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
 
-        unsigned m_vectorLength;
-        ArrayStorage* m_storage;
+        unsigned m_vectorLength; // The valid length of m_vector
+        int m_indexBias; // The number of JSValue sized blocks before ArrayStorage.
+        ArrayStorage *m_storage;
     };
 
     JSArray* asArray(JSValue);
 
     inline JSArray* asArray(JSCell* cell)
     {
-        ASSERT(cell->inherits(&JSArray::info));
+        ASSERT(cell->inherits(&JSArray::s_info));
         return static_cast<JSArray*>(cell);
     }
 
@@ -134,93 +182,35 @@ namespace JSC {
         return asArray(value.asCell());
     }
 
-    inline bool isJSArray(JSGlobalData* globalData, JSValue v)
-    {
-        return v.isCell() && v.asCell()->vptr() == globalData->jsArrayVPtr;
-    }
     inline bool isJSArray(JSGlobalData* globalData, JSCell* cell) { return cell->vptr() == globalData->jsArrayVPtr; }
+    inline bool isJSArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && isJSArray(globalData, v.asCell()); }
 
-    inline void JSArray::markChildrenDirect(MarkStack& markStack)
+    inline void JSArray::visitChildrenDirect(SlotVisitor& visitor)
     {
-        JSObject::markChildrenDirect(markStack);
+        JSObject::visitChildrenDirect(visitor);
         
         ArrayStorage* storage = m_storage;
 
         unsigned usedVectorLength = std::min(storage->m_length, m_vectorLength);
-        markStack.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
+        visitor.appendValues(storage->m_vector, usedVectorLength, MayContainNullValues);
 
         if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
             SparseArrayValueMap::iterator end = map->end();
             for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it)
-                markStack.append(it->second);
+                visitor.append(&it->second);
         }
     }
 
-    inline void MarkStack::markChildren(JSCell* cell)
+    // Rule from ECMA 15.2 about what an array index is.
+    // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
+    inline unsigned Identifier::toArrayIndex(bool& ok) const
     {
-        ASSERT(Heap::isCellMarked(cell));
-        if (!cell->structure()->typeInfo().overridesMarkChildren()) {
-#ifdef NDEBUG
-            asObject(cell)->markChildrenDirect(*this);
-#else
-            ASSERT(!m_isCheckingForDefaultMarkViolation);
-            m_isCheckingForDefaultMarkViolation = true;
-            cell->markChildren(*this);
-            ASSERT(m_isCheckingForDefaultMarkViolation);
-            m_isCheckingForDefaultMarkViolation = false;
-#endif
-            return;
-        }
-        if (cell->vptr() == m_jsArrayVPtr) {
-            asArray(cell)->markChildrenDirect(*this);
-            return;
-        }
-        cell->markChildren(*this);
+        unsigned i = toUInt32(ok);
+        if (ok && i >= 0xFFFFFFFFU)
+            ok = false;
+        return i;
     }
 
-    inline void MarkStack::drain()
-    {
-        while (!m_markSets.isEmpty() || !m_values.isEmpty()) {
-            while (!m_markSets.isEmpty() && m_values.size() < 50) {
-                ASSERT(!m_markSets.isEmpty());
-                MarkSet& current = m_markSets.last();
-                ASSERT(current.m_values);
-                JSValue* end = current.m_end;
-                ASSERT(current.m_values);
-                ASSERT(current.m_values != end);
-            findNextUnmarkedNullValue:
-                ASSERT(current.m_values != end);
-                JSValue value = *current.m_values;
-                current.m_values++;
-
-                JSCell* cell;
-                if (!value || !value.isCell() || Heap::isCellMarked(cell = value.asCell())) {
-                    if (current.m_values == end) {
-                        m_markSets.removeLast();
-                        continue;
-                    }
-                    goto findNextUnmarkedNullValue;
-                }
-
-                Heap::markCell(cell);
-                if (cell->structure()->typeInfo().type() < CompoundType) {
-                    if (current.m_values == end) {
-                        m_markSets.removeLast();
-                        continue;
-                    }
-                    goto findNextUnmarkedNullValue;
-                }
-
-                if (current.m_values == end)
-                    m_markSets.removeLast();
-
-                markChildren(cell);
-            }
-            while (!m_values.isEmpty())
-                markChildren(m_values.removeLast());
-        }
-    }
-    
 } // namespace JSC
 
 #endif // JSArray_h
index 803a08c97c23100f640c6904dbc04d3719de8d60..c2abaee1c8fbfc1eb846f9908d647d1aaa4e193d 100644 (file)
@@ -33,14 +33,13 @@ using namespace WTF;
 
 namespace JSC {
 
-const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 };
+const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", &Base::s_info, 0, 0 };
 
-JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo)
-    : JSObject(structure)
+JSByteArray::JSByteArray(ExecState* exec, Structure* structure, ByteArray* storage)
+    : JSNonFinalObject(exec->globalData(), structure)
     , m_storage(storage)
-    , m_classInfo(classInfo)
 {
-    putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete);
+    putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete);
 }
 
 #if !ASSERT_DISABLED
@@ -51,16 +50,15 @@ JSByteArray::~JSByteArray()
 #endif
 
 
-PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype)
+Structure* JSByteArray::createStructure(JSGlobalData& globalData, JSValue prototype, const JSC::ClassInfo* classInfo)
 {
-    PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
-    return result;
+    return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, classInfo);
 }
 
 bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     bool ok;
-    unsigned index = propertyName.toUInt32(&ok, false);
+    unsigned index = propertyName.toUInt32(ok);
     if (ok && canAccessIndex(index)) {
         slot.setValue(getIndex(exec, index));
         return true;
@@ -71,7 +69,7 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, const Identifier& property
 bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
     bool ok;
-    unsigned index = propertyName.toUInt32(&ok, false);
+    unsigned index = propertyName.toUInt32(ok);
     if (ok && canAccessIndex(index)) {
         descriptor.setDescriptor(getIndex(exec, index), DontDelete);
         return true;
@@ -91,7 +89,7 @@ bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Pro
 void JSByteArray::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     bool ok;
-    unsigned index = propertyName.toUInt32(&ok, false);
+    unsigned index = propertyName.toUInt32(ok);
     if (ok) {
         setIndex(exec, index, value);
         return;
index 5b7adcf88841da9f98e0534ecfa527fd867d1053..c481bb4c8b93ec1612971da1495a76e72bdf5b4d 100644 (file)
 
 namespace JSC {
 
-    class JSByteArray : public JSObject {
+    class JSByteArray : public JSNonFinalObject {
         friend class JSGlobalData;
     public:
+        typedef JSNonFinalObject Base;
+
         bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
-        JSValue getIndex(ExecState* exec, unsigned i)
+        JSValue getIndex(ExecState*, unsigned i)
         {
             ASSERT(canAccessIndex(i));
-            return jsNumber(exec, m_storage->data()[i]);
+            return jsNumber(m_storage->data()[i]);
         }
 
         void setIndex(unsigned i, int value)
@@ -73,9 +75,9 @@ namespace JSC {
                 setIndex(i, byteValue);
         }
 
-        JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo);
-        static PassRefPtr<Structure> createStructure(JSValue prototype);
-        
+        JSByteArray(ExecState*, Structure*, WTF::ByteArray* storage);
+        static Structure* createStructure(JSGlobalData&, JSValue prototype, const JSC::ClassInfo* = &s_defaultInfo);
+
         virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
         virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
@@ -84,7 +86,6 @@ namespace JSC {
 
         virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
-        virtual const ClassInfo* classInfo() const { return m_classInfo; }
         static const ClassInfo s_defaultInfo;
         
         size_t length() const { return m_storage->length(); }
@@ -99,21 +100,18 @@ namespace JSC {
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
 
     private:
-        enum VPtrStealingHackType { VPtrStealingHack };
-        JSByteArray(VPtrStealingHackType) 
-            : JSObject(createStructure(jsNull()))
-            , m_classInfo(0)
+        JSByteArray(VPtrStealingHackType)
+            : JSNonFinalObject(VPtrStealingHack)
         {
         }
 
         RefPtr<WTF::ByteArray> m_storage;
-        const ClassInfo* m_classInfo;
     };
     
     JSByteArray* asByteArray(JSValue value);
     inline JSByteArray* asByteArray(JSValue value)
     {
-        return static_cast<JSByteArray*>(asCell(value));
+        return static_cast<JSByteArray*>(value.asCell());
     }
 
     inline bool isJSByteArray(JSGlobalData* globalData, JSValue v) { return v.isCell() && v.asCell()->vptr() == globalData->jsByteArrayVPtr; }
index 0cc1ab1b7a6e419534e7e52d7b8b483480efd3be..0606cd40886f3376d45cffb4361559c3989a7a55 100644 (file)
@@ -76,6 +76,8 @@ extern const double Inf = NaNInf.doubles.Inf_Double;
  
 #endif // !(defined NAN && defined INFINITY)
 
+const ClassInfo JSCell::s_dummyCellInfo = { "DummyCell", 0, 0, 0 };
+
 bool JSCell::getUInt32(uint32_t&) const
 {
     return false;
@@ -119,7 +121,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, P
     // This is not a general purpose implementation of getOwnPropertySlot.
     // It should only be called by JSValue::get.
     // It calls getPropertySlot, not getOwnPropertySlot.
-    JSObject* object = toObject(exec);
+    JSObject* object = toObject(exec, exec->lexicalGlobalObject());
     slot.setBase(object);
     if (!object->getPropertySlot(exec, identifier, slot))
         slot.setUndefined();
@@ -131,7 +133,7 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl
     // This is not a general purpose implementation of getOwnPropertySlot.
     // It should only be called by JSValue::get.
     // It calls getPropertySlot, not getOwnPropertySlot.
-    JSObject* object = toObject(exec);
+    JSObject* object = toObject(exec, exec->lexicalGlobalObject());
     slot.setBase(object);
     if (!object->getPropertySlot(exec, identifier, slot))
         slot.setUndefined();
@@ -140,32 +142,27 @@ bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySl
 
 void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
 {
-    toObject(exec)->put(exec, identifier, value, slot);
+    toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value, slot);
 }
 
 void JSCell::put(ExecState* exec, unsigned identifier, JSValue value)
 {
-    toObject(exec)->put(exec, identifier, value);
+    toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value);
 }
 
 bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier)
 {
-    return toObject(exec)->deleteProperty(exec, identifier);
+    return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier);
 }
 
 bool JSCell::deleteProperty(ExecState* exec, unsigned identifier)
 {
-    return toObject(exec)->deleteProperty(exec, identifier);
+    return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier);
 }
 
 JSObject* JSCell::toThisObject(ExecState* exec) const
 {
-    return toObject(exec);
-}
-
-const ClassInfo* JSCell::classInfo() const
-{
-    return 0;
+    return toObject(exec, exec->lexicalGlobalObject());
 }
 
 JSValue JSCell::getJSNumber()
@@ -208,10 +205,25 @@ UString JSCell::toString(ExecState*) const
     return UString();
 }
 
-JSObject* JSCell::toObject(ExecState*) const
+JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const
 {
     ASSERT_NOT_REACHED();
     return 0;
 }
 
+bool isZombie(const JSCell* cell)
+{
+#if ENABLE(JSC_ZOMBIES)
+    return cell && cell->isZombie();
+#else
+    UNUSED_PARAM(cell);
+    return false;
+#endif
+}
+
+void slowValidateCell(JSCell* cell)
+{
+    ASSERT_GC_OBJECT_LOOKS_VALID(cell);
+}
+
 } // namespace JSC
index ae5aca3bf422eccde0516fce73fdc44cf66683f6..e30bc183ff69ce2396acef956e15ca566d15777d 100644 (file)
 #ifndef JSCell_h
 #define JSCell_h
 
-#include "Collector.h"
-#include "JSImmediate.h"
-#include "JSValue.h"
+#include "CallData.h"
+#include "CallFrame.h"
+#include "ConstructData.h"
+#include "Heap.h"
+#include "JSLock.h"
+#include "JSValueInlineMethods.h"
 #include "MarkStack.h"
-#include "Structure.h"
+#include "WriteBarrier.h"
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
-    class JSCell : public NoncopyableCustomAllocated {
+    class JSGlobalObject;
+    class Structure;
+
+#if COMPILER(MSVC)
+    // If WTF_MAKE_NONCOPYABLE is applied to JSCell we end up with a bunch of
+    // undefined references to the JSCell copy constructor and assignment operator
+    // when linking JavaScriptCore.
+    class MSVCBugWorkaround {
+        WTF_MAKE_NONCOPYABLE(MSVCBugWorkaround);
+
+    protected:
+        MSVCBugWorkaround() { }
+        ~MSVCBugWorkaround() { }
+    };
+
+    class JSCell : MSVCBugWorkaround {
+#else
+    class JSCell {
+        WTF_MAKE_NONCOPYABLE(JSCell);
+#endif
+
+        friend class ExecutableBase;
         friend class GetterSetter;
         friend class Heap;
-        friend class JIT;
-        friend class JSNumberCell;
         friend class JSObject;
         friend class JSPropertyNameIterator;
         friend class JSString;
@@ -44,21 +66,28 @@ namespace JSC {
         friend class JSAPIValueWrapper;
         friend class JSZombie;
         friend class JSGlobalData;
+        friend class MarkedSpace;
+        friend class MarkedBlock;
+        friend class ScopeChainNode;
+        friend class Structure;
+        friend class StructureChain;
+        friend class RegExp;
+        enum CreatingEarlyCellTag { CreatingEarlyCell };
+
+    protected:
+        enum VPtrStealingHackType { VPtrStealingHack };
 
     private:
-        explicit JSCell(Structure*);
+        explicit JSCell(VPtrStealingHackType) { }
+        JSCell(JSGlobalData&, Structure*);
+        JSCell(JSGlobalData&, Structure*, CreatingEarlyCellTag);
         virtual ~JSCell();
+        static const ClassInfo s_dummyCellInfo;
 
     public:
-        static PassRefPtr<Structure> createDummyStructure()
-        {
-            return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
-        }
+        static Structure* createDummyStructure(JSGlobalData&);
 
         // Querying the type.
-#if USE(JSVALUE32)
-        bool isNumber() const;
-#endif
         bool isString() const;
         bool isObject() const;
         virtual bool isGetterSetter() const;
@@ -87,20 +116,20 @@ namespace JSC {
         virtual bool toBoolean(ExecState*) const;
         virtual double toNumber(ExecState*) const;
         virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
+        virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         // Garbage collection.
         void* operator new(size_t, ExecState*);
         void* operator new(size_t, JSGlobalData*);
         void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; }
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 #if ENABLE(JSC_ZOMBIES)
         virtual bool isZombie() const { return false; }
 #endif
 
         // Object operations, with the toObject operation included.
-        virtual const ClassInfo* classInfo() const;
+        const ClassInfo* classInfo() const;
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
@@ -117,6 +146,15 @@ namespace JSC {
         // property names, we want a similar interface with appropriate optimizations.)
         bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
 
+        static ptrdiff_t structureOffset()
+        {
+            return OBJECT_OFFSETOF(JSCell, m_structure);
+        }
+
+#if ENABLE(GC_VALIDATION)
+        Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); }
+#endif
+        
     protected:
         static const unsigned AnonymousSlotCount = 0;
 
@@ -125,52 +163,40 @@ namespace JSC {
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
         
-        Structure* m_structure;
+        WriteBarrier<Structure> m_structure;
     };
 
-    inline JSCell::JSCell(Structure* structure)
-        : m_structure(structure)
-    {
-    }
-
-    inline JSCell::~JSCell()
+    inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure)
+        : m_structure(globalData, this, structure)
     {
+        ASSERT(m_structure);
     }
 
-#if USE(JSVALUE32)
-    inline bool JSCell::isNumber() const
+    inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag)
     {
-        return m_structure->typeInfo().type() == NumberType;
-    }
+#if ENABLE(GC_VALIDATION)
+        if (structure)
 #endif
-
-    inline bool JSCell::isObject() const
-    {
-        return m_structure->typeInfo().type() == ObjectType;
+            m_structure.setEarlyValue(globalData, this, structure);
+        // Very first set of allocations won't have a real structure.
+        ASSERT(m_structure || !globalData.dummyMarkableCellStructure);
     }
 
-    inline bool JSCell::isString() const
+    inline JSCell::~JSCell()
     {
-        return m_structure->typeInfo().type() == StringType;
+#if ENABLE(GC_VALIDATION)
+        m_structure.clear();
+#endif
     }
 
     inline Structure* JSCell::structure() const
     {
-        return m_structure;
+        return m_structure.get();
     }
 
-    inline void JSCell::markChildren(MarkStack&)
+    inline void JSCell::visitChildren(SlotVisitor& visitor)
     {
-    }
-
-    inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
-    {
-        return globalData->heap.allocate(size);
-    }
-
-    inline void* JSCell::operator new(size_t size, ExecState* exec)
-    {
-        return exec->heap()->allocate(size);
+        visitor.append(&m_structure);
     }
 
     // --- JSValue inlines ----------------------------
@@ -200,19 +226,28 @@ namespace JSC {
         return isCell() ? asCell()->getString(exec) : UString();
     }
 
+    template <typename Base> UString HandleConverter<Base, Unknown>::getString(ExecState* exec) const
+    {
+        return jsValue().getString(exec);
+    }
+
     inline JSObject* JSValue::getObject() const
     {
         return isCell() ? asCell()->getObject() : 0;
     }
 
-    inline CallType JSValue::getCallData(CallData& callData)
+    inline CallType getCallData(JSValue value, CallData& callData)
     {
-        return isCell() ? asCell()->getCallData(callData) : CallTypeNone;
+        CallType result = value.isCell() ? value.asCell()->getCallData(callData) : CallTypeNone;
+        ASSERT(result == CallTypeNone || value.isValidCallee());
+        return result;
     }
 
-    inline ConstructType JSValue::getConstructData(ConstructData& constructData)
+    inline ConstructType getConstructData(JSValue value, ConstructData& constructData)
     {
-        return isCell() ? asCell()->getConstructData(constructData) : ConstructTypeNone;
+        ConstructType result = value.isCell() ? value.asCell()->getConstructData(constructData) : ConstructTypeNone;
+        ASSERT(result == ConstructTypeNone || value.isValidCallee());
+        return result;
     }
 
     ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
@@ -230,14 +265,6 @@ namespace JSC {
         return false;
     }
 
-#if !USE(JSVALUE32_64)
-    ALWAYS_INLINE JSCell* JSValue::asCell() const
-    {
-        ASSERT(isCell());
-        return m_ptr;
-    }
-#endif // !USE(JSVALUE32_64)
-
     inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
     {
         return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
@@ -297,13 +324,6 @@ namespace JSC {
         return isUndefined() ? nonInlineNaN() : 0; // null and false both convert to 0.
     }
 
-    inline bool JSValue::needsThisConversion() const
-    {
-        if (UNLIKELY(!isCell()))
-            return true;
-        return asCell()->structure()->typeInfo().needsThisConversion();
-    }
-
     inline JSValue JSValue::getJSNumber()
     {
         if (isInt32() || isDouble())
@@ -315,30 +335,17 @@ namespace JSC {
 
     inline JSObject* JSValue::toObject(ExecState* exec) const
     {
-        return isCell() ? asCell()->toObject(exec) : toObjectSlowCase(exec);
+        return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
     }
 
-    inline JSObject* JSValue::toThisObject(ExecState* exec) const
+    inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
     {
-        return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
+        return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
     }
 
-    ALWAYS_INLINE void MarkStack::append(JSCell* cell)
-    {
-        ASSERT(!m_isCheckingForDefaultMarkViolation);
-        ASSERT(cell);
-        if (Heap::isCellMarked(cell))
-            return;
-        Heap::markCell(cell);
-        if (cell->structure()->typeInfo().type() >= CompoundType)
-            m_values.append(cell);
-    }
-
-    ALWAYS_INLINE void MarkStack::append(JSValue value)
+    inline JSObject* JSValue::toThisObject(ExecState* exec) const
     {
-        ASSERT(value);
-        if (value.isCell())
-            append(value.asCell());
+        return isCell() ? asCell()->toThisObject(exec) : toThisObjectSlowCase(exec);
     }
 
     inline Heap* Heap::heap(JSValue v)
@@ -350,15 +357,76 @@ namespace JSC {
 
     inline Heap* Heap::heap(JSCell* c)
     {
-        return cellBlock(c)->heap;
+        return MarkedSpace::heap(c);
     }
     
 #if ENABLE(JSC_ZOMBIES)
     inline bool JSValue::isZombie() const
     {
-        return isCell() && asCell() && asCell()->isZombie();
+        return isCell() && asCell() > (JSCell*)0x1ffffffffL && asCell()->isZombie();
     }
 #endif
+
+    inline void* MarkedBlock::allocate()
+    {
+        while (m_nextAtom < m_endAtom) {
+            if (!m_marks.testAndSet(m_nextAtom)) {
+                JSCell* cell = reinterpret_cast<JSCell*>(&atoms()[m_nextAtom]);
+                m_nextAtom += m_atomsPerCell;
+                cell->~JSCell();
+                return cell;
+            }
+            m_nextAtom += m_atomsPerCell;
+        }
+
+        return 0;
+    }
+    
+    inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes)
+    {
+        ASSERT(bytes && bytes < maxCellSize);
+        if (bytes < preciseCutoff)
+            return m_preciseSizeClasses[(bytes - 1) / preciseStep];
+        return m_impreciseSizeClasses[(bytes - 1) / impreciseStep];
+    }
+
+    inline void* MarkedSpace::allocate(size_t bytes)
+    {
+        SizeClass& sizeClass = sizeClassFor(bytes);
+        return allocateFromSizeClass(sizeClass);
+    }
+    
+    inline void* Heap::allocate(size_t bytes)
+    {
+        ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
+        ASSERT(JSLock::lockCount() > 0);
+        ASSERT(JSLock::currentThreadIsHoldingLock());
+        ASSERT(bytes <= MarkedSpace::maxCellSize);
+        ASSERT(m_operationInProgress == NoOperation);
+
+        m_operationInProgress = Allocation;
+        void* result = m_markedSpace.allocate(bytes);
+        m_operationInProgress = NoOperation;
+        if (result)
+            return result;
+
+        return allocateSlowCase(bytes);
+    }
+
+    inline void* JSCell::operator new(size_t size, JSGlobalData* globalData)
+    {
+        JSCell* result = static_cast<JSCell*>(globalData->heap.allocate(size));
+        result->m_structure.clear();
+        return result;
+    }
+
+    inline void* JSCell::operator new(size_t size, ExecState* exec)
+    {
+        JSCell* result = static_cast<JSCell*>(exec->heap()->allocate(size));
+        result->m_structure.clear();
+        return result;
+    }
+
 } // namespace JSC
 
 #endif // JSCell_h
diff --git a/runtime/JSChunk.cpp b/runtime/JSChunk.cpp
new file mode 100644 (file)
index 0000000..f064de8
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "JSChunk.h"
+
diff --git a/runtime/JSChunk.h b/runtime/JSChunk.h
new file mode 100644 (file)
index 0000000..bae2bc7
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 JSChunk_h
+#define JSChunk_h
+
+
+
+#endif // JSChunk_h
index 89c4dae9f0f4b206f5852bd2535c14b06bf6757e..e33d5d2561bf1f4f0d90d995f83a51c4169cd9bc 100644 (file)
 #include "CodeBlock.h"
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
+#include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
 #include "JSGlobalObject.h"
+#include "JSNotAnObject.h"
 #include "Interpreter.h"
 #include "ObjectPrototype.h"
 #include "Parser.h"
@@ -40,86 +42,107 @@ using namespace WTF;
 using namespace Unicode;
 
 namespace JSC {
+EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
+{
+    return throwVMError(exec, createNotAConstructorError(exec, exec->callee()));
+}
 
 ASSERT_CLASS_FITS_IN_CELL(JSFunction);
 
-const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };
+const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0 };
 
 bool JSFunction::isHostFunctionNonInline() const
 {
     return isHostFunction();
 }
 
-JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
-    : Base(structure)
-    , m_executable(adoptRef(new VPtrHackExecutable()))
+JSFunction::JSFunction(VPtrStealingHackType)
+    : Base(VPtrStealingHack)
 {
 }
 
-JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk, NativeFunction func)
-    : Base(&exec->globalData(), structure, name)
-#if ENABLE(JIT)
-    , m_executable(thunk)
-#endif
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeExecutable* thunk)
+    : Base(globalObject, structure)
+    , m_executable(exec->globalData(), this, thunk)
+    , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
 {
-#if ENABLE(JIT)
-    setNativeFunction(func);
-    putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
-#else
-    UNUSED_PARAM(thunk);
-    UNUSED_PARAM(length);
-    UNUSED_PARAM(func);
-    ASSERT_NOT_REACHED();
-#endif
+    ASSERT(inherits(&s_info));
+    putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
+    putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
 }
 
-JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
-    : Base(&exec->globalData(), structure, name)
-#if ENABLE(JIT)
-    , m_executable(exec->globalData().jitStubs->ctiNativeCallThunk())
-#endif
+JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, int length, const Identifier& name, NativeFunction func)
+    : Base(globalObject, structure)
+    , m_scopeChain(exec->globalData(), this, globalObject->globalScopeChain())
 {
-#if ENABLE(JIT)
-    setNativeFunction(func);
-    putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
-#else
-    UNUSED_PARAM(length);
-    UNUSED_PARAM(func);
-    ASSERT_NOT_REACHED();
-#endif
+    ASSERT(inherits(&s_info));
+    
+    // Can't do this during initialization because getHostFunction might do a GC allocation.
+    m_executable.set(exec->globalData(), this, exec->globalData().getHostFunction(func));
+    
+    putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
+    putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
 }
 
-JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
-    : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name())
-    , m_executable(executable)
+JSFunction::JSFunction(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChainNode)
+    : Base(scopeChainNode->globalObject.get(), scopeChainNode->globalObject->functionStructure())
+    , m_executable(exec->globalData(), this, executable)
+    , m_scopeChain(exec->globalData(), this, scopeChainNode)
 {
-    setScopeChain(scopeChainNode);
+    ASSERT(inherits(&s_info));
+    const Identifier& name = static_cast<FunctionExecutable*>(m_executable.get())->name();
+    putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
 }
 
 JSFunction::~JSFunction()
 {
     ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
+}
 
-    // JIT code for other functions may have had calls linked directly to the code for this function; these links
-    // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
-    // this memory is freed and may be reused (potentially for another, different JSFunction).
-    if (!isHostFunction()) {
-#if ENABLE(JIT_OPTIMIZE_CALL)
-        ASSERT(m_executable);
-        if (jsExecutable()->isGenerated())
-            jsExecutable()->generatedBytecode().unlinkCallers();
-#endif
-        scopeChain().~ScopeChain(); // FIXME: Don't we need to do this in the interpreter too?
-    }
+static const char* StrictModeCallerAccessError = "Cannot access caller property of a strict mode function";
+static const char* StrictModeArgumentsAccessError = "Cannot access arguments property of a strict mode function";
+
+static void createDescriptorForThrowingProperty(ExecState* exec, PropertyDescriptor& descriptor, const char* message)
+{
+    JSValue thrower = createTypeErrorFunction(exec, message);
+    descriptor.setAccessorDescriptor(thrower, thrower, DontEnum | DontDelete | Getter | Setter);
 }
 
-void JSFunction::markChildren(MarkStack& markStack)
+const UString& JSFunction::name(ExecState* exec)
 {
-    Base::markChildren(markStack);
-    if (!isHostFunction()) {
-        jsExecutable()->markAggregate(markStack);
-        scopeChain().markAggregate(markStack);
-    }
+    return asString(getDirect(exec->globalData(), exec->globalData().propertyNames->name))->tryGetValue();
+}
+
+const UString JSFunction::displayName(ExecState* exec)
+{
+    JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
+    
+    if (displayName && isJSString(&exec->globalData(), displayName))
+        return asString(displayName)->tryGetValue();
+    
+    return UString();
+}
+
+const UString JSFunction::calculatedDisplayName(ExecState* exec)
+{
+    const UString explicitName = displayName(exec);
+    
+    if (!explicitName.isEmpty())
+        return explicitName;
+    
+    return name(exec);
+}
+
+void JSFunction::visitChildren(SlotVisitor& visitor)
+{
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(visitor);
+
+    visitor.append(&m_scopeChain);
+    if (m_executable)
+        visitor.append(&m_executable);
 }
 
 CallType JSFunction::getCallData(CallData& callData)
@@ -129,16 +152,10 @@ CallType JSFunction::getCallData(CallData& callData)
         return CallTypeHost;
     }
     callData.js.functionExecutable = jsExecutable();
-    callData.js.scopeChain = scopeChain().node();
+    callData.js.scopeChain = scope();
     return CallTypeJS;
 }
 
-JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args)
-{
-    ASSERT(!isHostFunction());
-    return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot());
-}
-
 JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
 {
     JSFunction* thisObj = asFunction(slotBase);
@@ -153,11 +170,31 @@ JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identi
     return exec->interpreter()->retrieveCaller(exec, thisObj);
 }
 
-JSValue JSFunction::lengthGetter(ExecState* exec, JSValue slotBase, const Identifier&)
+JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
     JSFunction* thisObj = asFunction(slotBase);
     ASSERT(!thisObj->isHostFunction());
-    return jsNumber(exec, thisObj->jsExecutable()->parameterCount());
+    return jsNumber(thisObj->jsExecutable()->parameterCount());
+}
+
+static inline WriteBarrierBase<Unknown>* createPrototypeProperty(JSGlobalData& globalData, JSGlobalObject* globalObject, JSFunction* function)
+{
+    ASSERT(!function->isHostFunction());
+
+    ExecState* exec = globalObject->globalExec();
+    if (WriteBarrierBase<Unknown>* location = function->getDirectLocation(globalData, exec->propertyNames().prototype))
+        return location;
+    JSObject* prototype = constructEmptyObject(exec, globalObject->emptyObjectStructure());
+    prototype->putDirect(globalData, exec->propertyNames().constructor, function, DontEnum);
+    function->putDirect(globalData, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
+    return function->getDirectLocation(exec->globalData(), exec->propertyNames().prototype);
+}
+
+void JSFunction::preventExtensions(JSGlobalData& globalData)
+{
+    if (!isHostFunction())
+        createPrototypeProperty(globalData, scope()->globalObject.get(), this);
+    JSObject::preventExtensions(globalData);
 }
 
 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -166,19 +203,21 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
         return Base::getOwnPropertySlot(exec, propertyName, slot);
 
     if (propertyName == exec->propertyNames().prototype) {
-        JSValue* location = getDirectLocation(propertyName);
+        WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName);
 
-        if (!location) {
-            JSObject* prototype = new (exec) JSObject(scopeChain().globalObject()->emptyObjectStructure());
-            prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
-            putDirect(exec->propertyNames().prototype, prototype, DontDelete);
-            location = getDirectLocation(propertyName);
-        }
+        if (!location)
+            location = createPrototypeProperty(exec->globalData(), scope()->globalObject.get(), this);
 
-        slot.setValueSlot(this, location, offsetForLocation(location));
+        slot.setValue(this, location->get(), offsetForLocation(location));
     }
 
     if (propertyName == exec->propertyNames().arguments) {
+        if (jsExecutable()->isStrictMode()) {
+            throwTypeError(exec, "Can't access arguments object of a strict mode function");
+            slot.setValue(jsNull());
+            return true;
+        }
+   
         slot.setCacheableCustom(this, argumentsGetter);
         return true;
     }
@@ -189,6 +228,11 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
     }
 
     if (propertyName == exec->propertyNames().caller) {
+        if (jsExecutable()->isStrictMode()) {
+            throwTypeError(exec, StrictModeCallerAccessError);
+            slot.setValue(jsNull());
+            return true;
+        }
         slot.setCacheableCustom(this, callerGetter);
         return true;
     }
@@ -196,38 +240,48 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
     return Base::getOwnPropertySlot(exec, propertyName, slot);
 }
 
-    bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
-    {
-        if (isHostFunction())
-            return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
-        
-        if (propertyName == exec->propertyNames().prototype) {
-            PropertySlot slot;
-            getOwnPropertySlot(exec, propertyName, slot);
-            return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
-        }
-        
-        if (propertyName == exec->propertyNames().arguments) {
+bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    if (isHostFunction())
+        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    
+    if (propertyName == exec->propertyNames().prototype) {
+        PropertySlot slot;
+        getOwnPropertySlot(exec, propertyName, slot);
+        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    }
+    
+    if (propertyName == exec->propertyNames().arguments) {
+        if (jsExecutable()->isStrictMode())
+            createDescriptorForThrowingProperty(exec, descriptor, StrictModeArgumentsAccessError);
+        else
             descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
-            return true;
-        }
-        
-        if (propertyName == exec->propertyNames().length) {
-            descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
-            return true;
-        }
-        
-        if (propertyName == exec->propertyNames().caller) {
+        return true;
+    }
+    
+    if (propertyName == exec->propertyNames().length) {
+        descriptor.setDescriptor(jsNumber(jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
+        return true;
+    }
+    
+    if (propertyName == exec->propertyNames().caller) {
+        if (jsExecutable()->isStrictMode())
+            createDescriptorForThrowingProperty(exec, descriptor, StrictModeCallerAccessError);
+        else
             descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
-            return true;
-        }
-        
-        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        return true;
     }
     
+    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
 void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
     if (!isHostFunction() && (mode == IncludeDontEnumProperties)) {
+        // Make sure prototype has been reified.
+        PropertySlot slot;
+        getOwnPropertySlot(exec, exec->propertyNames().prototype, slot);
+
         propertyNames.add(exec->propertyNames().arguments);
         propertyNames.add(exec->propertyNames().callee);
         propertyNames.add(exec->propertyNames().caller);
@@ -242,6 +296,22 @@ void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue va
         Base::put(exec, propertyName, value, slot);
         return;
     }
+    if (propertyName == exec->propertyNames().prototype) {
+        // Make sure prototype has been reified, such that it can only be overwritten
+        // following the rules set out in ECMA-262 8.12.9.
+        PropertySlot slot;
+        getOwnPropertySlot(exec, propertyName, slot);
+    }
+    if (jsExecutable()->isStrictMode()) {
+        if (propertyName == exec->propertyNames().arguments) {
+            throwTypeError(exec, StrictModeArgumentsAccessError);
+            return;
+        }
+        if (propertyName == exec->propertyNames().caller) {
+            throwTypeError(exec, StrictModeCallerAccessError);
+            return;
+        }
+    }
     if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
         return;
     Base::put(exec, propertyName, value, slot);
@@ -262,25 +332,8 @@ ConstructType JSFunction::getConstructData(ConstructData& constructData)
     if (isHostFunction())
         return ConstructTypeNone;
     constructData.js.functionExecutable = jsExecutable();
-    constructData.js.scopeChain = scopeChain().node();
+    constructData.js.scopeChain = scope();
     return ConstructTypeJS;
 }
 
-JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)
-{
-    ASSERT(!isHostFunction());
-    Structure* structure;
-    JSValue prototype = get(exec, exec->propertyNames().prototype);
-    if (prototype.isObject())
-        structure = asObject(prototype)->inheritorID();
-    else
-        structure = exec->lexicalGlobalObject()->emptyObjectStructure();
-    JSObject* thisObj = new (exec) JSObject(structure);
-
-    JSValue result = exec->interpreter()->execute(jsExecutable(), exec, this, thisObj, args, scopeChain().node(), exec->exceptionSlot());
-    if (exec->hadException() || !result.isObject())
-        return thisObj;
-    return asObject(result);
-}
-
 } // namespace JSC
index 301b908117b550445a66c7e97422fea04b09de5b..42fd62a4d16c4b673a7fff64416f6539f2d08b4a 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef JSFunction_h
 #define JSFunction_h
 
-#include "InternalFunction.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
 
@@ -34,24 +34,36 @@ namespace JSC {
     class JSActivation;
     class JSGlobalObject;
     class NativeExecutable;
+    class VPtrHackExecutable;
 
-    class JSFunction : public InternalFunction {
+    EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*);
+
+    class JSFunction : public JSObjectWithGlobalObject {
         friend class JIT;
         friend class JSGlobalData;
 
-        typedef InternalFunction Base;
+        typedef JSObjectWithGlobalObject Base;
 
     public:
-        JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
-        JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*, NativeFunction);
-        JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*);
+        JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeFunction);
+        JSFunction(ExecState*, JSGlobalObject*, Structure*, int length, const Identifier&, NativeExecutable*);
+        JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*);
         virtual ~JSFunction();
 
-        JSObject* construct(ExecState*, const ArgList&);
-        JSValue call(ExecState*, JSValue thisValue, const ArgList&);
+        const UString& name(ExecState*);
+        const UString displayName(ExecState*);
+        const UString calculatedDisplayName(ExecState*);
 
-        void setScope(const ScopeChain& scopeChain) { setScopeChain(scopeChain); }
-        ScopeChain& scope() { return scopeChain(); }
+        ScopeChainNode* scope()
+        {
+            ASSERT(!isHostFunctionNonInline());
+            return m_scopeChain.get();
+        }
+        void setScope(JSGlobalData& globalData, ScopeChainNode* scopeChain)
+        {
+            ASSERT(!isHostFunctionNonInline());
+            m_scopeChain.set(globalData, this, scopeChain);
+        }
 
         ExecutableBase* executable() const { return m_executable.get(); }
 
@@ -59,76 +71,48 @@ namespace JSC {
         inline bool isHostFunction() const;
         FunctionExecutable* jsExecutable() const;
 
-        static JS_EXPORTDATA const ClassInfo info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
         { 
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
         }
 
-        NativeFunction nativeFunction()
-        {
-            return *WTF::bitwise_cast<NativeFunction*>(m_data);
-        }
+        NativeFunction nativeFunction();
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
     protected:
-        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | InternalFunction::StructureFlags;
+        const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
 
     private:
-        JSFunction(NonNullPassRefPtr<Structure>);
+        explicit JSFunction(VPtrStealingHackType);
 
         bool isHostFunctionNonInline() const;
 
+        virtual void preventExtensions(JSGlobalData&);
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
 
-        virtual void markChildren(MarkStack&);
-
-        virtual const ClassInfo* classInfo() const { return &info; }
+        virtual void visitChildren(SlotVisitor&);
 
         static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&);
         static JSValue callerGetter(ExecState*, JSValue, const Identifier&);
         static JSValue lengthGetter(ExecState*, JSValue, const Identifier&);
 
-        RefPtr<ExecutableBase> m_executable;
-        ScopeChain& scopeChain()
-        {
-            ASSERT(!isHostFunctionNonInline());
-            return *WTF::bitwise_cast<ScopeChain*>(m_data);
-        }
-        void clearScopeChain()
-        {
-            ASSERT(!isHostFunctionNonInline());
-            new (m_data) ScopeChain(NoScopeChain());
-        }
-        void setScopeChain(ScopeChainNode* sc)
-        {
-            ASSERT(!isHostFunctionNonInline());
-            new (m_data) ScopeChain(sc);
-        }
-        void setScopeChain(const ScopeChain& sc)
-        {
-            ASSERT(!isHostFunctionNonInline());
-            *WTF::bitwise_cast<ScopeChain*>(m_data) = sc;
-        }
-        void setNativeFunction(NativeFunction func)
-        {
-            *WTF::bitwise_cast<NativeFunction*>(m_data) = func;
-        }
-        unsigned char m_data[sizeof(void*)];
+        WriteBarrier<ExecutableBase> m_executable;
+        WriteBarrier<ScopeChainNode> m_scopeChain;
     };
 
     JSFunction* asFunction(JSValue);
 
     inline JSFunction* asFunction(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&JSFunction::info));
+        ASSERT(asObject(value)->inherits(&JSFunction::s_info));
         return static_cast<JSFunction*>(asObject(value));
     }
 
index 41b841e454a515f98559a93c2ded524a11ce2ec9..377e849154dce5a33032ae9638b4a6ffd310d25d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,9 +30,9 @@
 #include "JSGlobalData.h"
 
 #include "ArgList.h"
-#include "Collector.h"
-#include "CollectorHeapIterator.h"
+#include "Heap.h"
 #include "CommonIdentifiers.h"
+#include "DebuggerActivation.h"
 #include "FunctionConstructor.h"
 #include "GetterSetter.h"
 #include "Interpreter.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
+#include "JSZombie.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
 #include "Parser.h"
 #include "RegExpCache.h"
+#include "RegExpObject.h"
+#include "StrictEvalActivation.h"
 #include <wtf/WTFThreadData.h>
+#if ENABLE(REGEXP_TRACING)
+#include "RegExp.h"
+#endif
+
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
 
 using namespace WTF;
 
+namespace {
+
+using namespace JSC;
+
+class Recompiler {
+public:
+    void operator()(JSCell*);
+};
+
+inline void Recompiler::operator()(JSCell* cell)
+{
+    if (!cell->inherits(&JSFunction::s_info))
+        return;
+    JSFunction* function = asFunction(cell);
+    if (function->executable()->isHostFunction())
+        return;
+    function->jsExecutable()->discardCode();
+}
+
+} // namespace
+
 namespace JSC {
 
-extern JSC_CONST_HASHTABLE HashTable arrayTable;
+extern JSC_CONST_HASHTABLE HashTable arrayConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable arrayPrototypeTable;
+extern JSC_CONST_HASHTABLE HashTable booleanPrototypeTable;
 extern JSC_CONST_HASHTABLE HashTable jsonTable;
 extern JSC_CONST_HASHTABLE HashTable dateTable;
+extern JSC_CONST_HASHTABLE HashTable dateConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable errorPrototypeTable;
+extern JSC_CONST_HASHTABLE HashTable globalObjectTable;
 extern JSC_CONST_HASHTABLE HashTable mathTable;
-extern JSC_CONST_HASHTABLE HashTable numberTable;
+extern JSC_CONST_HASHTABLE HashTable numberConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable numberPrototypeTable;
+extern JSC_CONST_HASHTABLE HashTable objectConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable objectPrototypeTable;
 extern JSC_CONST_HASHTABLE HashTable regExpTable;
 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable regExpPrototypeTable;
 extern JSC_CONST_HASHTABLE HashTable stringTable;
+extern JSC_CONST_HASHTABLE HashTable stringConstructorTable;
 
 void* JSGlobalData::jsArrayVPtr;
 void* JSGlobalData::jsByteArrayVPtr;
 void* JSGlobalData::jsStringVPtr;
 void* JSGlobalData::jsFunctionVPtr;
 
+#if COMPILER(GCC)
+// Work around for gcc trying to coalesce our reads of the various cell vptrs
+#define CLOBBER_MEMORY() do { \
+    asm volatile ("" : : : "memory"); \
+} while (false)
+#else
+#define CLOBBER_MEMORY() do { } while (false)
+#endif
+
 void JSGlobalData::storeVPtrs()
 {
-    CollectorCell cell;
-    void* storage = &cell;
+    // Enough storage to fit a JSArray, JSByteArray, JSString, or JSFunction.
+    // COMPILE_ASSERTS below check that this is true.
+    char storage[64];
 
-    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
-    JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
+    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(storage), sizeof_JSArray_must_be_less_than_storage);
+    JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
+    CLOBBER_MEMORY();
     JSGlobalData::jsArrayVPtr = jsArray->vptr();
-    jsArray->~JSCell();
 
-    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
+    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(storage), sizeof_JSByteArray_must_be_less_than_storage);
     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
+    CLOBBER_MEMORY();
     JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
-    jsByteArray->~JSCell();
 
-    COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
+    COMPILE_ASSERT(sizeof(JSString) <= sizeof(storage), sizeof_JSString_must_be_less_than_storage);
     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
+    CLOBBER_MEMORY();
     JSGlobalData::jsStringVPtr = jsString->vptr();
-    jsString->~JSCell();
 
-    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
-    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
+    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(storage), sizeof_JSFunction_must_be_less_than_storage);
+    JSCell* jsFunction = new (storage) JSFunction(JSCell::VPtrStealingHack);
+    CLOBBER_MEMORY();
     JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
-    jsFunction->~JSCell();
 }
 
 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
     : globalDataType(globalDataType)
     , clientData(0)
-    , arrayTable(fastNew<HashTable>(JSC::arrayTable))
+    , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
+    , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
+    , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
     , dateTable(fastNew<HashTable>(JSC::dateTable))
+    , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable))
+    , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable))
+    , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable))
     , jsonTable(fastNew<HashTable>(JSC::jsonTable))
     , mathTable(fastNew<HashTable>(JSC::mathTable))
-    , numberTable(fastNew<HashTable>(JSC::numberTable))
+    , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
+    , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
+    , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
+    , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable))
     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
+    , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
     , stringTable(fastNew<HashTable>(JSC::stringTable))
-    , activationStructure(JSActivation::createStructure(jsNull()))
-    , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
-    , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull()))
-    , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
-    , stringStructure(JSString::createStructure(jsNull()))
-    , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
-    , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
-    , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
-    , getterSetterStructure(GetterSetter::createStructure(jsNull()))
-    , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
-    , dummyMarkableCellStructure(JSCell::createDummyStructure())
-#if USE(JSVALUE32)
-    , numberStructure(JSNumberCell::createStructure(jsNull()))
-#endif
+    , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
     , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
     , propertyNames(new CommonIdentifiers(this))
     , emptyList(new MarkedArgumentBuffer)
+#if ENABLE(ASSEMBLER)
+    , executableAllocator(*this)
+    , regexAllocator(*this)
+#endif
     , lexer(new Lexer(this))
     , parser(new Parser)
-    , interpreter(new Interpreter)
+    , interpreter(0)
     , heap(this)
-    , initializingLazyNumericCompareFunction(false)
-    , head(0)
+    , globalObjectCount(0)
     , dynamicGlobalObject(0)
-    , functionCodeBlockBeingReparsed(0)
-    , firstStringifierToMark(0)
-    , markStack(jsArrayVPtr)
     , cachedUTCOffset(NaN)
     , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
     , m_regExpCache(new RegExpCache(this))
+#if ENABLE(REGEXP_TRACING)
+    , m_rtTraceList(new RTTraceList())
+#endif
 #ifndef NDEBUG
     , exclusiveThread(0)
 #endif
 {
+    interpreter = new Interpreter(*this);
+    if (globalDataType == Default)
+        m_stack = wtfThreadData().stack();
+
+    // Need to be careful to keep everything consistent here
+    IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
+    JSLock lock(SilenceAssertionsOnly);
+    structureStructure.set(*this, Structure::createStructure(*this));
+    debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, jsNull()));
+    activationStructure.set(*this, JSActivation::createStructure(*this, jsNull()));
+    interruptedExecutionErrorStructure.set(*this, JSNonFinalObject::createStructure(*this, jsNull()));
+    terminatedExecutionErrorStructure.set(*this, JSNonFinalObject::createStructure(*this, jsNull()));
+    staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, jsNull()));
+    strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, jsNull()));
+    stringStructure.set(*this, JSString::createStructure(*this, jsNull()));
+    notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, jsNull()));
+    propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, jsNull()));
+    getterSetterStructure.set(*this, GetterSetter::createStructure(*this, jsNull()));
+    apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, jsNull()));
+    scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, jsNull()));
+    executableStructure.set(*this, ExecutableBase::createStructure(*this, jsNull()));
+    nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, jsNull()));
+    evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, jsNull()));
+    programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, jsNull()));
+    functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, jsNull()));
+    dummyMarkableCellStructure.set(*this, JSCell::createDummyStructure(*this));
+    regExpStructure.set(*this, RegExp::createStructure(*this, jsNull()));
+    structureChainStructure.set(*this, StructureChain::createStructure(*this, jsNull()));
+
+#if ENABLE(JSC_ZOMBIES)
+    zombieStructure.set(*this, JSZombie::createStructure(*this, jsNull()));
+#endif
+
+    wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);
+
 #if PLATFORM(MAC)
     startProfilerServerIfNeeded();
 #endif
 #if ENABLE(JIT) && ENABLE(INTERPRETER)
-#if PLATFORM(CF)
+#if USE(CF)
     CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
     CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
     if (canUseJIT) {
         m_canUseJIT = kCFBooleanTrue == canUseJIT;
         CFRelease(canUseJIT);
-    } else
-        m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
+    } else {
+      char* canUseJITString = getenv("JavaScriptCoreUseJIT");
+      m_canUseJIT = !canUseJITString || atoi(canUseJITString);
+    }
     CFRelease(canUseJITKey);
 #elif OS(UNIX)
-    m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
+    char* canUseJITString = getenv("JavaScriptCoreUseJIT");
+    m_canUseJIT = !canUseJITString || atoi(canUseJITString);
 #else
     m_canUseJIT = true;
 #endif
@@ -175,7 +260,36 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     if (m_canUseJIT)
         m_canUseJIT = executableAllocator.isValid();
 #endif
-    jitStubs.set(new JITThunks(this));
+    jitStubs = adoptPtr(new JITThunks(this));
+#endif
+}
+
+void JSGlobalData::clearBuiltinStructures()
+{
+    structureStructure.clear();
+    debuggerActivationStructure.clear();
+    activationStructure.clear();
+    interruptedExecutionErrorStructure.clear();
+    terminatedExecutionErrorStructure.clear();
+    staticScopeStructure.clear();
+    strictEvalActivationStructure.clear();
+    stringStructure.clear();
+    notAnObjectStructure.clear();
+    propertyNameIteratorStructure.clear();
+    getterSetterStructure.clear();
+    apiWrapperStructure.clear();
+    scopeChainNodeStructure.clear();
+    executableStructure.clear();
+    nativeExecutableStructure.clear();
+    evalExecutableStructure.clear();
+    programExecutableStructure.clear();
+    functionExecutableStructure.clear();
+    dummyMarkableCellStructure.clear();
+    regExpStructure.clear();
+    structureChainStructure.clear();
+
+#if ENABLE(JSC_ZOMBIES)
+    zombieStructure.clear();
 #endif
 }
 
@@ -189,23 +303,43 @@ JSGlobalData::~JSGlobalData()
     interpreter = 0;
 #endif
 
-    arrayTable->deleteTable();
+    arrayPrototypeTable->deleteTable();
+    arrayConstructorTable->deleteTable();
+    booleanPrototypeTable->deleteTable();
     dateTable->deleteTable();
+    dateConstructorTable->deleteTable();
+    errorPrototypeTable->deleteTable();
+    globalObjectTable->deleteTable();
     jsonTable->deleteTable();
     mathTable->deleteTable();
-    numberTable->deleteTable();
+    numberConstructorTable->deleteTable();
+    numberPrototypeTable->deleteTable();
+    objectConstructorTable->deleteTable();
+    objectPrototypeTable->deleteTable();
     regExpTable->deleteTable();
     regExpConstructorTable->deleteTable();
+    regExpPrototypeTable->deleteTable();
     stringTable->deleteTable();
+    stringConstructorTable->deleteTable();
 
-    fastDelete(const_cast<HashTable*>(arrayTable));
+    fastDelete(const_cast<HashTable*>(arrayConstructorTable));
+    fastDelete(const_cast<HashTable*>(arrayPrototypeTable));
+    fastDelete(const_cast<HashTable*>(booleanPrototypeTable));
     fastDelete(const_cast<HashTable*>(dateTable));
+    fastDelete(const_cast<HashTable*>(dateConstructorTable));
+    fastDelete(const_cast<HashTable*>(errorPrototypeTable));
+    fastDelete(const_cast<HashTable*>(globalObjectTable));
     fastDelete(const_cast<HashTable*>(jsonTable));
     fastDelete(const_cast<HashTable*>(mathTable));
-    fastDelete(const_cast<HashTable*>(numberTable));
+    fastDelete(const_cast<HashTable*>(numberConstructorTable));
+    fastDelete(const_cast<HashTable*>(numberPrototypeTable));
+    fastDelete(const_cast<HashTable*>(objectConstructorTable));
+    fastDelete(const_cast<HashTable*>(objectPrototypeTable));
     fastDelete(const_cast<HashTable*>(regExpTable));
     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
+    fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
     fastDelete(const_cast<HashTable*>(stringTable));
+    fastDelete(const_cast<HashTable*>(stringConstructorTable));
 
     delete parser;
     delete lexer;
@@ -220,6 +354,9 @@ JSGlobalData::~JSGlobalData()
 
     delete clientData;
     delete m_regExpCache;
+#if ENABLE(REGEXP_TRACING)
+    delete m_rtTraceList;
+#endif
 }
 
 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
@@ -234,10 +371,7 @@ PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
 
 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
 {
-    Structure::startIgnoringLeaks();
-    RefPtr<JSGlobalData> data = create(type);
-    Structure::stopIgnoringLeaks();
-    return data.release();
+    return create(type);
 }
 
 bool JSGlobalData::sharedInstanceExists()
@@ -249,7 +383,7 @@ JSGlobalData& JSGlobalData::sharedInstance()
 {
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
-        instance = new JSGlobalData(APIShared, ThreadStackTypeSmall);
+        instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef();
 #if ENABLE(JSC_MULTIPLE_THREADS)
         instance->makeUsableFromMultipleThreads();
 #endif
@@ -264,18 +398,21 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal()
     return sharedInstance;
 }
 
-// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc.
-const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
+#if ENABLE(JIT)
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
 {
-    if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
-        initializingLazyNumericCompareFunction = true;
-        RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
-        lazyNumericCompareFunction = function->bytecode(exec, exec->scopeChain()).instructions();
-        initializingLazyNumericCompareFunction = false;
-    }
-
-    return lazyNumericCompareFunction;
+    return jitStubs->hostFunctionStub(this, function);
+}
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
+{
+    return jitStubs->hostFunctionStub(this, function, generator);
 }
+#else
+NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function)
+{
+    return NativeExecutable::create(*this, function, callHostFunctionAsConstructor);
+}
+#endif
 
 JSGlobalData::ClientData::~ClientData()
 {
@@ -286,6 +423,7 @@ void JSGlobalData::resetDateCache()
     cachedUTCOffset = NaN;
     dstOffsetCache.reset();
     cachedDateString = UString();
+    cachedDateStringValue = NaN;
     dateInstanceCache.reset();
 }
 
@@ -309,16 +447,95 @@ void JSGlobalData::recompileAllJSFunctions()
     // If JavaScript is running, it's not safe to recompile, since we'll end
     // up throwing away code that is live on the stack.
     ASSERT(!dynamicGlobalObject);
+    
+    Recompiler recompiler;
+    heap.forEach(recompiler);
+}
+
+struct StackPreservingRecompiler {
+    HashSet<FunctionExecutable*> currentlyExecutingFunctions;
+    void operator()(JSCell* cell)
+    {
+        if (!cell->inherits(&FunctionExecutable::s_info))
+            return;
+        FunctionExecutable* executable = static_cast<FunctionExecutable*>(cell);
+        if (currentlyExecutingFunctions.contains(executable))
+            return;
+        executable->discardCode();
+    }
+};
 
-    LiveObjectIterator it = heap.primaryHeapBegin();
-    LiveObjectIterator heapEnd = heap.primaryHeapEnd();
-    for ( ; it != heapEnd; ++it) {
-        if ((*it)->inherits(&JSFunction::info)) {
-            JSFunction* function = asFunction(*it);
-            if (!function->executable()->isHostFunction())
-                function->jsExecutable()->recompile();
+void JSGlobalData::releaseExecutableMemory()
+{
+    if (dynamicGlobalObject) {
+        StackPreservingRecompiler recompiler;
+        HashSet<JSCell*> roots;
+        heap.getConservativeRegisterRoots(roots);
+        HashSet<JSCell*>::iterator end = roots.end();
+        for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
+            ScriptExecutable* executable = 0;
+            JSCell* cell = *ptr;
+            if (cell->inherits(&ScriptExecutable::s_info))
+                executable = static_cast<ScriptExecutable*>(*ptr);
+            else if (cell->inherits(&JSFunction::s_info)) {
+                JSFunction* function = asFunction(*ptr);
+                if (function->isHostFunction())
+                    continue;
+                executable = function->jsExecutable();
+            } else
+                continue;
+            ASSERT(executable->inherits(&ScriptExecutable::s_info));
+            executable->unlinkCalls();
+            if (executable->inherits(&FunctionExecutable::s_info))
+                recompiler.currentlyExecutingFunctions.add(static_cast<FunctionExecutable*>(executable));
+                
         }
+        heap.forEach(recompiler);
+    } else
+        recompileAllJSFunctions();
+
+    m_regExpCache->invalidateCode();
+    heap.collectAllGarbage();
+}
+
+#if ENABLE(ASSEMBLER)
+void releaseExecutableMemory(JSGlobalData& globalData)
+{
+    globalData.releaseExecutableMemory();
+}
+#endif
+
+#if ENABLE(REGEXP_TRACING)
+void JSGlobalData::addRegExpToTrace(RegExp* regExp)
+{
+    m_rtTraceList->add(regExp);
+}
+
+void JSGlobalData::dumpRegExpTrace()
+{
+    // The first RegExp object is ignored.  It is create by the RegExpPrototype ctor and not used.
+    RTTraceList::iterator iter = ++m_rtTraceList->begin();
+    
+    if (iter != m_rtTraceList->end()) {
+        printf("\nRegExp Tracing\n");
+        printf("                                                            match()    matches\n");
+        printf("Regular Expression                          JIT Address      calls      found\n");
+        printf("----------------------------------------+----------------+----------+----------\n");
+    
+        unsigned reCount = 0;
+    
+        for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
+            (*iter)->printTraceData();
+
+        printf("%d Regular Expressions\n", reCount);
     }
+    
+    m_rtTraceList->clear();
+}
+#else
+void JSGlobalData::dumpRegExpTrace()
+{
 }
+#endif
 
 } // namespace JSC
index 6ccbf2c5a9872195cf3afc574653c432638ced10..fee7818396599a19173d912bc1885ed9adeaf240 100644 (file)
 #define JSGlobalData_h
 
 #include "CachedTranscendentalFunction.h"
-#include "Collector.h"
+#include "Heap.h"
 #include "DateInstanceCache.h"
 #include "ExecutableAllocator.h"
+#include "Strong.h"
 #include "JITStubs.h"
 #include "JSValue.h"
-#include "MarkStack.h"
 #include "NumericStrings.h"
 #include "SmallStrings.h"
 #include "Terminator.h"
 #include "TimeoutChecker.h"
 #include "WeakRandom.h"
+#include <wtf/BumpPointerAllocator.h>
 #include <wtf/Forward.h>
 #include <wtf/HashMap.h>
 #include <wtf/RefCounted.h>
+#include <wtf/ThreadSpecific.h>
+#include <wtf/WTFThreadData.h>
+#if ENABLE(REGEXP_TRACING)
+#include <wtf/ListHashSet.h>
+#endif
 
 struct OpaqueJSClass;
 struct OpaqueJSClassContextData;
@@ -52,19 +58,24 @@ namespace JSC {
 
     class CodeBlock;
     class CommonIdentifiers;
+    class HandleStack;
     class IdentifierTable;
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
     class Lexer;
+    class NativeExecutable;
     class Parser;
     class RegExpCache;
     class Stringifier;
     class Structure;
     class UString;
+#if ENABLE(REGEXP_TRACING)
+    class RegExp;
+#endif
 
     struct HashTable;
-    struct Instruction;    
+    struct Instruction;
 
     struct DSTOffsetCache {
         DSTOffsetCache()
@@ -108,6 +119,7 @@ namespace JSC {
         };
 
         bool isSharedInstance() { return globalDataType == APIShared; }
+        bool usingAPI() { return globalDataType != Default; }
         static bool sharedInstanceExists();
         static JSGlobalData& sharedInstance();
 
@@ -118,35 +130,55 @@ namespace JSC {
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
         // Will start tracking threads that use the heap, which is resource-heavy.
-        void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); }
+        void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
 #endif
 
         GlobalDataType globalDataType;
         ClientData* clientData;
 
-        const HashTable* arrayTable;
+        const HashTable* arrayConstructorTable;
+        const HashTable* arrayPrototypeTable;
+        const HashTable* booleanPrototypeTable;
         const HashTable* dateTable;
+        const HashTable* dateConstructorTable;
+        const HashTable* errorPrototypeTable;
+        const HashTable* globalObjectTable;
         const HashTable* jsonTable;
         const HashTable* mathTable;
-        const HashTable* numberTable;
+        const HashTable* numberConstructorTable;
+        const HashTable* numberPrototypeTable;
+        const HashTable* objectConstructorTable;
+        const HashTable* objectPrototypeTable;
         const HashTable* regExpTable;
         const HashTable* regExpConstructorTable;
+        const HashTable* regExpPrototypeTable;
         const HashTable* stringTable;
+        const HashTable* stringConstructorTable;
         
-        RefPtr<Structure> activationStructure;
-        RefPtr<Structure> interruptedExecutionErrorStructure;
-        RefPtr<Structure> terminatedExecutionErrorStructure;
-        RefPtr<Structure> staticScopeStructure;
-        RefPtr<Structure> stringStructure;
-        RefPtr<Structure> notAnObjectErrorStubStructure;
-        RefPtr<Structure> notAnObjectStructure;
-        RefPtr<Structure> propertyNameIteratorStructure;
-        RefPtr<Structure> getterSetterStructure;
-        RefPtr<Structure> apiWrapperStructure;
-        RefPtr<Structure> dummyMarkableCellStructure;
-
-#if USE(JSVALUE32)
-        RefPtr<Structure> numberStructure;
+        Strong<Structure> structureStructure;
+        Strong<Structure> debuggerActivationStructure;
+        Strong<Structure> activationStructure;
+        Strong<Structure> interruptedExecutionErrorStructure;
+        Strong<Structure> terminatedExecutionErrorStructure;
+        Strong<Structure> staticScopeStructure;
+        Strong<Structure> strictEvalActivationStructure;
+        Strong<Structure> stringStructure;
+        Strong<Structure> notAnObjectStructure;
+        Strong<Structure> propertyNameIteratorStructure;
+        Strong<Structure> getterSetterStructure;
+        Strong<Structure> apiWrapperStructure;
+        Strong<Structure> scopeChainNodeStructure;
+        Strong<Structure> executableStructure;
+        Strong<Structure> nativeExecutableStructure;
+        Strong<Structure> evalExecutableStructure;
+        Strong<Structure> programExecutableStructure;
+        Strong<Structure> functionExecutableStructure;
+        Strong<Structure> dummyMarkableCellStructure;
+        Strong<Structure> regExpStructure;
+        Strong<Structure> structureChainStructure;
+
+#if ENABLE(JSC_ZOMBIES)
+        Strong<Structure> zombieStructure;
 #endif
 
         static void storeVPtrs();
@@ -167,23 +199,32 @@ namespace JSC {
         ExecutableAllocator regexAllocator;
 #endif
 
-#if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
-        bool canUseJIT() { return m_canUseJIT; }
-#endif
+#if !ENABLE(JIT)
+        bool canUseJIT() { return false; } // interpreter only
+#elif !ENABLE(INTERPRETER)
+        bool canUseJIT() { return true; } // jit only
 #else
-        bool canUseJIT() { return false; }
+        bool canUseJIT() { return m_canUseJIT; }
 #endif
+
+        const StackBounds& stack()
+        {
+            return wtfThreadData().stack();
+        }
+
         Lexer* lexer;
         Parser* parser;
         Interpreter* interpreter;
 #if ENABLE(JIT)
         OwnPtr<JITThunks> jitStubs;
-        NativeExecutable* getThunk(ThunkGenerator generator)
+        MacroAssemblerCodePtr getCTIStub(ThunkGenerator generator)
         {
-            return jitStubs->specializedThunk(this, generator);
+            return jitStubs->ctiStub(this, generator);
         }
+        NativeExecutable* getHostFunction(NativeFunction, ThunkGenerator);
 #endif
+        NativeExecutable* getHostFunction(NativeFunction);
+
         TimeoutChecker timeoutChecker;
         Terminator terminator;
         Heap heap;
@@ -193,21 +234,12 @@ namespace JSC {
         ReturnAddressPtr exceptionLocation;
 #endif
 
-        const Vector<Instruction>& numericCompareFunction(ExecState*);
-        Vector<Instruction> lazyNumericCompareFunction;
-        bool initializingLazyNumericCompareFunction;
-
         HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
 
-        JSGlobalObject* head;
+        unsigned globalObjectCount;
         JSGlobalObject* dynamicGlobalObject;
 
-        HashSet<JSObject*> arrayVisitedElements;
-
-        CodeBlock* functionCodeBlockBeingReparsed;
-        Stringifier* firstStringifierToMark;
-
-        MarkStack markStack;
+        HashSet<JSObject*> stringRecursionCheckVisitedObjects;
 
         double cachedUTCOffset;
         DSTOffsetCache dstOffsetCache;
@@ -218,6 +250,12 @@ namespace JSC {
         int maxReentryDepth;
 
         RegExpCache* m_regExpCache;
+        BumpPointerAllocator m_regExpAllocator;
+
+#if ENABLE(REGEXP_TRACING)
+        typedef ListHashSet<RefPtr<RegExp> > RTTraceList;
+        RTTraceList* m_rtTraceList;
+#endif
 
 #ifndef NDEBUG
         ThreadIdentifier exclusiveThread;
@@ -232,6 +270,17 @@ namespace JSC {
         void dumpSampleData(ExecState* exec);
         void recompileAllJSFunctions();
         RegExpCache* regExpCache() { return m_regExpCache; }
+#if ENABLE(REGEXP_TRACING)
+        void addRegExpToTrace(PassRefPtr<RegExp> regExp);
+#endif
+        void dumpRegExpTrace();
+        HandleSlot allocateGlobalHandle() { return heap.allocateGlobalHandle(); }
+        HandleSlot allocateLocalHandle() { return heap.allocateLocalHandle(); }
+        void clearBuiltinStructures();
+
+        bool isCollectorBusy() { return heap.isBusy(); }
+        void releaseExecutableMemory();
+
     private:
         JSGlobalData(GlobalDataType, ThreadStackType);
         static JSGlobalData*& sharedInstanceInternal();
@@ -239,8 +288,14 @@ namespace JSC {
 #if ENABLE(JIT) && ENABLE(INTERPRETER)
         bool m_canUseJIT;
 #endif
+        StackBounds m_stack;
     };
 
+    inline HandleSlot allocateGlobalHandle(JSGlobalData& globalData)
+    {
+        return globalData.allocateGlobalHandle();
+    }
+
 } // namespace JSC
 
 #endif // JSGlobalData_h
index 93ded4c7d9afb0d663b593630ecb0c1cc06d644b..a71624f33c468a2c2e5c0d1864085aa1069ffe77 100644 (file)
 #include "ErrorPrototype.h"
 #include "FunctionConstructor.h"
 #include "FunctionPrototype.h"
-#include "GlobalEvalFunction.h"
 #include "JSFunction.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSLock.h"
 #include "JSONObject.h"
 #include "Interpreter.h"
+#include "Lookup.h"
 #include "MathObject.h"
 #include "NativeErrorConstructor.h"
 #include "NativeErrorPrototype.h"
@@ -60,7 +60,6 @@
 #include "ObjectConstructor.h"
 #include "ObjectPrototype.h"
 #include "Profiler.h"
-#include "PrototypeFunction.h"
 #include "RegExpConstructor.h"
 #include "RegExpMatchesArray.h"
 #include "RegExpObject.h"
 #include "StringPrototype.h"
 #include "Debugger.h"
 
+#include "JSGlobalObject.lut.h"
+
 namespace JSC {
 
+const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable };
+
+/* Source for JSGlobalObject.lut.h
+@begin globalObjectTable
+  parseInt              globalFuncParseInt              DontEnum|Function 2
+  parseFloat            globalFuncParseFloat            DontEnum|Function 1
+  isNaN                 globalFuncIsNaN                 DontEnum|Function 1
+  isFinite              globalFuncIsFinite              DontEnum|Function 1
+  escape                globalFuncEscape                DontEnum|Function 1
+  unescape              globalFuncUnescape              DontEnum|Function 1
+  decodeURI             globalFuncDecodeURI             DontEnum|Function 1
+  decodeURIComponent    globalFuncDecodeURIComponent    DontEnum|Function 1
+  encodeURI             globalFuncEncodeURI             DontEnum|Function 1
+  encodeURIComponent    globalFuncEncodeURIComponent    DontEnum|Function 1
+@end
+*/
+
 ASSERT_CLASS_FITS_IN_CELL(JSGlobalObject);
 
 // Default number of ticks before a timeout check should be done.
@@ -80,71 +98,39 @@ static const int initialTickCountThreshold = 255;
 // Preferred number of milliseconds between each timeout check
 static const int preferredScriptCheckTimeInterval = 1000;
 
-static inline void markIfNeeded(MarkStack& markStack, JSValue v)
+template <typename T> static inline void visitIfNeeded(SlotVisitor& visitor, WriteBarrier<T>* v)
 {
-    if (v)
-        markStack.append(v);
-}
-
-static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s)
-{
-    if (s)
-        markIfNeeded(markStack, s->storedPrototype());
+    if (*v)
+        visitor.append(v);
 }
 
 JSGlobalObject::~JSGlobalObject()
 {
     ASSERT(JSLock::currentThreadIsHoldingLock());
 
-    if (d()->debugger)
-        d()->debugger->detach(this);
+    if (m_debugger)
+        m_debugger->detach(this);
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (UNLIKELY(*profiler != 0)) {
-        (*profiler)->stopProfiling(globalExec(), UString());
+        (*profiler)->stopProfiling(this);
     }
-
-    d()->next->d()->prev = d()->prev;
-    d()->prev->d()->next = d()->next;
-    JSGlobalObject*& headObject = head();
-    if (headObject == this)
-        headObject = d()->next;
-    if (headObject == this)
-        headObject = 0;
-
-    HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
-    for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
-        (*it)->clearGlobalObject();
-        
-    RegisterFile& registerFile = globalData()->interpreter->registerFile();
-    if (registerFile.clearGlobalObject(this))
-        registerFile.setNumGlobals(0);
-    d()->destructor(d());
 }
 
 void JSGlobalObject::init(JSObject* thisValue)
 {
     ASSERT(JSLock::currentThreadIsHoldingLock());
-
+    
     structure()->disableSpecificFunctionTracking();
 
-    d()->globalData = Heap::heap(this)->globalData();
-    d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue);
-
-    JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0);
+    m_globalData = Heap::heap(this)->globalData();
+    m_globalScopeChain.set(*m_globalData, this, new (m_globalData.get()) ScopeChainNode(0, this, m_globalData.get(), this, thisValue));
 
-    if (JSGlobalObject*& headObject = head()) {
-        d()->prev = headObject;
-        d()->next = headObject->d()->next;
-        headObject->d()->next->d()->prev = this;
-        headObject->d()->next = this;
-    } else
-        headObject = d()->next = d()->prev = this;
+    JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0);
 
-    d()->recursion = 0;
-    d()->debugger = 0;
+    m_debugger = 0;
 
-    d()->profileGroup = 0;
+    m_profileGroup = 0;
 
     reset(prototype());
 }
@@ -153,7 +139,7 @@ void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValu
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (symbolTablePut(propertyName, value))
+    if (symbolTablePut(exec->globalData(), propertyName, value))
         return;
     JSVariableObject::put(exec, propertyName, value, slot);
 }
@@ -162,14 +148,14 @@ void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& proper
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (symbolTablePutWithAttributes(propertyName, value, attributes))
+    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
 
-    JSValue valueBefore = getDirect(propertyName);
+    JSValue valueBefore = getDirect(exec->globalData(), propertyName);
     PutPropertySlot slot;
     JSVariableObject::put(exec, propertyName, value, slot);
     if (!valueBefore) {
-        JSValue valueAfter = getDirect(propertyName);
+        JSValue valueAfter = getDirect(exec->globalData(), propertyName);
         if (valueAfter)
             JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
     }
@@ -201,214 +187,190 @@ void JSGlobalObject::reset(JSValue prototype)
 {
     ExecState* exec = JSGlobalObject::globalExec();
 
-    // Prototypes
-
-    d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructure(jsNull())); // The real prototype will be set once ObjectPrototype is created.
-    d()->prototypeFunctionStructure = PrototypeFunction::createStructure(d()->functionPrototype);
-    NativeFunctionWrapper* callFunction = 0;
-    NativeFunctionWrapper* applyFunction = 0;
-    d()->functionPrototype->addFunctionProperties(exec, d()->prototypeFunctionStructure.get(), &callFunction, &applyFunction);
-    d()->callFunction = callFunction;
-    d()->applyFunction = applyFunction;
-    d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(jsNull()), d()->prototypeFunctionStructure.get());
-    d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype);
+    m_functionPrototype.set(exec->globalData(), this, new (exec) FunctionPrototype(exec, this, FunctionPrototype::createStructure(exec->globalData(), jsNull()))); // The real prototype will be set once ObjectPrototype is created.
+    m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), m_functionPrototype.get()));
+    m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), m_functionPrototype.get()));
+    JSFunction* callFunction = 0;
+    JSFunction* applyFunction = 0;
+    m_functionPrototype->addFunctionProperties(exec, this, m_functionStructure.get(), &callFunction, &applyFunction);
+    m_callFunction.set(exec->globalData(), this, callFunction);
+    m_applyFunction.set(exec->globalData(), this, applyFunction);
+    m_objectPrototype.set(exec->globalData(), this, new (exec) ObjectPrototype(exec, this, ObjectPrototype::createStructure(exec->globalData(), jsNull())));
+    m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get());
 
-    d()->emptyObjectStructure = d()->objectPrototype->inheritorID();
+    m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData()));
+    m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), jsNull()));
 
-    d()->functionStructure = JSFunction::createStructure(d()->functionPrototype);
-    d()->callbackFunctionStructure = JSCallbackFunction::createStructure(d()->functionPrototype);
-    d()->argumentsStructure = Arguments::createStructure(d()->objectPrototype);
-    d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(d()->objectPrototype);
-    d()->callbackObjectStructure = JSCallbackObject<JSObject>::createStructure(d()->objectPrototype);
+    m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), m_functionPrototype.get()));
+    m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), m_objectPrototype.get()));
+    m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), m_objectPrototype.get()));
+    m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSObjectWithGlobalObject>::createStructure(exec->globalData(), m_objectPrototype.get()));
 
-    d()->arrayPrototype = new (exec) ArrayPrototype(ArrayPrototype::createStructure(d()->objectPrototype));
-    d()->arrayStructure = JSArray::createStructure(d()->arrayPrototype);
-    d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(d()->arrayPrototype);
+    m_arrayPrototype.set(exec->globalData(), this, new (exec) ArrayPrototype(this, ArrayPrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+    m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), m_arrayPrototype.get()));
+    m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), m_arrayPrototype.get()));
 
-    d()->stringPrototype = new (exec) StringPrototype(exec, StringPrototype::createStructure(d()->objectPrototype));
-    d()->stringObjectStructure = StringObject::createStructure(d()->stringPrototype);
+    m_stringPrototype.set(exec->globalData(), this, new (exec) StringPrototype(exec, this, StringPrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+    m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), m_stringPrototype.get()));
 
-    d()->booleanPrototype = new (exec) BooleanPrototype(exec, BooleanPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
-    d()->booleanObjectStructure = BooleanObject::createStructure(d()->booleanPrototype);
+    m_booleanPrototype.set(exec->globalData(), this, new (exec) BooleanPrototype(exec, this, BooleanPrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+    m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), m_booleanPrototype.get()));
 
-    d()->numberPrototype = new (exec) NumberPrototype(exec, NumberPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
-    d()->numberObjectStructure = NumberObject::createStructure(d()->numberPrototype);
+    m_numberPrototype.set(exec->globalData(), this, new (exec) NumberPrototype(exec, this, NumberPrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+    m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), m_numberPrototype.get()));
 
-    d()->datePrototype = new (exec) DatePrototype(exec, DatePrototype::createStructure(d()->objectPrototype));
-    d()->dateStructure = DateInstance::createStructure(d()->datePrototype);
+    m_datePrototype.set(exec->globalData(), this, new (exec) DatePrototype(exec, this, DatePrototype::createStructure(exec->globalData(), m_objectPrototype.get())));
+    m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), m_datePrototype.get()));
 
-    d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
-    d()->regExpStructure = RegExpObject::createStructure(d()->regExpPrototype);
+    RegExp* emptyRegex = RegExp::create(&exec->globalData(), "", NoFlags);
+    
+    m_regExpPrototype.set(exec->globalData(), this, new (exec) RegExpPrototype(exec, this, RegExpPrototype::createStructure(exec->globalData(), m_objectPrototype.get()), emptyRegex));
+    m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), m_regExpPrototype.get()));
 
-    d()->methodCallDummy = constructEmptyObject(exec);
+    m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec));
 
-    ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(d()->objectPrototype), d()->prototypeFunctionStructure.get());
-    d()->errorStructure = ErrorInstance::createStructure(errorPrototype);
+    ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, this, ErrorPrototype::createStructure(exec->globalData(), m_objectPrototype.get()));
+    m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), errorPrototype));
 
     // Constructors
 
-    JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(d()->functionPrototype), d()->objectPrototype, d()->prototypeFunctionStructure.get());
-    JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(d()->functionPrototype), d()->functionPrototype);
-    JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(d()->functionPrototype), d()->arrayPrototype, d()->prototypeFunctionStructure.get());
-    JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype);
-    JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(d()->functionPrototype), d()->booleanPrototype);
-    JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(d()->functionPrototype), d()->numberPrototype);
-    JSCell* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype);
-
-    d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(d()->functionPrototype), d()->regExpPrototype);
-
-    d()->errorConstructor = new (exec) ErrorConstructor(exec, ErrorConstructor::createStructure(d()->functionPrototype), errorPrototype);
-
-    RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(errorPrototype);
-    RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(d()->functionPrototype);
-
-    d()->evalErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError");
-    d()->rangeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError");
-    d()->referenceErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError");
-    d()->syntaxErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError");
-    d()->typeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError");
-    d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError");
-
-    d()->objectPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, objectConstructor, DontEnum);
-    d()->functionPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, functionConstructor, DontEnum);
-    d()->arrayPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, arrayConstructor, DontEnum);
-    d()->booleanPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, booleanConstructor, DontEnum);
-    d()->stringPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, stringConstructor, DontEnum);
-    d()->numberPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, numberConstructor, DontEnum);
-    d()->datePrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, dateConstructor, DontEnum);
-    d()->regExpPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum);
-    errorPrototype->putDirectFunctionWithoutTransition(exec->propertyNames().constructor, d()->errorConstructor, DontEnum);
-
-    // Set global constructors
-
-    // FIXME: These properties could be handled by a static hash table.
-
-    putDirectFunctionWithoutTransition(Identifier(exec, "Object"), objectConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "Function"), functionConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "Array"), arrayConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "String"), stringConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "Number"), numberConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "Date"), dateConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "RegExp"), d()->regExpConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "Error"), d()->errorConstructor, DontEnum);
-    putDirectFunctionWithoutTransition(Identifier(exec, "EvalError"), d()->evalErrorConstructor);
-    putDirectFunctionWithoutTransition(Identifier(exec, "RangeError"), d()->rangeErrorConstructor);
-    putDirectFunctionWithoutTransition(Identifier(exec, "ReferenceError"), d()->referenceErrorConstructor);
-    putDirectFunctionWithoutTransition(Identifier(exec, "SyntaxError"), d()->syntaxErrorConstructor);
-    putDirectFunctionWithoutTransition(Identifier(exec, "TypeError"), d()->typeErrorConstructor);
-    putDirectFunctionWithoutTransition(Identifier(exec, "URIError"), d()->URIErrorConstructor);
-
-    // Set global values.
+    JSCell* objectConstructor = new (exec) ObjectConstructor(exec, this, ObjectConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_objectPrototype.get());
+    JSCell* functionConstructor = new (exec) FunctionConstructor(exec, this, FunctionConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_functionPrototype.get());
+    JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, this, ArrayConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_arrayPrototype.get());
+    JSCell* stringConstructor = new (exec) StringConstructor(exec, this, StringConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_stringPrototype.get());
+    JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, this, BooleanConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_booleanPrototype.get());
+    JSCell* numberConstructor = new (exec) NumberConstructor(exec, this, NumberConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_numberPrototype.get());
+    JSCell* dateConstructor = new (exec) DateConstructor(exec, this, DateConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_datePrototype.get());
+
+    m_regExpConstructor.set(exec->globalData(), this, new (exec) RegExpConstructor(exec, this, RegExpConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), m_regExpPrototype.get()));
+
+    m_errorConstructor.set(exec->globalData(), this, new (exec) ErrorConstructor(exec, this, ErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get()), errorPrototype));
+
+    Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), errorPrototype);
+    Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), m_functionPrototype.get());
+    m_evalErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError"));
+    m_rangeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError"));
+    m_referenceErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError"));
+    m_syntaxErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError"));
+    m_typeErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError"));
+    m_URIErrorConstructor.set(exec->globalData(), this, new (exec) NativeErrorConstructor(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError"));
+
+    m_objectPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum);
+    m_functionPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum);
+    m_arrayPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum);
+    m_booleanPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum);
+    m_stringPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum);
+    m_numberPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum);
+    m_datePrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum);
+    m_regExpPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum);
+    errorPrototype->putDirectFunctionWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum);
+
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum);
+
+    m_evalFunction.set(exec->globalData(), this, new (exec) JSFunction(exec, this, m_functionStructure.get(), 1, exec->propertyNames().eval, globalFuncEval));
+    putDirectFunctionWithoutTransition(exec, m_evalFunction.get(), DontEnum);
+
     GlobalPropertyInfo staticGlobals[] = {
-        GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, MathObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete),
-        GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(exec), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(exec, Inf), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, this, MathObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete),
+        GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly),
+        GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(Inf), DontEnum | DontDelete | ReadOnly),
         GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly),
-        GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(JSONObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete)
+        GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(this, JSONObject::createStructure(exec->globalData(), m_objectPrototype.get())), DontEnum | DontDelete)
     };
+    addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
 
-    addStaticGlobals(staticGlobals, sizeof(staticGlobals) / sizeof(GlobalPropertyInfo));
-
-    // Set global functions.
-
-    d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructure(d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this);
-    putDirectFunctionWithoutTransition(exec, d()->evalFunction, DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt"), globalFuncParseInt), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat"), globalFuncParseFloat), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN"), globalFuncIsNaN), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite"), globalFuncIsFinite), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape"), globalFuncEscape), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape"), globalFuncUnescape), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI"), globalFuncDecodeURI), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent"), globalFuncDecodeURIComponent), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI"), globalFuncEncodeURI), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent"), globalFuncEncodeURIComponent), DontEnum);
-#ifndef NDEBUG
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint"), globalFuncJSCPrint), DontEnum);
-#endif
-
-    resetPrototype(prototype);
+    resetPrototype(exec->globalData(), prototype);
 }
 
 // Set prototype, and also insert the object prototype at the end of the chain.
-void JSGlobalObject::resetPrototype(JSValue prototype)
+void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype)
 {
-    setPrototype(prototype);
+    setPrototype(globalData, prototype);
 
     JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this);
-    JSObject* objectPrototype = d()->objectPrototype;
+    JSObject* objectPrototype = m_objectPrototype.get();
     if (oldLastInPrototypeChain != objectPrototype)
-        oldLastInPrototypeChain->setPrototype(objectPrototype);
+        oldLastInPrototypeChain->setPrototype(globalData, objectPrototype);
 }
 
-void JSGlobalObject::markChildren(MarkStack& markStack)
+void JSGlobalObject::visitChildren(SlotVisitor& visitor)
 {
-    JSVariableObject::markChildren(markStack);
-    
-    HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end();
-    for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it)
-        (*it)->markAggregate(markStack);
-
-    RegisterFile& registerFile = globalData()->interpreter->registerFile();
-    if (registerFile.globalObject() == this)
-        registerFile.markGlobals(markStack, &globalData()->heap);
-
-    markIfNeeded(markStack, d()->regExpConstructor);
-    markIfNeeded(markStack, d()->errorConstructor);
-    markIfNeeded(markStack, d()->evalErrorConstructor);
-    markIfNeeded(markStack, d()->rangeErrorConstructor);
-    markIfNeeded(markStack, d()->referenceErrorConstructor);
-    markIfNeeded(markStack, d()->syntaxErrorConstructor);
-    markIfNeeded(markStack, d()->typeErrorConstructor);
-    markIfNeeded(markStack, d()->URIErrorConstructor);
-
-    markIfNeeded(markStack, d()->evalFunction);
-    markIfNeeded(markStack, d()->callFunction);
-    markIfNeeded(markStack, d()->applyFunction);
-
-    markIfNeeded(markStack, d()->objectPrototype);
-    markIfNeeded(markStack, d()->functionPrototype);
-    markIfNeeded(markStack, d()->arrayPrototype);
-    markIfNeeded(markStack, d()->booleanPrototype);
-    markIfNeeded(markStack, d()->stringPrototype);
-    markIfNeeded(markStack, d()->numberPrototype);
-    markIfNeeded(markStack, d()->datePrototype);
-    markIfNeeded(markStack, d()->regExpPrototype);
-
-    markIfNeeded(markStack, d()->methodCallDummy);
-
-    markIfNeeded(markStack, d()->errorStructure);
-    markIfNeeded(markStack, d()->argumentsStructure);
-    markIfNeeded(markStack, d()->arrayStructure);
-    markIfNeeded(markStack, d()->booleanObjectStructure);
-    markIfNeeded(markStack, d()->callbackConstructorStructure);
-    markIfNeeded(markStack, d()->callbackFunctionStructure);
-    markIfNeeded(markStack, d()->callbackObjectStructure);
-    markIfNeeded(markStack, d()->dateStructure);
-    markIfNeeded(markStack, d()->emptyObjectStructure);
-    markIfNeeded(markStack, d()->errorStructure);
-    markIfNeeded(markStack, d()->functionStructure);
-    markIfNeeded(markStack, d()->numberObjectStructure);
-    markIfNeeded(markStack, d()->prototypeFunctionStructure);
-    markIfNeeded(markStack, d()->regExpMatchesArrayStructure);
-    markIfNeeded(markStack, d()->regExpStructure);
-    markIfNeeded(markStack, d()->stringObjectStructure);
-
-    // No need to mark the other structures, because their prototypes are all
-    // guaranteed to be referenced elsewhere.
-
-    Register* registerArray = d()->registerArray.get();
-    if (!registerArray)
-        return;
-
-    size_t size = d()->registerArraySize;
-    markStack.appendValues(reinterpret_cast<JSValue*>(registerArray), size);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSVariableObject::visitChildren(visitor);
+
+    visitIfNeeded(visitor, &m_globalScopeChain);
+    visitIfNeeded(visitor, &m_methodCallDummy);
+
+    visitIfNeeded(visitor, &m_regExpConstructor);
+    visitIfNeeded(visitor, &m_errorConstructor);
+    visitIfNeeded(visitor, &m_evalErrorConstructor);
+    visitIfNeeded(visitor, &m_rangeErrorConstructor);
+    visitIfNeeded(visitor, &m_referenceErrorConstructor);
+    visitIfNeeded(visitor, &m_syntaxErrorConstructor);
+    visitIfNeeded(visitor, &m_typeErrorConstructor);
+    visitIfNeeded(visitor, &m_URIErrorConstructor);
+
+    visitIfNeeded(visitor, &m_evalFunction);
+    visitIfNeeded(visitor, &m_callFunction);
+    visitIfNeeded(visitor, &m_applyFunction);
+
+    visitIfNeeded(visitor, &m_objectPrototype);
+    visitIfNeeded(visitor, &m_functionPrototype);
+    visitIfNeeded(visitor, &m_arrayPrototype);
+    visitIfNeeded(visitor, &m_booleanPrototype);
+    visitIfNeeded(visitor, &m_stringPrototype);
+    visitIfNeeded(visitor, &m_numberPrototype);
+    visitIfNeeded(visitor, &m_datePrototype);
+    visitIfNeeded(visitor, &m_regExpPrototype);
+
+    visitIfNeeded(visitor, &m_argumentsStructure);
+    visitIfNeeded(visitor, &m_arrayStructure);
+    visitIfNeeded(visitor, &m_booleanObjectStructure);
+    visitIfNeeded(visitor, &m_callbackConstructorStructure);
+    visitIfNeeded(visitor, &m_callbackFunctionStructure);
+    visitIfNeeded(visitor, &m_callbackObjectStructure);
+    visitIfNeeded(visitor, &m_dateStructure);
+    visitIfNeeded(visitor, &m_emptyObjectStructure);
+    visitIfNeeded(visitor, &m_nullPrototypeObjectStructure);
+    visitIfNeeded(visitor, &m_errorStructure);
+    visitIfNeeded(visitor, &m_functionStructure);
+    visitIfNeeded(visitor, &m_numberObjectStructure);
+    visitIfNeeded(visitor, &m_regExpMatchesArrayStructure);
+    visitIfNeeded(visitor, &m_regExpStructure);
+    visitIfNeeded(visitor, &m_stringObjectStructure);
+    visitIfNeeded(visitor, &m_internalFunctionStructure);
+
+    if (m_registerArray) {
+        // Outside the execution of global code, when our variables are torn off,
+        // we can mark the torn-off array.
+        visitor.appendValues(m_registerArray.get(), m_registerArraySize);
+    } else if (m_registers) {
+        // During execution of global code, when our variables are in the register file,
+        // the symbol table tells us how many variables there are, and registers
+        // points to where they end, and the registers used for execution begin.
+        visitor.appendValues(m_registers - symbolTable().size(), symbolTable().size());
+    }
 }
 
 ExecState* JSGlobalObject::globalExec()
 {
-    return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize);
+    return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
 }
 
 bool JSGlobalObject::isDynamicScope(bool&) const
@@ -416,19 +378,26 @@ bool JSGlobalObject::isDynamicScope(bool&) const
     return true;
 }
 
+void JSGlobalObject::disableEval()
+{
+    ASSERT(m_isEvalEnabled);
+    m_isEvalEnabled = false;
+}
+
 void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
 {
-    ASSERT(!d()->registerArray);
-    ASSERT(!d()->registerArraySize);
+    ASSERT(!m_registerArray);
+    ASSERT(!m_registerArraySize);
 
     int numGlobals = registerFile.numGlobals();
     if (!numGlobals) {
-        d()->registers = 0;
+        m_registers = 0;
         return;
     }
-    
-    Register* registerArray = copyRegisterArray(registerFile.lastGlobal(), numGlobals);
-    setRegisters(registerArray + numGlobals, registerArray, numGlobals);
+
+    OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData(), reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.lastGlobal()), numGlobals, numGlobals);
+    WriteBarrier<Unknown>* registers = registerArray.get() + numGlobals;
+    setRegisters(registers, registerArray.release(), numGlobals);
 }
 
 void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
@@ -440,37 +409,111 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
     registerFile.setGlobalObject(this);
     registerFile.setNumGlobals(symbolTable().size());
 
-    if (d()->registerArray) {
-        memcpy(registerFile.start() - d()->registerArraySize, d()->registerArray.get(), d()->registerArraySize * sizeof(Register));
-        setRegisters(registerFile.start(), 0, 0);
+    if (m_registerArray) {
+        // The register file is always a gc root so no barrier is needed here
+        memcpy(registerFile.start() - m_registerArraySize, m_registerArray.get(), m_registerArraySize * sizeof(WriteBarrier<Unknown>));
+        setRegisters(reinterpret_cast<WriteBarrier<Unknown>*>(registerFile.start()), nullptr, 0);
     }
 }
 
+void JSGlobalObject::resizeRegisters(int oldSize, int newSize)
+{
+    ASSERT(oldSize <= newSize);
+    if (newSize == oldSize)
+        return;
+    ASSERT(newSize && newSize > oldSize);
+    if (m_registerArray || !m_registers) {
+        ASSERT(static_cast<size_t>(oldSize) == m_registerArraySize);
+        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
+        for (int i = 0; i < oldSize; i++)
+            registerArray[newSize - oldSize + i].set(globalData(), this, m_registerArray[i].get());
+        WriteBarrier<Unknown>* registers = registerArray.get() + newSize;
+        setRegisters(registers, registerArray.release(), newSize);
+    } else {
+        ASSERT(static_cast<size_t>(newSize) < globalData().interpreter->registerFile().maxGlobals());
+        globalData().interpreter->registerFile().setNumGlobals(newSize);
+    }
+
+    for (int i = -newSize; i < -oldSize; ++i)
+        m_registers[i].setUndefined();
+}
+
 void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData)
 {
     return globalData->heap.allocate(size);
 }
 
-void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData)
+void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
+{
+    size_t oldSize = m_registerArraySize;
+    size_t newSize = oldSize + count;
+    OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]);
+    if (m_registerArray) {
+        // memcpy is safe here as we're copying barriers we already own from the existing array
+        memcpy(registerArray.get() + count, m_registerArray.get(), oldSize * sizeof(Register));
+    }
+
+    WriteBarrier<Unknown>* registers = registerArray.get() + newSize;
+    setRegisters(registers, registerArray.release(), newSize);
+
+    for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
+        GlobalPropertyInfo& global = globals[i];
+        ASSERT(global.attributes & DontDelete);
+        SymbolTableEntry newEntry(index, global.attributes);
+        symbolTable().add(global.identifier.impl(), newEntry);
+        registerAt(index).set(globalData(), this, global.value);
+    }
+}
+
+bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
+{
+    if (getStaticFunctionSlot<JSVariableObject>(exec, ExecState::globalObjectTable(exec), this, propertyName, slot))
+        return true;
+    return symbolTableGet(propertyName, slot);
+}
+
+bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    if (getStaticFunctionDescriptor<JSVariableObject>(exec, ExecState::globalObjectTable(exec), this, propertyName, descriptor))
+        return true;
+    return symbolTableGet(propertyName, descriptor);
+}
+
+void JSGlobalObject::WeakMapsFinalizer::finalize(Handle<Unknown> handle, void*)
+{
+    JSGlobalObject* globalObject = asGlobalObject(handle.get());
+    globalObject->m_weakMaps.clear();
+}
+
+JSGlobalObject::WeakMapsFinalizer* JSGlobalObject::weakMapsFinalizer()
 {
-    delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData);
+    static WeakMapsFinalizer* finalizer = new WeakMapsFinalizer();
+    return finalizer;
 }
 
-DynamicGlobalObjectScope::DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
-    : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
+DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject)
+    : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject)
     , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
 {
     if (!m_dynamicGlobalObjectSlot) {
-#if ENABLE(JIT)
-        if (ExecutablePool::underMemoryPressure())
-            callFrame->globalData().recompileAllJSFunctions();
+#if ENABLE(ASSEMBLER)
+        if (ExecutableAllocator::underMemoryPressure())
+            globalData.recompileAllJSFunctions();
 #endif
+
         m_dynamicGlobalObjectSlot = dynamicGlobalObject;
 
         // Reset the date cache between JS invocations to force the VM
         // to observe time zone changes.
-        callFrame->globalData().resetDateCache();
+        globalData.resetDateCache();
     }
 }
 
+void slowValidateCell(JSGlobalObject* globalObject)
+{
+    if (!globalObject->isGlobalObject())
+        CRASH();
+    ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info);
+}
+
 } // namespace JSC
index dff45182d2b508a2c7812ab46a7297391c35e7ed..9f05d49123aa43f9ed33bdd423bc01d32b4da7e9 100644 (file)
@@ -26,9 +26,9 @@
 #include "JSGlobalData.h"
 #include "JSVariableObject.h"
 #include "JSWeakObjectMapRefInternal.h"
-#include "NativeFunctionWrapper.h"
 #include "NumberPrototype.h"
 #include "StringPrototype.h"
+#include "StructureChain.h"
 #include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RandomNumber.h>
@@ -42,10 +42,8 @@ namespace JSC {
     class ErrorConstructor;
     class FunctionPrototype;
     class GlobalCodeBlock;
-    class GlobalEvalFunction;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
-    class PrototypeFunction;
     class RegExpConstructor;
     class RegExpPrototype;
     class RegisterFile;
@@ -57,130 +55,106 @@ namespace JSC {
     
     class JSGlobalObject : public JSVariableObject {
     protected:
-        using JSVariableObject::JSVariableObjectData;
         typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
 
-        struct JSGlobalObjectData : public JSVariableObjectData {
-            // We use an explicit destructor function pointer instead of a
-            // virtual destructor because we want to avoid adding a vtable
-            // pointer to this struct. Adding a vtable pointer would force the
-            // compiler to emit costly pointer fixup code when casting from
-            // JSVariableObjectData* to JSGlobalObjectData*.
-            typedef void (*Destructor)(void*);
-
-            JSGlobalObjectData(Destructor destructor)
-                : JSVariableObjectData(&symbolTable, 0)
-                , destructor(destructor)
-                , registerArraySize(0)
-                , globalScopeChain(NoScopeChain())
-                , regExpConstructor(0)
-                , errorConstructor(0)
-                , evalErrorConstructor(0)
-                , rangeErrorConstructor(0)
-                , referenceErrorConstructor(0)
-                , syntaxErrorConstructor(0)
-                , typeErrorConstructor(0)
-                , URIErrorConstructor(0)
-                , evalFunction(0)
-                , callFunction(0)
-                , applyFunction(0)
-                , objectPrototype(0)
-                , functionPrototype(0)
-                , arrayPrototype(0)
-                , booleanPrototype(0)
-                , stringPrototype(0)
-                , numberPrototype(0)
-                , datePrototype(0)
-                , regExpPrototype(0)
-                , methodCallDummy(0)
-                , weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
-            {
-            }
-            
-            Destructor destructor;
-            
-            size_t registerArraySize;
-
-            JSGlobalObject* next;
-            JSGlobalObject* prev;
-
-            Debugger* debugger;
-            
-            ScopeChain globalScopeChain;
-            Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
-
-            int recursion;
-
-            RegExpConstructor* regExpConstructor;
-            ErrorConstructor* errorConstructor;
-            NativeErrorConstructor* evalErrorConstructor;
-            NativeErrorConstructor* rangeErrorConstructor;
-            NativeErrorConstructor* referenceErrorConstructor;
-            NativeErrorConstructor* syntaxErrorConstructor;
-            NativeErrorConstructor* typeErrorConstructor;
-            NativeErrorConstructor* URIErrorConstructor;
-
-            GlobalEvalFunction* evalFunction;
-            NativeFunctionWrapper* callFunction;
-            NativeFunctionWrapper* applyFunction;
-
-            ObjectPrototype* objectPrototype;
-            FunctionPrototype* functionPrototype;
-            ArrayPrototype* arrayPrototype;
-            BooleanPrototype* booleanPrototype;
-            StringPrototype* stringPrototype;
-            NumberPrototype* numberPrototype;
-            DatePrototype* datePrototype;
-            RegExpPrototype* regExpPrototype;
-
-            JSObject* methodCallDummy;
-
-            RefPtr<Structure> argumentsStructure;
-            RefPtr<Structure> arrayStructure;
-            RefPtr<Structure> booleanObjectStructure;
-            RefPtr<Structure> callbackConstructorStructure;
-            RefPtr<Structure> callbackFunctionStructure;
-            RefPtr<Structure> callbackObjectStructure;
-            RefPtr<Structure> dateStructure;
-            RefPtr<Structure> emptyObjectStructure;
-            RefPtr<Structure> errorStructure;
-            RefPtr<Structure> functionStructure;
-            RefPtr<Structure> numberObjectStructure;
-            RefPtr<Structure> prototypeFunctionStructure;
-            RefPtr<Structure> regExpMatchesArrayStructure;
-            RefPtr<Structure> regExpStructure;
-            RefPtr<Structure> stringObjectStructure;
-
-            SymbolTable symbolTable;
-            unsigned profileGroup;
-
-            RefPtr<JSGlobalData> globalData;
-
-            HashSet<GlobalCodeBlock*> codeBlocks;
-            WeakMapSet weakMaps;
-            WeakRandom weakRandom;
+        RefPtr<JSGlobalData> m_globalData;
+
+        size_t m_registerArraySize;
+        Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize];
+
+        WriteBarrier<ScopeChainNode> m_globalScopeChain;
+        WriteBarrier<JSObject> m_methodCallDummy;
+
+        WriteBarrier<RegExpConstructor> m_regExpConstructor;
+        WriteBarrier<ErrorConstructor> m_errorConstructor;
+        WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor;
+        WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor;
+        WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor;
+        WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor;
+        WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
+        WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
+
+        WriteBarrier<JSFunction> m_evalFunction;
+        WriteBarrier<JSFunction> m_callFunction;
+        WriteBarrier<JSFunction> m_applyFunction;
+
+        WriteBarrier<ObjectPrototype> m_objectPrototype;
+        WriteBarrier<FunctionPrototype> m_functionPrototype;
+        WriteBarrier<ArrayPrototype> m_arrayPrototype;
+        WriteBarrier<BooleanPrototype> m_booleanPrototype;
+        WriteBarrier<StringPrototype> m_stringPrototype;
+        WriteBarrier<NumberPrototype> m_numberPrototype;
+        WriteBarrier<DatePrototype> m_datePrototype;
+        WriteBarrier<RegExpPrototype> m_regExpPrototype;
+
+        WriteBarrier<Structure> m_argumentsStructure;
+        WriteBarrier<Structure> m_arrayStructure;
+        WriteBarrier<Structure> m_booleanObjectStructure;
+        WriteBarrier<Structure> m_callbackConstructorStructure;
+        WriteBarrier<Structure> m_callbackFunctionStructure;
+        WriteBarrier<Structure> m_callbackObjectStructure;
+        WriteBarrier<Structure> m_dateStructure;
+        WriteBarrier<Structure> m_emptyObjectStructure;
+        WriteBarrier<Structure> m_nullPrototypeObjectStructure;
+        WriteBarrier<Structure> m_errorStructure;
+        WriteBarrier<Structure> m_functionStructure;
+        WriteBarrier<Structure> m_numberObjectStructure;
+        WriteBarrier<Structure> m_regExpMatchesArrayStructure;
+        WriteBarrier<Structure> m_regExpStructure;
+        WriteBarrier<Structure> m_stringObjectStructure;
+        WriteBarrier<Structure> m_internalFunctionStructure;
+
+        unsigned m_profileGroup;
+        Debugger* m_debugger;
+
+        WeakMapSet m_weakMaps;
+        Weak<JSGlobalObject> m_weakMapsFinalizer;
+        class WeakMapsFinalizer : public WeakHandleOwner {
+        public:
+            virtual void finalize(Handle<Unknown>, void* context);
         };
+        static WeakMapsFinalizer* weakMapsFinalizer();
+
+        WeakRandom m_weakRandom;
+
+        SymbolTable m_symbolTable;
+
+        bool m_isEvalEnabled;
 
     public:
         void* operator new(size_t, JSGlobalData*);
 
-        explicit JSGlobalObject()
-            : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData))
+        explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure)
+            : JSVariableObject(globalData, structure, &m_symbolTable, 0)
+            , m_registerArraySize(0)
+            , m_globalScopeChain()
+            , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
+            , m_isEvalEnabled(true)
         {
+            COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
+            putThisToAnonymousValue(0);
             init(this);
         }
 
+        static JS_EXPORTDATA const ClassInfo s_info;
+
     protected:
-        JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
-            : JSVariableObject(structure, data)
+        JSGlobalObject(JSGlobalData& globalData, Structure* structure, JSObject* thisValue)
+            : JSVariableObject(globalData, structure, &m_symbolTable, 0)
+            , m_registerArraySize(0)
+            , m_globalScopeChain()
+            , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
+            , m_isEvalEnabled(true)
         {
+            COMPILE_ASSERT(JSGlobalObject::AnonymousSlotCount == 1, JSGlobalObject_has_only_a_single_slot);
+            putThisToAnonymousValue(0);
             init(thisValue);
         }
 
     public:
         virtual ~JSGlobalObject();
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
@@ -191,65 +165,65 @@ namespace JSC {
         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
 
-        // Linked list of all global objects that use the same JSGlobalData.
-        JSGlobalObject*& head() { return d()->globalData->head; }
-        JSGlobalObject* next() { return d()->next; }
+        // We use this in the code generator as we perform symbol table
+        // lookups prior to initializing the properties
+        bool symbolTableHasProperty(const Identifier& propertyName);
 
         // The following accessors return pristine values, even if a script 
         // replaces the global object's associated property.
 
-        RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
-
-        ErrorConstructor* errorConstructor() const { return d()->errorConstructor; }
-        NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; }
-        NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
-        NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
-        NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
-        NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; }
-        NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; }
-
-        GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
-
-        ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
-        FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
-        ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
-        BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
-        StringPrototype* stringPrototype() const { return d()->stringPrototype; }
-        NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
-        DatePrototype* datePrototype() const { return d()->datePrototype; }
-        RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
-
-        JSObject* methodCallDummy() const { return d()->methodCallDummy; }
-
-        Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
-        Structure* arrayStructure() const { return d()->arrayStructure.get(); }
-        Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
-        Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
-        Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
-        Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
-        Structure* dateStructure() const { return d()->dateStructure.get(); }
-        Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
-        Structure* errorStructure() const { return d()->errorStructure.get(); }
-        Structure* functionStructure() const { return d()->functionStructure.get(); }
-        Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
-        Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
-        Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
-        Structure* regExpStructure() const { return d()->regExpStructure.get(); }
-        Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
-
-        void setProfileGroup(unsigned value) { d()->profileGroup = value; }
-        unsigned profileGroup() const { return d()->profileGroup; }
-
-        Debugger* debugger() const { return d()->debugger; }
-        void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
-        
+        RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); }
+
+        ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); }
+        NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
+        NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
+        NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
+        NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); }
+        NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); }
+        NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); }
+
+        JSFunction* evalFunction() const { return m_evalFunction.get(); }
+        JSFunction* callFunction() const { return m_callFunction.get(); }
+        JSFunction* applyFunction() const { return m_applyFunction.get(); }
+
+        ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
+        FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
+        ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
+        BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
+        StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
+        NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
+        DatePrototype* datePrototype() const { return m_datePrototype.get(); }
+        RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
+
+        JSObject* methodCallDummy() const { return m_methodCallDummy.get(); }
+
+        Structure* argumentsStructure() const { return m_argumentsStructure.get(); }
+        Structure* arrayStructure() const { return m_arrayStructure.get(); }
+        Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
+        Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
+        Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
+        Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
+        Structure* dateStructure() const { return m_dateStructure.get(); }
+        Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); }
+        Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
+        Structure* errorStructure() const { return m_errorStructure.get(); }
+        Structure* functionStructure() const { return m_functionStructure.get(); }
+        Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
+        Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
+        Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
+        Structure* regExpStructure() const { return m_regExpStructure.get(); }
+        Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
+
+        void setProfileGroup(unsigned value) { m_profileGroup = value; }
+        unsigned profileGroup() const { return m_profileGroup; }
+
+        Debugger* debugger() const { return m_debugger; }
+        void setDebugger(Debugger* debugger) { m_debugger = debugger; }
+
         virtual bool supportsProfiling() const { return false; }
-        
-        int recursion() { return d()->recursion; }
-        void incRecursion() { ++d()->recursion; }
-        void decRecursion() { --d()->recursion; }
-        
-        ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
+        virtual bool supportsRichSourceInfo() const { return true; }
+
+        ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); }
 
         virtual bool isGlobalObject() const { return true; }
 
@@ -262,35 +236,39 @@ namespace JSC {
 
         virtual bool isDynamicScope(bool& requiresDynamicChecks) const;
 
-        HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
+        void disableEval();
+        bool isEvalEnabled() { return m_isEvalEnabled; }
 
         void copyGlobalsFrom(RegisterFile&);
         void copyGlobalsTo(RegisterFile&);
-        
-        void resetPrototype(JSValue prototype);
+        void resizeRegisters(int oldSize, int newSize);
+
+        void resetPrototype(JSGlobalData&, JSValue prototype);
 
-        JSGlobalData* globalData() { return d()->globalData.get(); }
-        JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
+        JSGlobalData& globalData() const { return *m_globalData.get(); }
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
         void registerWeakMap(OpaqueJSWeakObjectMap* map)
         {
-            d()->weakMaps.add(map);
+            if (!m_weakMapsFinalizer)
+                m_weakMapsFinalizer.set(globalData(), this, weakMapsFinalizer());
+            m_weakMaps.add(map);
         }
 
         void deregisterWeakMap(OpaqueJSWeakObjectMap* map)
         {
-            d()->weakMaps.remove(map);
+            m_weakMaps.remove(map);
         }
 
-        double weakRandomNumber() { return d()->weakRandom.get(); }
+        double weakRandomNumber() { return m_weakRandom.get(); }
     protected:
 
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        static const unsigned AnonymousSlotCount = JSVariableObject::AnonymousSlotCount + 1;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
         struct GlobalPropertyInfo {
             GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
@@ -307,13 +285,11 @@ namespace JSC {
         void addStaticGlobals(GlobalPropertyInfo*, int count);
 
     private:
-        static void destroyJSGlobalObjectData(void*);
-
         // FIXME: Fold reset into init.
         void init(JSObject* thisValue);
         void reset(JSValue prototype);
 
-        void setRegisters(Register* registers, Register* registerArray, size_t count);
+        void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
 
         void* operator new(size_t); // can only be allocated with JSGlobalData
     };
@@ -326,42 +302,10 @@ namespace JSC {
         return static_cast<JSGlobalObject*>(asObject(value));
     }
 
-    inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
+    inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count)
     {
         JSVariableObject::setRegisters(registers, registerArray);
-        d()->registerArraySize = count;
-    }
-
-    inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
-    {
-        size_t oldSize = d()->registerArraySize;
-        size_t newSize = oldSize + count;
-        Register* registerArray = new Register[newSize];
-        if (d()->registerArray)
-            memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
-        setRegisters(registerArray + newSize, registerArray, newSize);
-
-        for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
-            GlobalPropertyInfo& global = globals[i];
-            ASSERT(global.attributes & DontDelete);
-            SymbolTableEntry newEntry(index, global.attributes);
-            symbolTable().add(global.identifier.ustring().rep(), newEntry);
-            registerAt(index) = global.value;
-        }
-    }
-
-    inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-    {
-        if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
-            return true;
-        return symbolTableGet(propertyName, slot);
-    }
-
-    inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
-    {
-        if (symbolTableGet(propertyName, descriptor))
-            return true;
-        return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+        m_registerArraySize = count;
     }
 
     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
@@ -373,21 +317,19 @@ namespace JSC {
         return symbolTableGet(propertyName, slot, slotIsWriteable);
     }
 
+    inline bool JSGlobalObject::symbolTableHasProperty(const Identifier& propertyName)
+    {
+        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
+        return !entry.isNull();
+    }
+
     inline JSValue Structure::prototypeForLookup(ExecState* exec) const
     {
         if (typeInfo().type() == ObjectType)
-            return m_prototype;
-
-#if USE(JSVALUE32)
-        if (typeInfo().type() == StringType)
-            return exec->lexicalGlobalObject()->stringPrototype();
+            return m_prototype.get();
 
-        ASSERT(typeInfo().type() == NumberType);
-        return exec->lexicalGlobalObject()->numberPrototype();
-#else
         ASSERT(typeInfo().type() == StringType);
         return exec->lexicalGlobalObject()->stringPrototype();
-#endif
     }
 
     inline StructureChain* Structure::prototypeChain(ExecState* exec) const
@@ -395,7 +337,7 @@ namespace JSC {
         // We cache our prototype chain so our clients can share it.
         if (!isValid(exec, m_cachedPrototypeChain.get())) {
             JSValue prototype = prototypeForLookup(exec);
-            m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
+            m_cachedPrototypeChain.set(exec->globalData(), this, StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure()));
         }
         return m_cachedPrototypeChain.get();
     }
@@ -406,9 +348,9 @@ namespace JSC {
             return false;
 
         JSValue prototype = prototypeForLookup(exec);
-        RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
+        WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
         while(*cachedStructure && !prototype.isNull()) {
-            if (asObject(prototype)->structure() != *cachedStructure)
+            if (asObject(prototype)->structure() != cachedStructure->get())
                 return false;
             ++cachedStructure;
             prototype = asObject(prototype)->prototype();
@@ -427,46 +369,62 @@ namespace JSC {
         return globalData().dynamicGlobalObject;
     }
 
-    inline JSObject* constructEmptyObject(ExecState* exec)
+    inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
     {
-        return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
+        return constructEmptyObject(exec, globalObject->emptyObjectStructure());
     }
-    
-    inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
+
+    inline JSObject* constructEmptyObject(ExecState* exec)
     {
-        return new (exec) JSObject(globalObject->emptyObjectStructure());
+        return constructEmptyObject(exec, exec->lexicalGlobalObject());
     }
 
-    inline JSArray* constructEmptyArray(ExecState* exec)
+    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
     {
-        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
+        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure());
     }
     
-    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
+    inline JSArray* constructEmptyArray(ExecState* exec)
+    {
+        return constructEmptyArray(exec, exec->lexicalGlobalObject());
+    }
+
+    inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength)
     {
-        return new (exec) JSArray(globalObject->arrayStructure());
+        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), initialLength, CreateInitialized);
     }
 
     inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
     {
-        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
+        return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength);
     }
 
-    inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
+    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, JSValue singleItemValue)
     {
         MarkedArgumentBuffer values;
         values.append(singleItemValue);
-        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
+        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), values);
+    }
+
+    inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
+    {
+        return constructArray(exec, exec->lexicalGlobalObject(), singleItemValue);
+    }
+
+    inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values)
+    {
+        return new (exec) JSArray(exec->globalData(), globalObject->arrayStructure(), values);
     }
 
     inline JSArray* constructArray(ExecState* exec, const ArgList& values)
     {
-        return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
+        return constructArray(exec, exec->lexicalGlobalObject(), values);
     }
 
-    class DynamicGlobalObjectScope : public Noncopyable {
+    class DynamicGlobalObjectScope {
+        WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
     public:
-        DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject);
+        DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
 
         ~DynamicGlobalObjectScope()
         {
index 228ed6cd87d4f5cfd3f92db70c572739ec4621f9..35507e872042e5812ae85f7f0dd9ba930be97a84 100644 (file)
@@ -26,7 +26,6 @@
 #include "JSGlobalObjectFunctions.h"
 
 #include "CallFrame.h"
-#include "GlobalEvalFunction.h"
 #include "Interpreter.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "LiteralParser.h"
 #include "Nodes.h"
 #include "Parser.h"
-#include "StringBuilder.h"
-#include "StringExtras.h"
+#include "UStringBuilder.h"
 #include "dtoa.h"
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
 #include <wtf/unicode/UTF8.h>
 
 using namespace WTF;
@@ -51,12 +49,12 @@ using namespace Unicode;
 
 namespace JSC {
 
-static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEscape)
+static JSValue encode(ExecState* exec, const char* doNotEscape)
 {
-    UString str = args.at(0).toString(exec);
-    CString cstr = str.UTF8String(true);
+    UString str = exec->argument(0).toString(exec);
+    CString cstr = str.utf8(true);
     if (!cstr.data())
-        return throwError(exec, URIError, "String contained an illegal UTF-16 sequence.");
+        return throwError(exec, createURIError(exec, "String contained an illegal UTF-16 sequence."));
 
     JSStringBuilder builder;
     const char* p = cstr.data();
@@ -73,13 +71,13 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc
     return builder.build(exec);
 }
 
-static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict)
+static JSValue decode(ExecState* exec, const char* doNotUnescape, bool strict)
 {
     JSStringBuilder builder;
-    UString str = args.at(0).toString(exec);
+    UString str = exec->argument(0).toString(exec);
     int k = 0;
-    int len = str.size();
-    const UChar* d = str.data();
+    int len = str.length();
+    const UChar* d = str.characters();
     UChar u = 0;
     while (k < len) {
         const UChar* p = d + k;
@@ -118,7 +116,7 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne
             }
             if (charLen == 0) {
                 if (strict)
-                    return throwError(exec, URIError);
+                    return throwError(exec, createURIError(exec, "URI error"));
                 // The only case where we don't use "strict" mode is the "unescape" function.
                 // For that, it's good to support the wonky "%u" syntax for compatibility with WinIE.
                 if (k <= len - 6 && p[1] == 'u'
@@ -142,6 +140,7 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne
 bool isStrWhiteSpace(UChar c)
 {
     switch (c) {
+        // ECMA-262-5th 7.2 & 7.3
         case 0x0009:
         case 0x000A:
         case 0x000B:
@@ -151,6 +150,7 @@ bool isStrWhiteSpace(UChar c)
         case 0x00A0:
         case 0x2028:
         case 0x2029:
+        case 0xFEFF:
             return true;
         default:
             return c > 0xff && isSeparatorSpace(c);
@@ -195,10 +195,32 @@ double parseIntOverflow(const char* s, int length, int radix)
     return number;
 }
 
+double parseIntOverflow(const UChar* s, int length, int radix)
+{
+    double number = 0.0;
+    double radixMultiplier = 1.0;
+
+    for (const UChar* p = s + length - 1; p >= s; p--) {
+        if (radixMultiplier == Inf) {
+            if (*p != '0') {
+                number = Inf;
+                break;
+            }
+        } else {
+            int digit = parseDigit(*p, radix);
+            number += digit * radixMultiplier;
+        }
+
+        radixMultiplier *= radix;
+    }
+
+    return number;
+}
+
 static double parseInt(const UString& s, int radix)
 {
-    int length = s.size();
-    const UChar* data = s.data();
+    int length = s.length();
+    const UChar* data = s.characters();
     int p = 0;
 
     while (p < length && isStrWhiteSpace(data[p]))
@@ -241,11 +263,10 @@ static double parseInt(const UString& s, int radix)
     }
 
     if (number >= mantissaOverflowLowerBound) {
-        // FIXME: It is incorrect to use UString::ascii() here because it's not thread-safe.
         if (radix == 10)
-            number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);
+            number = WTF::strtod(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0);
         else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
-            number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);
+            number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix);
     }
 
     if (!sawDigit)
@@ -254,105 +275,241 @@ static double parseInt(const UString& s, int radix)
     return sign * number;
 }
 
+static const int SizeOfInfinity = 8;
+
+static bool isInfinity(const UChar* data, const UChar* end)
+{
+    return (end - data) >= SizeOfInfinity
+        && data[0] == 'I'
+        && data[1] == 'n'
+        && data[2] == 'f'
+        && data[3] == 'i'
+        && data[4] == 'n'
+        && data[5] == 'i'
+        && data[6] == 't'
+        && data[7] == 'y';
+}
+
+// See ecma-262 9.3.1
+static double jsHexIntegerLiteral(const UChar*& data, const UChar* end)
+{
+    // Hex number.
+    data += 2;
+    const UChar* firstDigitPosition = data;
+    double number = 0;
+    while (true) {
+        number = number * 16 + toASCIIHexValue(*data);
+        ++data;
+        if (data == end)
+            break;
+        if (!isASCIIHexDigit(*data))
+            break;
+    }
+    if (number >= mantissaOverflowLowerBound)
+        number = parseIntOverflow(firstDigitPosition, data - firstDigitPosition, 16);
+
+    return number;
+}
+
+// See ecma-262 9.3.1
+static double jsStrDecimalLiteral(const UChar*& data, const UChar* end)
+{
+    ASSERT(data < end);
+
+    // Copy the sting into a null-terminated byte buffer, and call strtod.
+    Vector<char, 32> byteBuffer;
+    for (const UChar* characters = data; characters < end; ++characters) {
+        UChar character = *characters;
+        byteBuffer.append(isASCII(character) ? character : 0);
+    }
+    byteBuffer.append(0);
+    char* endOfNumber;
+    double number = WTF::strtod(byteBuffer.data(), &endOfNumber);
+
+    // Check if strtod found a number; if so return it.
+    ptrdiff_t consumed = endOfNumber - byteBuffer.data();
+    if (consumed) {
+        data += consumed;
+        return number;
+    }
+
+    // Check for [+-]?Infinity
+    switch (*data) {
+    case 'I':
+        if (isInfinity(data, end)) {
+            data += SizeOfInfinity;
+            return Inf;
+        }
+        break;
+
+    case '+':
+        if (isInfinity(data + 1, end)) {
+            data += SizeOfInfinity + 1;
+            return Inf;
+        }
+        break;
+
+    case '-':
+        if (isInfinity(data + 1, end)) {
+            data += SizeOfInfinity + 1;
+            return -Inf;
+        }
+        break;
+    }
+
+    // Not a number.
+    return NaN;
+}
+
+// See ecma-262 9.3.1
+double jsToNumber(const UString& s)
+{
+    unsigned size = s.length();
+
+    if (size == 1) {
+        UChar c = s.characters()[0];
+        if (isASCIIDigit(c))
+            return c - '0';
+        if (isStrWhiteSpace(c))
+            return 0;
+        return NaN;
+    }
+
+    const UChar* data = s.characters();
+    const UChar* end = data + size;
+
+    // Skip leading white space.
+    for (; data < end; ++data) {
+        if (!isStrWhiteSpace(*data))
+            break;
+    }
+
+    // Empty string.
+    if (data == end)
+        return 0.0;
+
+    double number;
+    if (data[0] == '0' && data + 2 < end && (data[1] | 0x20) == 'x' && isASCIIHexDigit(data[2]))
+        number = jsHexIntegerLiteral(data, end);
+    else
+        number = jsStrDecimalLiteral(data, end);
+
+    // Allow trailing white space.
+    for (; data < end; ++data) {
+        if (!isStrWhiteSpace(*data))
+            break;
+    }
+    if (data != end)
+        return NaN;
+
+    return number;
+}
+
 static double parseFloat(const UString& s)
 {
-    // Check for 0x prefix here, because toDouble allows it, but we must treat it as 0.
-    // Need to skip any whitespace and then one + or - sign.
-    int length = s.size();
-    const UChar* data = s.data();
-    int p = 0;
-    while (p < length && isStrWhiteSpace(data[p]))
-        ++p;
+    unsigned size = s.length();
 
-    if (p < length && (data[p] == '+' || data[p] == '-'))
-        ++p;
+    if (size == 1) {
+        UChar c = s.characters()[0];
+        if (isASCIIDigit(c))
+            return c - '0';
+        return NaN;
+    }
 
-    if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X'))
-        return 0;
+    const UChar* data = s.characters();
+    const UChar* end = data + size;
 
-    // FIXME: UString::toDouble will ignore leading ASCII spaces, but we need to ignore
-    // other StrWhiteSpaceChar values as well.
-    return s.toDouble(true /*tolerant*/, false /* NaN for empty string */);
+    // Skip leading white space.
+    for (; data < end; ++data) {
+        if (!isStrWhiteSpace(*data))
+            break;
+    }
+
+    // Empty string.
+    if (data == end)
+        return NaN;
+
+    return jsStrDecimalLiteral(data, end);
 }
 
-JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
 {
-    JSObject* thisObject = thisValue.toThisObject(exec);
+    JSObject* thisObject = exec->hostThisValue().toThisObject(exec);
     JSObject* unwrappedObject = thisObject->unwrappedObject();
-    if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != function)
-        return throwError(exec, EvalError, "The \"this\" value passed to eval must be the global object from which eval originated");
+    if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != exec->callee())
+        return throwVMError(exec, createEvalError(exec, "The \"this\" value passed to eval must be the global object from which eval originated"));
 
-    JSValue x = args.at(0);
+    JSValue x = exec->argument(0);
     if (!x.isString())
-        return x;
+        return JSValue::encode(x);
 
     UString s = x.toString(exec);
 
-    LiteralParser preparser(exec, s, LiteralParser::NonStrictJSON);
+    LiteralParser preparser(exec, s.characters(), s.length(), LiteralParser::NonStrictJSON);
     if (JSValue parsedObject = preparser.tryLiteralParse())
-        return parsedObject;
+        return JSValue::encode(parsedObject);
 
-    RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s));
-    JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node());
+    EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false);
+    JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain());
     if (error)
-        return throwError(exec, error);
+        return throwVMError(exec, error);
 
-    return exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot());
+    return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()));
 }
 
-JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
 {
-    JSValue value = args.at(0);
-    int32_t radix = args.at(1).toInt32(exec);
+    JSValue value = exec->argument(0);
+    int32_t radix = exec->argument(1).toInt32(exec);
 
     if (radix != 0 && radix != 10)
-        return jsNumber(exec, parseInt(value.toString(exec), radix));
+        return JSValue::encode(jsNumber(parseInt(value.toString(exec), radix)));
 
     if (value.isInt32())
-        return value;
+        return JSValue::encode(value);
 
     if (value.isDouble()) {
         double d = value.asDouble();
         if (isfinite(d))
-            return jsNumber(exec, (d > 0) ? floor(d) : ceil(d));
+            return JSValue::encode(jsNumber((d > 0) ? floor(d) : ceil(d)));
         if (isnan(d) || isinf(d))
-            return jsNaN(exec);
-        return jsNumber(exec, 0);
+            return JSValue::encode(jsNaN());
+        return JSValue::encode(jsNumber(0));
     }
 
-    return jsNumber(exec, parseInt(value.toString(exec), radix));
+    return JSValue::encode(jsNumber(parseInt(value.toString(exec), radix)));
 }
 
-JSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState* exec)
 {
-    return jsNumber(exec, parseFloat(args.at(0).toString(exec)));
+    return JSValue::encode(jsNumber(parseFloat(exec->argument(0).toString(exec))));
 }
 
-JSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState* exec)
 {
-    return jsBoolean(isnan(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsBoolean(isnan(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState* exec)
 {
-    double n = args.at(0).toNumber(exec);
-    return jsBoolean(!isnan(n) && !isinf(n));
+    double n = exec->argument(0).toNumber(exec);
+    return JSValue::encode(jsBoolean(!isnan(n) && !isinf(n)));
 }
 
-JSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState* exec)
 {
     static const char do_not_unescape_when_decoding_URI[] =
         "#$&+,/:;=?@";
 
-    return decode(exec, args, do_not_unescape_when_decoding_URI, true);
+    return JSValue::encode(decode(exec, do_not_unescape_when_decoding_URI, true));
 }
 
-JSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState* exec)
 {
-    return decode(exec, args, "", true);
+    return JSValue::encode(decode(exec, "", true));
 }
 
-JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec)
 {
     static const char do_not_escape_when_encoding_URI[] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -360,10 +517,10 @@ JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState* exec, JSObject*, JSValue, c
         "0123456789"
         "!#$&'()*+,-./:;=?@_~";
 
-    return encode(exec, args, do_not_escape_when_encoding_URI);
+    return JSValue::encode(encode(exec, do_not_escape_when_encoding_URI));
 }
 
-JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec)
 {
     static const char do_not_escape_when_encoding_URI_component[] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -371,10 +528,10 @@ JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState* exec, JSObject*, J
         "0123456789"
         "!'()*-._~";
 
-    return encode(exec, args, do_not_escape_when_encoding_URI_component);
+    return JSValue::encode(encode(exec, do_not_escape_when_encoding_URI_component));
 }
 
-JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec)
 {
     static const char do_not_escape[] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -383,9 +540,9 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
         "*+-./@_";
 
     JSStringBuilder builder;
-    UString str = args.at(0).toString(exec);
-    const UChar* c = str.data();
-    for (unsigned k = 0; k < str.size(); k++, c++) {
+    UString str = exec->argument(0).toString(exec);
+    const UChar* c = str.characters();
+    for (unsigned k = 0; k < str.length(); k++, c++) {
         int u = c[0];
         if (u > 255) {
             char tmp[7];
@@ -400,17 +557,17 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
         }
     }
 
-    return builder.build(exec);
+    return JSValue::encode(builder.build(exec));
 }
 
-JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec)
 {
-    StringBuilder builder;
-    UString str = args.at(0).toString(exec);
+    UStringBuilder builder;
+    UString str = exec->argument(0).toString(exec);
     int k = 0;
-    int len = str.size();
+    int len = str.length();
     while (k < len) {
-        const UChar* c = str.data() + k;
+        const UChar* c = str.characters() + k;
         UChar u;
         if (c[0] == '%' && k <= len - 6 && c[1] == 'u') {
             if (isASCIIHexDigit(c[2]) && isASCIIHexDigit(c[3]) && isASCIIHexDigit(c[4]) && isASCIIHexDigit(c[5])) {
@@ -427,16 +584,7 @@ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, co
         builder.append(*c);
     }
 
-    return jsString(exec, builder.build());
-}
-
-#ifndef NDEBUG
-JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args)
-{
-    CString string = args.at(0).toString(exec).UTF8String();
-    puts(string.data());
-    return jsUndefined();
+    return JSValue::encode(jsString(exec, builder.toUString()));
 }
-#endif
 
 } // namespace JSC
index b1046f2dd48ee106da588968b714399db565aab5..36e9ac4cf90d103e54c10dd6ff333e69ca3a343e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -24,6 +24,7 @@
 #ifndef JSGlobalObjectFunctions_h
 #define JSGlobalObjectFunctions_h
 
+#include "JSValue.h"
 #include <wtf/unicode/Unicode.h>
 
 namespace JSC {
@@ -31,29 +32,27 @@ namespace JSC {
     class ArgList;
     class ExecState;
     class JSObject;
-    class JSValue;
 
     // FIXME: These functions should really be in JSGlobalObject.cpp, but putting them there
     // is a 0.5% reduction.
 
-    JSValue JSC_HOST_CALL globalFuncEval(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncParseInt(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncEscape(ExecState*, JSObject*, JSValue, const ArgList&);
-    JSValue JSC_HOST_CALL globalFuncUnescape(ExecState*, JSObject*, JSValue, const ArgList&);
-#ifndef NDEBUG
-    JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState*, JSObject*, JSValue, const ArgList&);
-#endif
+    EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncParseFloat(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncIsNaN(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncIsFinite(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncDecodeURI(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncDecodeURIComponent(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncEncodeURI(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncEncodeURIComponent(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncEscape(ExecState*);
+    EncodedJSValue JSC_HOST_CALL globalFuncUnescape(ExecState*);
 
     static const double mantissaOverflowLowerBound = 9007199254740992.0;
     double parseIntOverflow(const char*, int length, int radix);
+    double parseIntOverflow(const UChar*, int length, int radix);
     bool isStrWhiteSpace(UChar);
+    double jsToNumber(const UString& s);
 
 } // namespace JSC
 
diff --git a/runtime/JSImmediate.cpp b/runtime/JSImmediate.cpp
deleted file mode 100644 (file)
index 846238d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  Copyright (C) 2003-2006, 2008 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
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "JSImmediate.h"
-
-namespace JSC {
-
-} // namespace JSC
diff --git a/runtime/JSImmediate.h b/runtime/JSImmediate.h
deleted file mode 100644 (file)
index 9127b6a..0000000
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef JSImmediate_h
-#define JSImmediate_h
-
-#if !USE(JSVALUE32_64)
-
-#include <wtf/Assertions.h>
-#include <wtf/AlwaysInline.h>
-#include <wtf/MathExtras.h>
-#include <wtf/StdLibExtras.h>
-#include "JSValue.h"
-#include <limits>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-namespace JSC {
-
-    class ExecState;
-    class JSCell;
-    class JSFastMath;
-    class JSGlobalData;
-    class JSObject;
-    class UString;
-
-#if USE(JSVALUE64)
-    inline intptr_t reinterpretDoubleToIntptr(double value)
-    {
-        return WTF::bitwise_cast<intptr_t>(value);
-    }
-
-    inline double reinterpretIntptrToDouble(intptr_t value)
-    {
-        return WTF::bitwise_cast<double>(value);
-    }
-#endif
-
-    /*
-     * A JSValue* is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 
-     * value masquerading as a pointer). The low two bits in a JSValue* are available for type tagging
-     * because allocator alignment guarantees they will be 00 in cell pointers.
-     *
-     * For example, on a 32 bit system:
-     *
-     * JSCell*:             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     00
-     *                      [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
-     * JSImmediate:         XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     TT
-     *                      [ high 30 bits: 'payload' ]             [ low 2 bits -- tag ]
-     *
-     * Where the bottom two bits are non-zero they either indicate that the immediate is a 31 bit signed
-     * integer, or they mark the value as being an immediate of a type other than integer, with a secondary
-     * tag used to indicate the exact type.
-     *
-     * Where the lowest bit is set (TT is equal to 01 or 11) the high 31 bits form a 31 bit signed int value.
-     * Where TT is equal to 10 this indicates this is a type of immediate other than an integer, and the next
-     * two bits will form an extended tag.
-     *
-     * 31 bit signed int:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                     X1
-     *                      [ high 30 bits of the value ]      [ high bit part of value ]
-     * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      ZZ               10
-     *                      [ extended 'payload' ]  [  extended tag  ]  [  tag 'other'  ]
-     *
-     * Where the first bit of the extended tag is set this flags the value as being a boolean, and the following
-     * bit would flag the value as undefined.  If neither bits are set, the value is null.
-     *
-     * Other:               YYYYYYYYYYYYYYYYYYYYYYYYYYYY      UB               10
-     *                      [ extended 'payload' ]  [ undefined | bool ]  [ tag 'other' ]
-     *
-     * For boolean value the lowest bit in the payload holds the value of the bool, all remaining bits are zero.
-     * For undefined or null immediates the payload is zero.
-     *
-     * Boolean:             000000000000000000000000000V      01               10
-     *                      [ boolean value ]              [ bool ]       [ tag 'other' ]
-     * Undefined:           0000000000000000000000000000      10               10
-     *                      [ zero ]                    [ undefined ]     [ tag 'other' ]
-     * Null:                0000000000000000000000000000      00               10
-     *                      [ zero ]                       [ zero ]       [ tag 'other' ]
-     */
-
-    /*
-     * On 64-bit platforms, we support an alternative encoding form for immediates, if
-     * USE(JSVALUE64) is defined.  When this format is used, double precision
-     * floating point values may also be encoded as JSImmediates.
-     *
-     * The encoding makes use of unused NaN space in the IEEE754 representation.  Any value
-     * with the top 13 bits set represents a QNaN (with the sign bit set).  QNaN values
-     * can encode a 51-bit payload.  Hardware produced and C-library payloads typically
-     * have a payload of zero.  We assume that non-zero payloads are available to encode
-     * pointer and integer values.  Since any 64-bit bit pattern where the top 15 bits are
-     * all set represents a NaN with a non-zero payload, we can use this space in the NaN
-     * ranges to encode other values (however there are also other ranges of NaN space that
-     * could have been selected).  This range of NaN space is represented by 64-bit numbers
-     * begining with the 16-bit hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no
-     * valid double-precision numbers will begin fall in these ranges.
-     *
-     * The scheme we have implemented encodes double precision values by adding 2^48 to the
-     * 64-bit integer representation of the number.  After this manipulation, no encoded
-     * double-precision value will begin with the pattern 0x0000 or 0xFFFF.
-     *
-     * The top 16-bits denote the type of the encoded JSImmediate:
-     *
-     * Pointer: 0000:PPPP:PPPP:PPPP
-     *          0001:****:****:****
-     * Double:{         ...
-     *          FFFE:****:****:****
-     * Integer: FFFF:0000:IIII:IIII
-     *
-     * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.  The tag 0x0000
-     * denotes a pointer, or another form of tagged immediate.  Boolean, null and undefined
-     * values are encoded in the same manner as the default format.
-     */
-
-    class JSImmediate {
-    private:
-        friend class JIT;
-        friend class JSValue;
-        friend class JSFastMath;
-        friend class JSInterfaceJIT;
-        friend class SpecializedThunkJIT;
-        friend JSValue jsNumber(ExecState* exec, double d);
-        friend JSValue jsNumber(ExecState*, char i);
-        friend JSValue jsNumber(ExecState*, unsigned char i);
-        friend JSValue jsNumber(ExecState*, short i);
-        friend JSValue jsNumber(ExecState*, unsigned short i);
-        friend JSValue jsNumber(ExecState* exec, int i);
-        friend JSValue jsNumber(ExecState* exec, unsigned i);
-        friend JSValue jsNumber(ExecState* exec, long i);
-        friend JSValue jsNumber(ExecState* exec, unsigned long i);
-        friend JSValue jsNumber(ExecState* exec, long long i);
-        friend JSValue jsNumber(ExecState* exec, unsigned long long i);
-        friend JSValue jsNumber(JSGlobalData* globalData, double d);
-        friend JSValue jsNumber(JSGlobalData* globalData, short i);
-        friend JSValue jsNumber(JSGlobalData* globalData, unsigned short i);
-        friend JSValue jsNumber(JSGlobalData* globalData, int i);
-        friend JSValue jsNumber(JSGlobalData* globalData, unsigned i);
-        friend JSValue jsNumber(JSGlobalData* globalData, long i);
-        friend JSValue jsNumber(JSGlobalData* globalData, unsigned long i);
-        friend JSValue jsNumber(JSGlobalData* globalData, long long i);
-        friend JSValue jsNumber(JSGlobalData* globalData, unsigned long long i);
-
-#if USE(JSVALUE64)
-        // If all bits in the mask are set, this indicates an integer number,
-        // if any but not all are set this value is a double precision number.
-        static const intptr_t TagTypeNumber = 0xffff000000000000ll;
-        // This value is 2^48, used to encode doubles such that the encoded value will begin
-        // with a 16-bit pattern within the range 0x0001..0xFFFE.
-        static const intptr_t DoubleEncodeOffset = 0x1000000000000ll;
-#elif USE(JSVALUE32)
-        static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit
-#endif
-        static const intptr_t TagBitTypeOther   = 0x2; // second bit set indicates immediate other than an integer
-        static const intptr_t TagMask           = TagTypeNumber | TagBitTypeOther;
-
-        static const intptr_t ExtendedTagMask         = 0xC; // extended tag holds a further two bits
-        static const intptr_t ExtendedTagBitBool      = 0x4;
-        static const intptr_t ExtendedTagBitUndefined = 0x8;
-
-        static const intptr_t FullTagTypeMask      = TagMask | ExtendedTagMask;
-        static const intptr_t FullTagTypeBool      = TagBitTypeOther | ExtendedTagBitBool;
-        static const intptr_t FullTagTypeUndefined = TagBitTypeOther | ExtendedTagBitUndefined;
-        static const intptr_t FullTagTypeNull      = TagBitTypeOther;
-
-#if USE(JSVALUE64)
-        static const int32_t IntegerPayloadShift  = 0;
-#else
-        static const int32_t IntegerPayloadShift  = 1;
-#endif
-        static const int32_t ExtendedPayloadShift = 4;
-
-        static const intptr_t ExtendedPayloadBitBoolValue = 1 << ExtendedPayloadShift;
-
-        static const int32_t signBit = 0x80000000;
-        static ALWAYS_INLINE bool isImmediate(JSValue v)
-        {
-            return rawValue(v) & TagMask;
-        }
-        
-        static ALWAYS_INLINE bool isNumber(JSValue v)
-        {
-            return rawValue(v) & TagTypeNumber;
-        }
-
-        static ALWAYS_INLINE bool isIntegerNumber(JSValue v)
-        {
-#if USE(JSVALUE64)
-            return (rawValue(v) & TagTypeNumber) == TagTypeNumber;
-#else
-            return isNumber(v);
-#endif
-        }
-
-#if USE(JSVALUE64)
-        static ALWAYS_INLINE bool isDouble(JSValue v)
-        {
-            return isNumber(v) && !isIntegerNumber(v);
-        }
-#endif
-
-        static ALWAYS_INLINE bool isPositiveIntegerNumber(JSValue v)
-        {
-            // A single mask to check for the sign bit and the number tag all at once.
-            return (rawValue(v) & (signBit | TagTypeNumber)) == TagTypeNumber;
-        }
-        
-        static ALWAYS_INLINE bool isBoolean(JSValue v)
-        {
-            return (rawValue(v) & FullTagTypeMask) == FullTagTypeBool;
-        }
-        
-        static ALWAYS_INLINE bool isUndefinedOrNull(JSValue v)
-        {
-            // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
-            return (rawValue(v) & ~ExtendedTagBitUndefined) == FullTagTypeNull;
-        }
-
-        static JSValue from(char);
-        static JSValue from(signed char);
-        static JSValue from(unsigned char);
-        static JSValue from(short);
-        static JSValue from(unsigned short);
-        static JSValue from(int);
-        static JSValue from(unsigned);
-        static JSValue from(long);
-        static JSValue from(unsigned long);
-        static JSValue from(long long);
-        static JSValue from(unsigned long long);
-        static JSValue from(double);
-
-        static ALWAYS_INLINE bool isEitherImmediate(JSValue v1, JSValue v2)
-        {
-            return (rawValue(v1) | rawValue(v2)) & TagMask;
-        }
-
-        static ALWAYS_INLINE bool areBothImmediate(JSValue v1, JSValue v2)
-        {
-            return isImmediate(v1) & isImmediate(v2);
-        }
-
-        static ALWAYS_INLINE bool areBothImmediateIntegerNumbers(JSValue v1, JSValue v2)
-        {
-#if USE(JSVALUE64)
-            return (rawValue(v1) & rawValue(v2) & TagTypeNumber) == TagTypeNumber;
-#else
-            return rawValue(v1) & rawValue(v2) & TagTypeNumber;
-#endif
-        }
-
-        static double toDouble(JSValue);
-        static bool toBoolean(JSValue);
-
-        static bool getUInt32(JSValue, uint32_t&);
-        static bool getTruncatedInt32(JSValue, int32_t&);
-        static bool getTruncatedUInt32(JSValue, uint32_t&);
-
-        static int32_t getTruncatedInt32(JSValue);
-        static uint32_t getTruncatedUInt32(JSValue);
-
-        static JSValue trueImmediate();
-        static JSValue falseImmediate();
-        static JSValue undefinedImmediate();
-        static JSValue nullImmediate();
-        static JSValue zeroImmediate();
-        static JSValue oneImmediate();
-
-    private:
-#if USE(JSVALUE64)
-        static const int minImmediateInt = ((-INT_MAX) - 1);
-        static const int maxImmediateInt = INT_MAX;
-#else
-        static const int minImmediateInt = ((-INT_MAX) - 1) >> IntegerPayloadShift;
-        static const int maxImmediateInt = INT_MAX >> IntegerPayloadShift;
-#endif
-        static const unsigned maxImmediateUInt = maxImmediateInt;
-
-        static ALWAYS_INLINE JSValue makeValue(intptr_t integer)
-        {
-            return JSValue::makeImmediate(integer);
-        }
-
-        // With USE(JSVALUE64) we want the argument to be zero extended, so the
-        // integer doesn't interfere with the tag bits in the upper word.  In the default encoding,
-        // if intptr_t id larger then int32_t we sign extend the value through the upper word.
-#if USE(JSVALUE64)
-        static ALWAYS_INLINE JSValue makeInt(uint32_t value)
-#else
-        static ALWAYS_INLINE JSValue makeInt(int32_t value)
-#endif
-        {
-            return makeValue((static_cast<intptr_t>(value) << IntegerPayloadShift) | TagTypeNumber);
-        }
-        
-#if USE(JSVALUE64)
-        static ALWAYS_INLINE JSValue makeDouble(double value)
-        {
-            return makeValue(reinterpretDoubleToIntptr(value) + DoubleEncodeOffset);
-        }
-#endif
-        
-        static ALWAYS_INLINE JSValue makeBool(bool b)
-        {
-            return makeValue((static_cast<intptr_t>(b) << ExtendedPayloadShift) | FullTagTypeBool);
-        }
-        
-        static ALWAYS_INLINE JSValue makeUndefined()
-        {
-            return makeValue(FullTagTypeUndefined);
-        }
-        
-        static ALWAYS_INLINE JSValue makeNull()
-        {
-            return makeValue(FullTagTypeNull);
-        }
-
-        template<typename T>
-        static JSValue fromNumberOutsideIntegerRange(T);
-
-#if USE(JSVALUE64)
-        static ALWAYS_INLINE double doubleValue(JSValue v)
-        {
-            return reinterpretIntptrToDouble(rawValue(v) - DoubleEncodeOffset);
-        }
-#endif
-
-        static ALWAYS_INLINE int32_t intValue(JSValue v)
-        {
-            return static_cast<int32_t>(rawValue(v) >> IntegerPayloadShift);
-        }
-        
-        static ALWAYS_INLINE uint32_t uintValue(JSValue v)
-        {
-            return static_cast<uint32_t>(rawValue(v) >> IntegerPayloadShift);
-        }
-        
-        static ALWAYS_INLINE bool boolValue(JSValue v)
-        {
-            return rawValue(v) & ExtendedPayloadBitBoolValue;
-        }
-        
-        static ALWAYS_INLINE intptr_t rawValue(JSValue v)
-        {
-            return v.immediateValue();
-        }
-    };
-
-    ALWAYS_INLINE JSValue JSImmediate::trueImmediate() { return makeBool(true); }
-    ALWAYS_INLINE JSValue JSImmediate::falseImmediate() { return makeBool(false); }
-    ALWAYS_INLINE JSValue JSImmediate::undefinedImmediate() { return makeUndefined(); }
-    ALWAYS_INLINE JSValue JSImmediate::nullImmediate() { return makeNull(); }
-    ALWAYS_INLINE JSValue JSImmediate::zeroImmediate() { return makeInt(0); }
-    ALWAYS_INLINE JSValue JSImmediate::oneImmediate() { return makeInt(1); }
-
-#if USE(JSVALUE64)
-    inline bool doubleToBoolean(double value)
-    {
-        return value < 0.0 || value > 0.0;
-    }
-
-    ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
-    {
-        ASSERT(isImmediate(v));
-        return isNumber(v) ? isIntegerNumber(v) ? v != zeroImmediate()
-            : doubleToBoolean(doubleValue(v)) : v == trueImmediate();
-    }
-#else
-    ALWAYS_INLINE bool JSImmediate::toBoolean(JSValue v)
-    {
-        ASSERT(isImmediate(v));
-        return isIntegerNumber(v) ? v != zeroImmediate() : v == trueImmediate();
-    }
-#endif
-
-    ALWAYS_INLINE uint32_t JSImmediate::getTruncatedUInt32(JSValue v)
-    {
-        // FIXME: should probably be asserting isPositiveIntegerNumber here.
-        ASSERT(isIntegerNumber(v));
-        return intValue(v);
-    }
-
-#if USE(JSVALUE64)
-    template<typename T>
-    inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T value)
-    {
-        return makeDouble(static_cast<double>(value));
-    }
-#else
-    template<typename T>
-    inline JSValue JSImmediate::fromNumberOutsideIntegerRange(T)
-    {
-        return JSValue();
-    }
-#endif
-
-    ALWAYS_INLINE JSValue JSImmediate::from(char i)
-    {
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(signed char i)
-    {
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(unsigned char i)
-    {
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(short i)
-    {
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(unsigned short i)
-    {
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(int i)
-    {
-#if !USE(JSVALUE64)
-        if ((i < minImmediateInt) | (i > maxImmediateInt))
-            return fromNumberOutsideIntegerRange(i);
-#endif
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(unsigned i)
-    {
-        if (i > maxImmediateUInt)
-            return fromNumberOutsideIntegerRange(i);
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(long i)
-    {
-        if ((i < minImmediateInt) | (i > maxImmediateInt))
-            return fromNumberOutsideIntegerRange(i);
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(unsigned long i)
-    {
-        if (i > maxImmediateUInt)
-            return fromNumberOutsideIntegerRange(i);
-        return makeInt(i);
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(long long i)
-    {
-        if ((i < minImmediateInt) | (i > maxImmediateInt))
-            return JSValue();
-        return makeInt(static_cast<intptr_t>(i));
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(unsigned long long i)
-    {
-        if (i > maxImmediateUInt)
-            return fromNumberOutsideIntegerRange(i);
-        return makeInt(static_cast<intptr_t>(i));
-    }
-
-    ALWAYS_INLINE JSValue JSImmediate::from(double d)
-    {
-        const int intVal = static_cast<int>(d);
-
-        // Check for data loss from conversion to int.
-        if (intVal != d || (!intVal && signbit(d)))
-            return fromNumberOutsideIntegerRange(d);
-
-        return from(intVal);
-    }
-
-    ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(JSValue v)
-    {
-        ASSERT(isIntegerNumber(v));
-        return intValue(v);
-    }
-
-    ALWAYS_INLINE double JSImmediate::toDouble(JSValue v)
-    {
-        ASSERT(isImmediate(v));
-
-        if (isIntegerNumber(v))
-            return intValue(v);
-
-#if USE(JSVALUE64)
-        if (isNumber(v)) {
-            ASSERT(isDouble(v));
-            return doubleValue(v);
-        }
-#else
-        ASSERT(!isNumber(v));
-#endif
-
-        if (rawValue(v) == FullTagTypeUndefined)
-            return nonInlineNaN();
-
-        ASSERT(JSImmediate::isBoolean(v) || (v == JSImmediate::nullImmediate()));
-        return rawValue(v) >> ExtendedPayloadShift;
-    }
-
-    ALWAYS_INLINE bool JSImmediate::getUInt32(JSValue v, uint32_t& i)
-    {
-        i = uintValue(v);
-        return isPositiveIntegerNumber(v);
-    }
-
-    ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(JSValue v, int32_t& i)
-    {
-        i = intValue(v);
-        return isIntegerNumber(v);
-    }
-
-    ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(JSValue v, uint32_t& i)
-    {
-        return getUInt32(v, i);
-    }
-
-    inline JSValue::JSValue(JSNullTag)
-    {
-        *this = JSImmediate::nullImmediate();
-    }
-    
-    inline JSValue::JSValue(JSUndefinedTag)
-    {
-        *this = JSImmediate::undefinedImmediate();
-    }
-
-    inline JSValue::JSValue(JSTrueTag)
-    {
-        *this = JSImmediate::trueImmediate();
-    }
-
-    inline JSValue::JSValue(JSFalseTag)
-    {
-        *this = JSImmediate::falseImmediate();
-    }
-
-    inline bool JSValue::isUndefinedOrNull() const
-    {
-        return JSImmediate::isUndefinedOrNull(asValue());
-    }
-
-    inline bool JSValue::isBoolean() const
-    {
-        return JSImmediate::isBoolean(asValue());
-    }
-
-    inline bool JSValue::isTrue() const
-    {
-        return asValue() == JSImmediate::trueImmediate();
-    }
-
-    inline bool JSValue::isFalse() const
-    {
-        return asValue() == JSImmediate::falseImmediate();
-    }
-
-    inline bool JSValue::getBoolean(bool& v) const
-    {
-        if (JSImmediate::isBoolean(asValue())) {
-            v = JSImmediate::toBoolean(asValue());
-            return true;
-        }
-        
-        return false;
-    }
-
-    inline bool JSValue::getBoolean() const
-    {
-        return asValue() == jsBoolean(true);
-    }
-
-    inline bool JSValue::isCell() const
-    {
-        return !JSImmediate::isImmediate(asValue());
-    }
-
-    inline bool JSValue::isInt32() const
-    {
-        return JSImmediate::isIntegerNumber(asValue());
-    }
-
-    inline int32_t JSValue::asInt32() const
-    {
-        ASSERT(isInt32());
-        return JSImmediate::getTruncatedInt32(asValue());
-    }
-
-    inline bool JSValue::isUInt32() const
-    {
-        return JSImmediate::isPositiveIntegerNumber(asValue());
-    }
-
-    inline uint32_t JSValue::asUInt32() const
-    {
-        ASSERT(isUInt32());
-        return JSImmediate::getTruncatedUInt32(asValue());
-    }
-
-    class JSFastMath {
-    public:
-        static ALWAYS_INLINE bool canDoFastBitwiseOperations(JSValue v1, JSValue v2)
-        {
-            return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
-        }
-
-        static ALWAYS_INLINE JSValue equal(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastBitwiseOperations(v1, v2));
-            return jsBoolean(v1 == v2);
-        }
-
-        static ALWAYS_INLINE JSValue notEqual(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastBitwiseOperations(v1, v2));
-            return jsBoolean(v1 != v2);
-        }
-
-        static ALWAYS_INLINE JSValue andImmediateNumbers(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastBitwiseOperations(v1, v2));
-            return JSImmediate::makeValue(JSImmediate::rawValue(v1) & JSImmediate::rawValue(v2));
-        }
-
-        static ALWAYS_INLINE JSValue xorImmediateNumbers(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastBitwiseOperations(v1, v2));
-            return JSImmediate::makeValue((JSImmediate::rawValue(v1) ^ JSImmediate::rawValue(v2)) | JSImmediate::TagTypeNumber);
-        }
-
-        static ALWAYS_INLINE JSValue orImmediateNumbers(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastBitwiseOperations(v1, v2));
-            return JSImmediate::makeValue(JSImmediate::rawValue(v1) | JSImmediate::rawValue(v2));
-        }
-
-        static ALWAYS_INLINE bool canDoFastRshift(JSValue v1, JSValue v2)
-        {
-            return JSImmediate::areBothImmediateIntegerNumbers(v1, v2);
-        }
-
-        static ALWAYS_INLINE bool canDoFastUrshift(JSValue v1, JSValue v2)
-        {
-            return JSImmediate::areBothImmediateIntegerNumbers(v1, v2) && !(JSImmediate::rawValue(v1) & JSImmediate::signBit);
-        }
-
-        static ALWAYS_INLINE JSValue rightShiftImmediateNumbers(JSValue val, JSValue shift)
-        {
-            ASSERT(canDoFastRshift(val, shift) || canDoFastUrshift(val, shift));
-#if USE(JSVALUE64)
-            return JSImmediate::makeValue(static_cast<intptr_t>(static_cast<uint32_t>(static_cast<int32_t>(JSImmediate::rawValue(val)) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f))) | JSImmediate::TagTypeNumber);
-#else
-            return JSImmediate::makeValue((JSImmediate::rawValue(val) >> ((JSImmediate::rawValue(shift) >> JSImmediate::IntegerPayloadShift) & 0x1f)) | JSImmediate::TagTypeNumber);
-#endif
-        }
-
-        static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v)
-        {
-            // Number is non-negative and an operation involving two of these can't overflow.
-            // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
-            return (JSImmediate::rawValue(v) & (JSImmediate::TagTypeNumber + (JSImmediate::signBit | (JSImmediate::signBit >> 1)))) == JSImmediate::TagTypeNumber;
-        }
-
-        static ALWAYS_INLINE bool canDoFastAdditiveOperations(JSValue v1, JSValue v2)
-        {
-            // Number is non-negative and an operation involving two of these can't overflow.
-            // Checking for allowed negative numbers takes more time than it's worth on SunSpider.
-            return canDoFastAdditiveOperations(v1) && canDoFastAdditiveOperations(v2);
-        }
-
-        static ALWAYS_INLINE JSValue addImmediateNumbers(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastAdditiveOperations(v1, v2));
-            return JSImmediate::makeValue(JSImmediate::rawValue(v1) + JSImmediate::rawValue(v2) - JSImmediate::TagTypeNumber);
-        }
-
-        static ALWAYS_INLINE JSValue subImmediateNumbers(JSValue v1, JSValue v2)
-        {
-            ASSERT(canDoFastAdditiveOperations(v1, v2));
-            return JSImmediate::makeValue(JSImmediate::rawValue(v1) - JSImmediate::rawValue(v2) + JSImmediate::TagTypeNumber);
-        }
-
-        static ALWAYS_INLINE JSValue incImmediateNumber(JSValue v)
-        {
-            ASSERT(canDoFastAdditiveOperations(v));
-            return JSImmediate::makeValue(JSImmediate::rawValue(v) + (1 << JSImmediate::IntegerPayloadShift));
-        }
-
-        static ALWAYS_INLINE JSValue decImmediateNumber(JSValue v)
-        {
-            ASSERT(canDoFastAdditiveOperations(v));
-            return JSImmediate::makeValue(JSImmediate::rawValue(v) - (1 << JSImmediate::IntegerPayloadShift));
-        }
-    };
-
-} // namespace JSC
-
-#endif // !USE(JSVALUE32_64)
-
-#endif // JSImmediate_h
index a1cffbd23de29c7b0e2c8f16559c61f97dc6b62e..fc543f0e82f72f768b8c75645885bcc1f163ace0 100644 (file)
 #include "config.h"
 #include "JSLock.h"
 
-#include "Collector.h"
+#include "Heap.h"
 #include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if USE(PTHREADS)
 #include <pthread.h>
 #endif
 
 namespace JSC {
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+// 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 ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
 
 // Acquire this mutex before accessing lock-related data.
 static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
@@ -65,6 +70,12 @@ JSLock::JSLock(ExecState* exec)
     lock(m_lockBehavior);
 }
 
+JSLock::JSLock(JSGlobalData* globalData)
+    : m_lockBehavior(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
+{
+    lock(m_lockBehavior);
+}
+
 void JSLock::lock(JSLockBehavior lockBehavior)
 {
 #ifdef NDEBUG
@@ -202,7 +213,7 @@ JSLock::DropAllLocks::~DropAllLocks()
     --lockDropDepth;
 }
 
-#else
+#else // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
 
 JSLock::JSLock(ExecState*)
     : m_lockBehavior(SilenceAssertionsOnly)
@@ -249,6 +260,6 @@ JSLock::DropAllLocks::~DropAllLocks()
 {
 }
 
-#endif // USE(MULTIPLE_THREADS)
+#endif // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
 
 } // namespace JSC
index 8b015c4c88d44c9ee56c49658558138e23400d33..7b07b4fb3da5e4e82e005c5244565c9a670bf87f 100644 (file)
@@ -49,12 +49,15 @@ namespace JSC {
     // assertions working, so that clients that use the shared context don't break.
 
     class ExecState;
+    class JSGlobalData;
 
     enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
 
-    class JSLock : public Noncopyable {
+    class JSLock {
+        WTF_MAKE_NONCOPYABLE(JSLock);
     public:
         JSLock(ExecState*);
+        JSLock(JSGlobalData*);
 
         JSLock(JSLockBehavior lockBehavior)
             : m_lockBehavior(lockBehavior)
@@ -87,7 +90,8 @@ namespace JSC {
 
         JSLockBehavior m_lockBehavior;
 
-        class DropAllLocks : public Noncopyable {
+        class DropAllLocks {
+            WTF_MAKE_NONCOPYABLE(DropAllLocks);
         public:
             DropAllLocks(ExecState* exec);
             DropAllLocks(JSLockBehavior);
index f4764e270b90ae409badf21a0f88b2b408dcc0ff..1115dc070b74444e265e48e44e38b3736ee3f014 100644 (file)
@@ -39,91 +39,84 @@ ASSERT_CLASS_FITS_IN_CELL(JSNotAnObject);
 // JSValue methods
 JSValue JSNotAnObject::toPrimitive(ExecState* exec, PreferredPrimitiveType) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
-    return m_exception;
+    ASSERT_UNUSED(exec, exec->hadException());
+    return jsNumber(0);
 }
 
 bool JSNotAnObject::getPrimitiveNumber(ExecState* exec, double&, JSValue&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::toBoolean(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 double JSNotAnObject::toNumber(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return NaN;
 }
 
 UString JSNotAnObject::toString(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return "";
 }
 
-JSObject* JSNotAnObject::toObject(ExecState* exec) const
+JSObject* JSNotAnObject::toObject(ExecState* exec, JSGlobalObject*) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
-    return m_exception;
-}
-
-// Marking
-void JSNotAnObject::markChildren(MarkStack& markStack)
-{
-    JSObject::markChildren(markStack);
-    markStack.append(m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
+    return const_cast<JSNotAnObject*>(this);
 }
 
 // JSObject methods
 bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, const Identifier&, PropertySlot&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::getOwnPropertySlot(ExecState* exec, unsigned, PropertySlot&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
 }
 
 void JSNotAnObject::put(ExecState* exec, unsigned, JSValue)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
 }
 
 bool JSNotAnObject::deleteProperty(ExecState* exec, const Identifier&)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return false;
 }
 
 void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, EnumerationMode)
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
 }
 
 } // namespace JSC
index 339d41f5a2294413c140ae9fdff58347f30fa6fb..4c6806a5f1250eb22c30742c30524a94f87ffb46 100644 (file)
 
 namespace JSC {
 
-    class JSNotAnObjectErrorStub : public JSObject {
-    public:
-        JSNotAnObjectErrorStub(ExecState* exec, bool isNull)
-            : JSObject(exec->globalData().notAnObjectErrorStubStructure)
-            , m_isNull(isNull)
-        {
-        }
-
-        bool isNull() const { return m_isNull; }
-
-    private:
-        virtual bool isNotAnObjectErrorStub() const { return true; }
-
-        bool m_isNull;
-    };
-    
     // This unholy class is used to allow us to avoid multiple exception checks
     // in certain SquirrelFish bytecodes -- effectively it just silently consumes
     // any operations performed on the result of a failed toObject call.
-    class JSNotAnObject : public JSObject {
+    class JSNotAnObject : public JSNonFinalObject {
     public:
-        JSNotAnObject(ExecState* exec, JSNotAnObjectErrorStub* exception)
-            : JSObject(exec->globalData().notAnObjectStructure)
-            , m_exception(exception)
+        JSNotAnObject(ExecState* exec)
+            : JSNonFinalObject(exec->globalData(), exec->globalData().notAnObjectStructure.get())
         {
         }
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
      private:
         
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
 
         // JSValue methods
         virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
@@ -75,10 +58,7 @@ namespace JSC {
         virtual bool toBoolean(ExecState*) const;
         virtual double toNumber(ExecState*) const;
         virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
-
-        // Marking
-        virtual void markChildren(MarkStack&);
+        virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         // JSObject methods
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
@@ -92,8 +72,6 @@ namespace JSC {
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
 
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-
-        JSNotAnObjectErrorStub* m_exception;
     };
 
 } // namespace JSC
diff --git a/runtime/JSNumberCell.cpp b/runtime/JSNumberCell.cpp
deleted file mode 100644 (file)
index a61c751..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2004, 2007, 2008 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
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "JSNumberCell.h"
-
-#if USE(JSVALUE32)
-
-#include "NumberObject.h"
-#include "UString.h"
-
-namespace JSC {
-
-JSValue JSNumberCell::toPrimitive(ExecState*, PreferredPrimitiveType) const
-{
-    return const_cast<JSNumberCell*>(this);
-}
-
-bool JSNumberCell::getPrimitiveNumber(ExecState*, double& number, JSValue& value)
-{
-    number = m_value;
-    value = this;
-    return true;
-}
-
-bool JSNumberCell::toBoolean(ExecState*) const
-{
-    return m_value < 0.0 || m_value > 0.0; // false for NaN
-}
-
-double JSNumberCell::toNumber(ExecState*) const
-{
-  return m_value;
-}
-
-UString JSNumberCell::toString(ExecState*) const
-{
-    return UString::from(m_value);
-}
-
-JSObject* JSNumberCell::toObject(ExecState* exec) const
-{
-    return constructNumber(exec, const_cast<JSNumberCell*>(this));
-}
-
-JSObject* JSNumberCell::toThisObject(ExecState* exec) const
-{
-    return constructNumber(exec, const_cast<JSNumberCell*>(this));
-}
-
-bool JSNumberCell::getUInt32(uint32_t& uint32) const
-{
-    uint32 = static_cast<uint32_t>(m_value);
-    return uint32 == m_value;
-}
-
-JSValue JSNumberCell::getJSNumber()
-{
-    return this;
-}
-
-JSValue jsNumberCell(ExecState* exec, double d)
-{
-    return new (exec) JSNumberCell(exec, d);
-}
-
-JSValue jsNumberCell(JSGlobalData* globalData, double d)
-{
-    return new (globalData) JSNumberCell(globalData, d);
-}
-
-} // namespace JSC
-
-#else // USE(JSVALUE32)
-
-// Keep our exported symbols lists happy.
-namespace JSC {
-
-JSValue jsNumberCell(ExecState*, double);
-
-JSValue jsNumberCell(ExecState*, double)
-{
-    ASSERT_NOT_REACHED();
-    return JSValue();
-}
-
-} // namespace JSC
-
-#endif // USE(JSVALUE32)
diff --git a/runtime/JSNumberCell.h b/runtime/JSNumberCell.h
deleted file mode 100644 (file)
index cdd2d8c..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2007, 2008 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
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef JSNumberCell_h
-#define JSNumberCell_h
-
-#include "CallFrame.h"
-#include "JSCell.h"
-#include "JSImmediate.h"
-#include "Collector.h"
-#include "UString.h"
-#include <stddef.h> // for size_t
-
-namespace JSC {
-
-    extern const double NaN;
-    extern const double Inf;
-
-#if USE(JSVALUE32)
-    JSValue jsNumberCell(ExecState*, double);
-
-    class Identifier;
-    class JSCell;
-    class JSObject;
-    class JSString;
-    class PropertySlot;
-
-    struct ClassInfo;
-    struct Instruction;
-
-    class JSNumberCell : public JSCell {
-        friend class JIT;
-        friend JSValue jsNumberCell(JSGlobalData*, double);
-        friend JSValue jsNumberCell(ExecState*, double);
-
-    public:
-        double value() const { return m_value; }
-
-        virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const;
-        virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
-        virtual bool toBoolean(ExecState*) const;
-        virtual double toNumber(ExecState*) const;
-        virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
-
-        virtual JSObject* toThisObject(ExecState*) const;
-        virtual JSValue getJSNumber();
-
-        void* operator new(size_t size, ExecState* exec)
-        {
-            return exec->heap()->allocateNumber(size);
-        }
-
-        void* operator new(size_t size, JSGlobalData* globalData)
-        {
-            return globalData->heap.allocateNumber(size);
-        }
-
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); }
-
-    private:
-        JSNumberCell(JSGlobalData* globalData, double value)
-            : JSCell(globalData->numberStructure.get())
-            , m_value(value)
-        {
-        }
-
-        JSNumberCell(ExecState* exec, double value)
-            : JSCell(exec->globalData().numberStructure.get())
-            , m_value(value)
-        {
-        }
-
-        virtual bool getUInt32(uint32_t&) const;
-
-        double m_value;
-    };
-
-    JSValue jsNumberCell(JSGlobalData*, double);
-
-    inline bool isNumberCell(JSValue v)
-    {
-        return v.isCell() && v.asCell()->isNumber();
-    }
-
-    inline JSNumberCell* asNumberCell(JSValue v)
-    {
-        ASSERT(isNumberCell(v));
-        return static_cast<JSNumberCell*>(v.asCell());
-    }
-
-    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState* exec, double d)
-    {
-        *this = jsNumberCell(exec, d);
-    }
-
-    inline JSValue::JSValue(ExecState* exec, double d)
-    {
-        JSValue v = JSImmediate::from(d);
-        *this = v ? v : jsNumberCell(exec, d);
-    }
-
-    inline JSValue::JSValue(ExecState* exec, int i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(exec, i);
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(exec, i);
-    }
-
-    inline JSValue::JSValue(ExecState* exec, long i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(exec, i);
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned long i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(exec, i);
-    }
-
-    inline JSValue::JSValue(ExecState* exec, long long i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned long long i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(exec, static_cast<double>(i));
-    }
-
-    inline JSValue::JSValue(JSGlobalData* globalData, double d)
-    {
-        JSValue v = JSImmediate::from(d);
-        *this = v ? v : jsNumberCell(globalData, d);
-    }
-
-    inline JSValue::JSValue(JSGlobalData* globalData, int i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(globalData, i);
-    }
-
-    inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
-    {
-        JSValue v = JSImmediate::from(i);
-        *this = v ? v : jsNumberCell(globalData, i);
-    }
-
-    inline bool JSValue::isDouble() const
-    {
-        return isNumberCell(asValue());
-    }
-
-    inline double JSValue::asDouble() const
-    {
-        return asNumberCell(asValue())->value();
-    }
-
-    inline bool JSValue::isNumber() const
-    {
-        return JSImmediate::isNumber(asValue()) || isDouble();
-    }
-
-    inline double JSValue::uncheckedGetNumber() const
-    {
-        ASSERT(isNumber());
-        return JSImmediate::isImmediate(asValue()) ? JSImmediate::toDouble(asValue()) : asDouble();
-    }
-
-#endif // USE(JSVALUE32)
-
-#if USE(JSVALUE64)
-    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
-    {
-        *this = JSImmediate::fromNumberOutsideIntegerRange(d);
-    }
-
-    inline JSValue::JSValue(ExecState*, double d)
-    {
-        JSValue v = JSImmediate::from(d);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(ExecState*, int i)
-    {
-        JSValue v = JSImmediate::from(i);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(ExecState*, unsigned i)
-    {
-        JSValue v = JSImmediate::from(i);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(ExecState*, long i)
-    {
-        JSValue v = JSImmediate::from(i);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(ExecState*, unsigned long i)
-    {
-        JSValue v = JSImmediate::from(i);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(ExecState*, long long i)
-    {
-        JSValue v = JSImmediate::from(static_cast<double>(i));
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(ExecState*, unsigned long long i)
-    {
-        JSValue v = JSImmediate::from(static_cast<double>(i));
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(JSGlobalData*, double d)
-    {
-        JSValue v = JSImmediate::from(d);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(JSGlobalData*, int i)
-    {
-        JSValue v = JSImmediate::from(i);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline JSValue::JSValue(JSGlobalData*, unsigned i)
-    {
-        JSValue v = JSImmediate::from(i);
-        ASSERT(v);
-        *this = v;
-    }
-
-    inline bool JSValue::isDouble() const
-    {
-        return JSImmediate::isDouble(asValue());
-    }
-
-    inline double JSValue::asDouble() const
-    {
-        return JSImmediate::doubleValue(asValue());
-    }
-
-    inline bool JSValue::isNumber() const
-    {
-        return JSImmediate::isNumber(asValue());
-    }
-
-    inline double JSValue::uncheckedGetNumber() const
-    {
-        ASSERT(isNumber());
-        return JSImmediate::toDouble(asValue());
-    }
-
-#endif // USE(JSVALUE64)
-
-#if USE(JSVALUE32) || USE(JSVALUE64)
-
-    inline JSValue::JSValue(ExecState*, char i)
-    {
-        ASSERT(JSImmediate::from(i));
-        *this = JSImmediate::from(i);
-    }
-
-    inline JSValue::JSValue(ExecState*, unsigned char i)
-    {
-        ASSERT(JSImmediate::from(i));
-        *this = JSImmediate::from(i);
-    }
-
-    inline JSValue::JSValue(ExecState*, short i)
-    {
-        ASSERT(JSImmediate::from(i));
-        *this = JSImmediate::from(i);
-    }
-
-    inline JSValue::JSValue(ExecState*, unsigned short i)
-    {
-        ASSERT(JSImmediate::from(i));
-        *this = JSImmediate::from(i);
-    }
-
-    inline JSValue jsNaN(ExecState* exec)
-    {
-        return jsNumber(exec, NaN);
-    }
-
-    inline JSValue jsNaN(JSGlobalData* globalData)
-    {
-        return jsNumber(globalData, NaN);
-    }
-
-    // --- JSValue inlines ----------------------------
-
-    ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
-    {
-        return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
-    }
-
-    inline bool JSValue::getNumber(double &result) const
-    {
-        if (isInt32())
-            result = asInt32();
-        else if (LIKELY(isDouble()))
-            result = asDouble();
-        else {
-            ASSERT(!isNumber());
-            return false;
-        }
-        return true;
-    }
-
-#endif // USE(JSVALUE32) || USE(JSVALUE64)
-
-} // namespace JSC
-
-#endif // JSNumberCell_h
index f6c6b5f9a7260aa39f5d9a840b66c6c61b951fe8..8d261a20b1d60fe8fa77b24f4a600350e91a04e9 100644 (file)
 #include "Error.h"
 #include "ExceptionHelpers.h"
 #include "JSArray.h"
+#include "JSGlobalObject.h"
 #include "LiteralParser.h"
+#include "Local.h"
+#include "LocalScope.h"
 #include "Lookup.h"
 #include "PropertyNameArray.h"
-#include "StringBuilder.h"
+#include "UStringBuilder.h"
+#include "UStringConcatenate.h"
 #include <wtf/MathExtras.h>
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSONObject);
 
-static JSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState*);
+static EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*);
 
 }
 
@@ -49,6 +53,12 @@ static JSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState*, JSObject*, JSVal
 
 namespace JSC {
 
+JSONObject::JSONObject(JSGlobalObject* globalObject, Structure* structure)
+    : JSObjectWithGlobalObject(globalObject, structure)
+{
+    ASSERT(inherits(&s_info));
+}
+
 // PropertyNameForFunctionCall objects must be on the stack, since the JSValue that they create is not marked.
 class PropertyNameForFunctionCall {
 public:
@@ -63,25 +73,25 @@ private:
     mutable JSValue m_value;
 };
 
-class Stringifier : public Noncopyable {
+class Stringifier {
+    WTF_MAKE_NONCOPYABLE(Stringifier);
 public:
-    Stringifier(ExecState*, JSValue replacer, JSValue space);
-    ~Stringifier();
-    JSValue stringify(JSValue);
+    Stringifier(ExecState*, const Local<Unknown>& replacer, const Local<Unknown>& space);
+    Local<Unknown> stringify(Handle<Unknown>);
 
-    void markAggregate(MarkStack&);
+    void visitAggregate(SlotVisitor&);
 
 private:
     class Holder {
     public:
-        Holder(JSObject*);
+        Holder(JSGlobalData&, JSObject*);
 
-        JSObject* object() const { return m_object; }
+        JSObject* object() const { return m_object.get(); }
 
-        bool appendNextProperty(Stringifier&, StringBuilder&);
+        bool appendNextProperty(Stringifier&, UStringBuilder&);
 
     private:
-        JSObject* const m_object;
+        Local<JSObject> m_object;
         const bool m_isArray;
         bool m_isJSArray;
         unsigned m_index;
@@ -91,28 +101,26 @@ private:
 
     friend class Holder;
 
-    static void appendQuotedString(StringBuilder&, const UString&);
+    static void appendQuotedString(UStringBuilder&, const UString&);
 
     JSValue toJSON(JSValue, const PropertyNameForFunctionCall&);
 
     enum StringifyResult { StringifyFailed, StringifySucceeded, StringifyFailedDueToUndefinedValue };
-    StringifyResult appendStringifiedValue(StringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&);
+    StringifyResult appendStringifiedValue(UStringBuilder&, JSValue, JSObject* holder, const PropertyNameForFunctionCall&);
 
     bool willIndent() const;
     void indent();
     void unindent();
-    void startNewLine(StringBuilder&) const;
+    void startNewLine(UStringBuilder&) const;
 
-    Stringifier* const m_nextStringifierToMark;
     ExecState* const m_exec;
-    const JSValue m_replacer;
+    const Local<Unknown> m_replacer;
     bool m_usingArrayReplacer;
     PropertyNameArray m_arrayReplacerPropertyNames;
     CallType m_replacerCallType;
     CallData m_replacerCallData;
     const UString m_gap;
 
-    HashSet<JSObject*> m_holderCycleDetector;
     Vector<Holder, 16> m_holderStack;
     UString m_repeatedGap;
     UString m_indent;
@@ -125,11 +133,11 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
     if (!value.isObject())
         return value;
     JSObject* object = asObject(value);
-    if (object->inherits(&NumberObject::info))
-        return jsNumber(exec, object->toNumber(exec));
-    if (object->inherits(&StringObject::info))
+    if (object->inherits(&NumberObject::s_info))
+        return jsNumber(object->toNumber(exec));
+    if (object->inherits(&StringObject::s_info))
         return jsString(exec, object->toString(exec));
-    if (object->inherits(&BooleanObject::info))
+    if (object->inherits(&BooleanObject::s_info))
         return object->toPrimitive(exec);
     return value;
 }
@@ -157,8 +165,8 @@ static inline UString gap(ExecState* exec, JSValue space)
 
     // If the space value is a string, use it as the gap string, otherwise use no gap string.
     UString spaces = space.getString(exec);
-    if (spaces.size() > maxGapLength) {
-        spaces = spaces.substr(0, maxGapLength);
+    if (spaces.length() > maxGapLength) {
+        spaces = spaces.substringSharingImpl(0, maxGapLength);
     }
     return spaces;
 }
@@ -182,30 +190,27 @@ JSValue PropertyNameForFunctionCall::value(ExecState* exec) const
         if (m_identifier)
             m_value = jsString(exec, m_identifier->ustring());
         else
-            m_value = jsNumber(exec, m_number);
+            m_value = jsNumber(m_number);
     }
     return m_value;
 }
 
 // ------------------------------ Stringifier --------------------------------
 
-Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
-    : m_nextStringifierToMark(exec->globalData().firstStringifierToMark)
-    , m_exec(exec)
+Stringifier::Stringifier(ExecState* exec, const Local<Unknown>& replacer, const Local<Unknown>& space)
+    : m_exec(exec)
     , m_replacer(replacer)
     , m_usingArrayReplacer(false)
     , m_arrayReplacerPropertyNames(exec)
     , m_replacerCallType(CallTypeNone)
-    , m_gap(gap(exec, space))
+    , m_gap(gap(exec, space.get()))
 {
-    exec->globalData().firstStringifierToMark = this;
-
     if (!m_replacer.isObject())
         return;
 
-    if (asObject(m_replacer)->inherits(&JSArray::info)) {
+    if (m_replacer.asObject()->inherits(&JSArray::s_info)) {
         m_usingArrayReplacer = true;
-        JSObject* array = asObject(m_replacer);
+        Handle<JSObject> array = m_replacer.asObject();
         unsigned length = array->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
         for (unsigned i = 0; i < length; ++i) {
             JSValue name = array->get(exec, i);
@@ -225,7 +230,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
             }
 
             if (name.isObject()) {
-                if (!asObject(name)->inherits(&NumberObject::info) && !asObject(name)->inherits(&StringObject::info))
+                if (!asObject(name)->inherits(&NumberObject::s_info) && !asObject(name)->inherits(&StringObject::s_info))
                     continue;
                 propertyName = name.toString(exec);
                 if (exec->hadException())
@@ -236,52 +241,34 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
         return;
     }
 
-    m_replacerCallType = asObject(m_replacer)->getCallData(m_replacerCallData);
-}
-
-Stringifier::~Stringifier()
-{
-    ASSERT(m_exec->globalData().firstStringifierToMark == this);
-    m_exec->globalData().firstStringifierToMark = m_nextStringifierToMark;
+    m_replacerCallType = m_replacer.asObject()->getCallData(m_replacerCallData);
 }
 
-void Stringifier::markAggregate(MarkStack& markStack)
-{
-    for (Stringifier* stringifier = this; stringifier; stringifier = stringifier->m_nextStringifierToMark) {
-        size_t size = m_holderStack.size();
-        for (size_t i = 0; i < size; ++i)
-            markStack.append(m_holderStack[i].object());
-    }
-}
-
-JSValue Stringifier::stringify(JSValue value)
+Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
 {
     JSObject* object = constructEmptyObject(m_exec);
     if (m_exec->hadException())
-        return jsNull();
+        return Local<Unknown>(m_exec->globalData(), jsNull());
 
     PropertyNameForFunctionCall emptyPropertyName(m_exec->globalData().propertyNames->emptyIdentifier);
-    object->putDirect(m_exec->globalData().propertyNames->emptyIdentifier, value);
+    object->putDirect(m_exec->globalData(), m_exec->globalData().propertyNames->emptyIdentifier, value.get());
 
-    StringBuilder result;
-    if (appendStringifiedValue(result, value, object, emptyPropertyName) != StringifySucceeded)
-        return jsUndefined();
+    UStringBuilder result;
+    if (appendStringifiedValue(result, value.get(), object, emptyPropertyName) != StringifySucceeded)
+        return Local<Unknown>(m_exec->globalData(), jsUndefined());
     if (m_exec->hadException())
-        return jsNull();
+        return Local<Unknown>(m_exec->globalData(), jsNull());
 
-    return jsString(m_exec, result.build());
+    return Local<Unknown>(m_exec->globalData(), jsString(m_exec, result.toUString()));
 }
 
-void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value)
+void Stringifier::appendQuotedString(UStringBuilder& builder, const UString& value)
 {
-    int length = value.size();
-
-    // String length plus 2 for quote marks plus 8 so we can accomodate a few escaped characters.
-    builder.reserveCapacity(builder.size() + length + 2 + 8);
+    int length = value.length();
 
     builder.append('"');
 
-    const UChar* data = value.data();
+    const UChar* data = value.characters();
     for (int i = 0; i < length; ++i) {
         int start = i;
         while (i < length && (data[i] > 0x1F && data[i] != '"' && data[i] != '\\'))
@@ -322,7 +309,7 @@ void Stringifier::appendQuotedString(StringBuilder& builder, const UString& valu
                 static const char hexDigits[] = "0123456789abcdef";
                 UChar ch = data[i];
                 UChar hex[] = { '\\', 'u', hexDigits[(ch >> 12) & 0xF], hexDigits[(ch >> 8) & 0xF], hexDigits[(ch >> 4) & 0xF], hexDigits[ch & 0xF] };
-                builder.append(hex, sizeof(hex) / sizeof(UChar));
+                builder.append(hex, WTF_ARRAY_LENGTH(hex));
                 break;
         }
     }
@@ -350,11 +337,11 @@ inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionC
         return value;
 
     JSValue list[] = { propertyName.value(m_exec) };
-    ArgList args(list, sizeof(list) / sizeof(JSValue));
+    ArgList args(list, WTF_ARRAY_LENGTH(list));
     return call(m_exec, object, callType, callData, value, args);
 }
 
-Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName)
+Stringifier::StringifyResult Stringifier::appendStringifiedValue(UStringBuilder& builder, JSValue value, JSObject* holder, const PropertyNameForFunctionCall& propertyName)
 {
     // Call the toJSON function.
     value = toJSON(value, propertyName);
@@ -364,13 +351,13 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
     // Call the replacer function.
     if (m_replacerCallType != CallTypeNone) {
         JSValue list[] = { propertyName.value(m_exec), value };
-        ArgList args(list, sizeof(list) / sizeof(JSValue));
-        value = call(m_exec, m_replacer, m_replacerCallType, m_replacerCallData, holder, args);
+        ArgList args(list, WTF_ARRAY_LENGTH(list));
+        value = call(m_exec, m_replacer.get(), m_replacerCallType, m_replacerCallData, holder, args);
         if (m_exec->hadException())
             return StringifyFailed;
     }
 
-    if (value.isUndefined() && !holder->inherits(&JSArray::info))
+    if (value.isUndefined() && !holder->inherits(&JSArray::s_info))
         return StringifyFailedDueToUndefinedValue;
 
     if (value.isNull()) {
@@ -399,7 +386,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
         if (!isfinite(numericValue))
             builder.append("null");
         else
-            builder.append(UString::from(numericValue));
+            builder.append(UString::number(numericValue));
         return StringifySucceeded;
     }
 
@@ -410,7 +397,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
 
     CallData callData;
     if (object->getCallData(callData) != CallTypeNone) {
-        if (holder->inherits(&JSArray::info)) {
+        if (holder->inherits(&JSArray::s_info)) {
             builder.append("null");
             return StringifySucceeded;
         }
@@ -418,12 +405,14 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
     }
 
     // Handle cycle detection, and put the holder on the stack.
-    if (!m_holderCycleDetector.add(object).second) {
-        throwError(m_exec, TypeError, "JSON.stringify cannot serialize cyclic structures.");
-        return StringifyFailed;
+    for (unsigned i = 0; i < m_holderStack.size(); i++) {
+        if (m_holderStack[i].object() == object) {
+            throwError(m_exec, createTypeError(m_exec, "JSON.stringify cannot serialize cyclic structures."));
+            return StringifyFailed;
+        }
     }
     bool holderStackWasEmpty = m_holderStack.isEmpty();
-    m_holderStack.append(object);
+    m_holderStack.append(Holder(m_exec->globalData(), object));
     if (!holderStackWasEmpty)
         return StringifySucceeded;
 
@@ -437,13 +426,12 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
                 return StringifyFailed;
             if (!--tickCount) {
                 if (localTimeoutChecker.didTimeOut(m_exec)) {
-                    m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+                    throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
                     return StringifyFailed;
                 }
                 tickCount = localTimeoutChecker.ticksUntilNextCheck();
             }
         }
-        m_holderCycleDetector.remove(m_holderStack.last().object());
         m_holderStack.removeLast();
     } while (!m_holderStack.isEmpty());
     return StringifySucceeded;
@@ -457,20 +445,20 @@ inline bool Stringifier::willIndent() const
 inline void Stringifier::indent()
 {
     // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent.
-    unsigned newSize = m_indent.size() + m_gap.size();
-    if (newSize > m_repeatedGap.size())
-        m_repeatedGap = makeString(m_repeatedGap, m_gap);
-    ASSERT(newSize <= m_repeatedGap.size());
-    m_indent = m_repeatedGap.substr(0, newSize);
+    unsigned newSize = m_indent.length() + m_gap.length();
+    if (newSize > m_repeatedGap.length())
+        m_repeatedGap = makeUString(m_repeatedGap, m_gap);
+    ASSERT(newSize <= m_repeatedGap.length());
+    m_indent = m_repeatedGap.substringSharingImpl(0, newSize);
 }
 
 inline void Stringifier::unindent()
 {
-    ASSERT(m_indent.size() >= m_gap.size());
-    m_indent = m_repeatedGap.substr(0, m_indent.size() - m_gap.size());
+    ASSERT(m_indent.length() >= m_gap.length());
+    m_indent = m_repeatedGap.substringSharingImpl(0, m_indent.length() - m_gap.length());
 }
 
-inline void Stringifier::startNewLine(StringBuilder& builder) const
+inline void Stringifier::startNewLine(UStringBuilder& builder) const
 {
     if (m_gap.isEmpty())
         return;
@@ -478,14 +466,14 @@ inline void Stringifier::startNewLine(StringBuilder& builder) const
     builder.append(m_indent);
 }
 
-inline Stringifier::Holder::Holder(JSObject* object)
-    : m_object(object)
-    , m_isArray(object->inherits(&JSArray::info))
+inline Stringifier::Holder::Holder(JSGlobalData& globalData, JSObject* object)
+    : m_object(globalData, object)
+    , m_isArray(object->inherits(&JSArray::s_info))
     , m_index(0)
 {
 }
 
-bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBuilder& builder)
+bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBuilder& builder)
 {
     ASSERT(m_index <= m_size);
 
@@ -494,7 +482,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
     // First time through, initialize.
     if (!m_index) {
         if (m_isArray) {
-            m_isJSArray = isJSArray(&exec->globalData(), m_object);
+            m_isJSArray = isJSArray(&exec->globalData(), m_object.get());
             m_size = m_object->get(exec, exec->globalData().propertyNames->length).toUInt32(exec);
             builder.append('[');
         } else {
@@ -514,7 +502,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
     // Last time through, finish up and return false.
     if (m_index == m_size) {
         stringifier.unindent();
-        if (m_size && builder[builder.size() - 1] != '{')
+        if (m_size && builder[builder.length() - 1] != '{')
             stringifier.startNewLine(builder);
         builder.append(m_isArray ? ']' : '}');
         return false;
@@ -527,10 +515,10 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
     if (m_isArray) {
         // Get the value.
         JSValue value;
-        if (m_isJSArray && asArray(m_object)->canGetIndex(index))
-            value = asArray(m_object)->getIndex(index);
+        if (m_isJSArray && asArray(m_object.get())->canGetIndex(index))
+            value = asArray(m_object.get())->getIndex(index);
         else {
-            PropertySlot slot(m_object);
+            PropertySlot slot(m_object.get());
             if (!m_object->getOwnPropertySlot(exec, index, slot))
                 slot.setUndefined();
             if (exec->hadException())
@@ -544,10 +532,10 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
         stringifier.startNewLine(builder);
 
         // Append the stringified value.
-        stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object, index);
+        stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), index);
     } else {
         // Get the value.
-        PropertySlot slot(m_object);
+        PropertySlot slot(m_object.get());
         Identifier& propertyName = m_propertyNames->propertyNameVector()[index];
         if (!m_object->getOwnPropertySlot(exec, propertyName, slot))
             return true;
@@ -555,7 +543,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
         if (exec->hadException())
             return false;
 
-        rollBackPoint = builder.size();
+        rollBackPoint = builder.length();
 
         // Append the separator string.
         if (builder[rollBackPoint - 1] != '{')
@@ -569,7 +557,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
             builder.append(' ');
 
         // Append the stringified value.
-        stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object, propertyName);
+        stringifyResult = stringifier.appendStringifiedValue(builder, value, m_object.get(), propertyName);
     }
 
     // From this point on, no access to the this pointer or to any members, because the
@@ -595,12 +583,12 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui
 
 // ------------------------------ JSONObject --------------------------------
 
-const ClassInfo JSONObject::info = { "JSON", 0, 0, ExecState::jsonTable };
+const ClassInfo JSONObject::s_info = { "JSON", &JSObjectWithGlobalObject::s_info, 0, ExecState::jsonTable };
 
 /* Source for JSONObject.lut.h
 @begin jsonTable
-  parse         JSONProtoFuncParse             DontEnum|Function 1
-  stringify     JSONProtoFuncStringify         DontEnum|Function 1
+  parse         JSONProtoFuncParse             DontEnum|Function 2
+  stringify     JSONProtoFuncStringify         DontEnum|Function 3
 @end
 */
 
@@ -616,16 +604,11 @@ bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro
     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
 }
 
-void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier)
-{
-    stringifier->markAggregate(markStack);
-}
-
 class Walker {
 public:
-    Walker(ExecState* exec, JSObject* function, CallType callType, CallData callData)
+    Walker(ExecState* exec, Handle<JSObject> function, CallType callType, CallData callData)
         : m_exec(exec)
-        , m_function(function)
+        , m_function(exec->globalData(), function)
         , m_callType(callType)
         , m_callData(callData)
     {
@@ -636,13 +619,13 @@ private:
     {
         JSValue args[] = { property, unfiltered };
         ArgList argList(args, 2);
-        return call(m_exec, m_function, m_callType, m_callData, thisObj, argList);
+        return call(m_exec, m_function.get(), m_callType, m_callData, thisObj, argList);
     }
 
     friend class Holder;
 
     ExecState* m_exec;
-    JSObject* m_function;
+    Local<JSObject> m_function;
     CallType m_callType;
     CallData m_callData;
 };
@@ -656,8 +639,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
 {
     Vector<PropertyNameArray, 16> propertyStack;
     Vector<uint32_t, 16> indexStack;
-    Vector<JSObject*, 16> objectStack;
-    Vector<JSArray*, 16> arrayStack;
+    LocalStack<JSObject, 16> objectStack(m_exec->globalData());
+    LocalStack<JSArray, 16> arrayStack(m_exec->globalData());
     
     Vector<WalkerState, 16> stateStack;
     WalkerState state = StateUnknown;
@@ -672,32 +655,28 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::info));
-                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) {
-                    m_exec->setException(createStackOverflowError(m_exec));
-                    return jsUndefined();
-                }
+                ASSERT(isJSArray(&m_exec->globalData(), asObject(inValue)) || asObject(inValue)->inherits(&JSArray::s_info));
+                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
+                    return throwError(m_exec, createStackOverflowError(m_exec));
 
                 JSArray* array = asArray(inValue);
-                arrayStack.append(array);
+                arrayStack.push(array);
                 indexStack.append(0);
                 // fallthrough
             }
             arrayStartVisitMember:
             case ArrayStartVisitMember: {
                 if (!--tickCount) {
-                    if (localTimeoutChecker.didTimeOut(m_exec)) {
-                        m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
-                        return jsUndefined();
-                    }
+                    if (localTimeoutChecker.didTimeOut(m_exec))
+                        return throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
                     tickCount = localTimeoutChecker.ticksUntilNextCheck();
                 }
 
-                JSArray* array = arrayStack.last();
+                JSArray* array = arrayStack.peek();
                 uint32_t index = indexStack.last();
                 if (index == array->length()) {
                     outValue = array;
-                    arrayStack.removeLast();
+                    arrayStack.pop();
                     indexStack.removeLast();
                     break;
                 }
@@ -719,13 +698,13 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 // fallthrough
             }
             case ArrayEndVisitMember: {
-                JSArray* array = arrayStack.last();
-                JSValue filteredValue = callReviver(array, jsString(m_exec, UString::from(indexStack.last())), outValue);
+                JSArray* array = arrayStack.peek();
+                JSValue filteredValue = callReviver(array, jsString(m_exec, UString::number(indexStack.last())), outValue);
                 if (filteredValue.isUndefined())
                     array->deleteProperty(m_exec, indexStack.last());
                 else {
                     if (isJSArray(&m_exec->globalData(), array) && array->canSetIndex(indexStack.last()))
-                        array->setIndex(indexStack.last(), filteredValue);
+                        array->setIndex(m_exec->globalData(), indexStack.last(), filteredValue);
                     else
                         array->put(m_exec, indexStack.last(), filteredValue);
                 }
@@ -737,14 +716,12 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             objectStartState:
             case ObjectStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::info));
-                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion) {
-                    m_exec->setException(createStackOverflowError(m_exec));
-                    return jsUndefined();
-                }
+                ASSERT(!isJSArray(&m_exec->globalData(), asObject(inValue)) && !asObject(inValue)->inherits(&JSArray::s_info));
+                if (objectStack.size() + arrayStack.size() > maximumFilterRecursion)
+                    return throwError(m_exec, createStackOverflowError(m_exec));
 
                 JSObject* object = asObject(inValue);
-                objectStack.append(object);
+                objectStack.push(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec));
                 object->getOwnPropertyNames(m_exec, propertyStack.last());
@@ -753,19 +730,17 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             objectStartVisitMember:
             case ObjectStartVisitMember: {
                 if (!--tickCount) {
-                    if (localTimeoutChecker.didTimeOut(m_exec)) {
-                        m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
-                        return jsUndefined();
-                    }
+                    if (localTimeoutChecker.didTimeOut(m_exec))
+                        return throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
                     tickCount = localTimeoutChecker.ticksUntilNextCheck();
                 }
 
-                JSObject* object = objectStack.last();
+                JSObject* object = objectStack.peek();
                 uint32_t index = indexStack.last();
                 PropertyNameArray& properties = propertyStack.last();
                 if (index == properties.size()) {
                     outValue = object;
-                    objectStack.removeLast();
+                    objectStack.pop();
                     indexStack.removeLast();
                     propertyStack.removeLast();
                     break;
@@ -788,7 +763,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 // fallthrough
             }
             case ObjectEndVisitMember: {
-                JSObject* object = objectStack.last();
+                JSObject* object = objectStack.peek();
                 Identifier prop = propertyStack.last()[indexStack.last()];
                 PutPropertySlot slot;
                 JSValue filteredValue = callReviver(object, jsString(m_exec, prop.ustring()), outValue);
@@ -808,7 +783,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     break;
                 }
                 JSObject* object = asObject(inValue);
-                if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info))
+                if (isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::s_info))
                     goto arrayStartState;
                 goto objectStartState;
         }
@@ -819,10 +794,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
         stateStack.removeLast();
 
         if (!--tickCount) {
-            if (localTimeoutChecker.didTimeOut(m_exec)) {
-                m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
-                return jsUndefined();
-            }
+            if (localTimeoutChecker.didTimeOut(m_exec))
+                return throwError(m_exec, createInterruptedExecutionException(&m_exec->globalData()));
             tickCount = localTimeoutChecker.ticksUntilNextCheck();
         }
     }
@@ -833,45 +806,48 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
 }
 
 // ECMA-262 v5 15.12.2
-JSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
 {
-    if (args.isEmpty())
-        return throwError(exec, GeneralError, "JSON.parse requires at least one parameter");
-    JSValue value = args.at(0);
+    if (!exec->argumentCount())
+        return throwVMError(exec, createError(exec, "JSON.parse requires at least one parameter"));
+    JSValue value = exec->argument(0);
     UString source = value.toString(exec);
     if (exec->hadException())
-        return jsNull();
-    
-    LiteralParser jsonParser(exec, source, LiteralParser::StrictJSON);
+        return JSValue::encode(jsNull());
+
+    LocalScope scope(exec->globalData());
+    LiteralParser jsonParser(exec, source.characters(), source.length(), LiteralParser::StrictJSON);
     JSValue unfiltered = jsonParser.tryLiteralParse();
     if (!unfiltered)
-        return throwError(exec, SyntaxError, "Unable to parse JSON string");
+        return throwVMError(exec, createSyntaxError(exec, "Unable to parse JSON string"));
     
-    if (args.size() < 2)
-        return unfiltered;
+    if (exec->argumentCount() < 2)
+        return JSValue::encode(unfiltered);
     
-    JSValue function = args.at(1);
+    JSValue function = exec->argument(1);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
-        return unfiltered;
-    return Walker(exec, asObject(function), callType, callData).walk(unfiltered);
+        return JSValue::encode(unfiltered);
+    return JSValue::encode(Walker(exec, Local<JSObject>(exec->globalData(), asObject(function)), callType, callData).walk(unfiltered));
 }
 
 // ECMA-262 v5 15.12.3
-JSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec)
 {
-    if (args.isEmpty())
-        return throwError(exec, GeneralError, "No input to stringify");
-    JSValue value = args.at(0);
-    JSValue replacer = args.at(1);
-    JSValue space = args.at(2);
-    return Stringifier(exec, replacer, space).stringify(value);
+    if (!exec->argumentCount())
+        return throwVMError(exec, createError(exec, "No input to stringify"));
+    LocalScope scope(exec->globalData());
+    Local<Unknown> value(exec->globalData(), exec->argument(0));
+    Local<Unknown> replacer(exec->globalData(), exec->argument(1));
+    Local<Unknown> space(exec->globalData(), exec->argument(2));
+    return JSValue::encode(Stringifier(exec, replacer, space).stringify(value).get());
 }
 
 UString JSONStringify(ExecState* exec, JSValue value, unsigned indent)
 {
-    JSValue result = Stringifier(exec, jsNull(), jsNumber(exec, indent)).stringify(value);
+    LocalScope scope(exec->globalData());
+    Local<Unknown> result = Stringifier(exec, Local<Unknown>(exec->globalData(), jsNull()), Local<Unknown>(exec->globalData(), jsNumber(indent))).stringify(Local<Unknown>(exec->globalData(), value));
     if (result.isUndefinedOrNull())
         return UString();
     return result.getString(exec);
index 7a9e0a48b90e035647b9686e053245a1325240c5..b7733205c808be2d783fd7c7e82e891f4dceb1fb 100644 (file)
 #ifndef JSONObject_h
 #define JSONObject_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
 
     class Stringifier;
 
-    class JSONObject : public JSObject {
+    class JSONObject : public JSObjectWithGlobalObject {
     public:
-        JSONObject(NonNullPassRefPtr<Structure> structure)
-            : JSObject(structure)
-        {
-        }
+        JSONObject(JSGlobalObject*, Structure*);
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
-
-        static void markStringifiers(MarkStack&, Stringifier*);
+        
+        static const ClassInfo s_info;
 
     protected:
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
@@ -53,8 +50,6 @@ namespace JSC {
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
     };
 
     UString JSONStringify(ExecState* exec, JSValue value, unsigned indent);
index 61d3bb145767b676a9a0aa280fbcfec663c96b78..05ec555b60d72dfb84c6636cde007a59f3ff286a 100644 (file)
@@ -27,6 +27,7 @@
 #include "DatePrototype.h"
 #include "ErrorConstructor.h"
 #include "GetterSetter.h"
+#include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "NativeErrorConstructor.h"
 #include "ObjectPrototype.h"
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
+ASSERT_CLASS_FITS_IN_CELL(JSNonFinalObject);
+ASSERT_CLASS_FITS_IN_CELL(JSFinalObject);
+
+const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
+
+const ClassInfo JSObject::s_info = { "Object", 0, 0, 0 };
 
 static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
@@ -61,26 +68,26 @@ static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* class
     }
 }
 
-void JSObject::markChildren(MarkStack& markStack)
+void JSObject::visitChildren(SlotVisitor& visitor)
 {
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
 #ifndef NDEBUG
-    bool wasCheckingForDefaultMarkViolation = markStack.m_isCheckingForDefaultMarkViolation;
-    markStack.m_isCheckingForDefaultMarkViolation = false;
+    bool wasCheckingForDefaultMarkViolation = visitor.m_isCheckingForDefaultMarkViolation;
+    visitor.m_isCheckingForDefaultMarkViolation = false;
 #endif
 
-    markChildrenDirect(markStack);
+    visitChildrenDirect(visitor);
 
 #ifndef NDEBUG
-    markStack.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
+    visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
 #endif
 }
 
 UString JSObject::className() const
 {
     const ClassInfo* info = classInfo();
-    if (info)
-        return info->className;
-    return "Object";
+    ASSERT(info);
+    return info->className;
 }
 
 bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
@@ -90,7 +97,7 @@ bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Proper
 
 static void throwSetterError(ExecState* exec)
 {
-    throwError(exec, TypeError, "setting a property that has only a getter");
+    throwError(exec, createTypeError(exec, "setting a property that has only a getter"));
 }
 
 // ECMA 8.6.2.2
@@ -103,18 +110,8 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu
         // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
         if (!value.isObject() && !value.isNull())
             return;
-
-        JSValue nextPrototypeValue = value;
-        while (nextPrototypeValue && nextPrototypeValue.isObject()) {
-            JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject();
-            if (nextPrototype == this) {
-                throwError(exec, GeneralError, "cyclic __proto__ value");
-                return;
-            }
-            nextPrototypeValue = nextPrototype->prototype();
-        }
-
-        setPrototype(value);
+        if (!setPrototypeWithCycleCheck(exec->globalData(), value))
+            throwError(exec, createError(exec, "cyclic __proto__ value"));
         return;
     }
 
@@ -123,18 +120,22 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu
     for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) {
         prototype = obj->prototype();
         if (prototype.isNull()) {
-            putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
+            if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
+                throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
             return;
         }
     }
     
     unsigned attributes;
     JSCell* specificValue;
-    if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly)
+    if ((m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) {
+        if (slot.isStrictMode())
+            throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
         return;
+    }
 
     for (JSObject* obj = this; ; obj = asObject(prototype)) {
-        if (JSValue gs = obj->getDirect(propertyName)) {
+        if (JSValue gs = obj->getDirect(exec->globalData(), propertyName)) {
             if (gs.isGetterSetter()) {
                 JSObject* setterFunc = asGetterSetter(gs)->setter();        
                 if (!setterFunc) {
@@ -160,7 +161,8 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu
             break;
     }
 
-    putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
+    if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
+        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
     return;
 }
 
@@ -170,6 +172,21 @@ void JSObject::put(ExecState* exec, unsigned propertyName, JSValue value)
     put(exec, Identifier::from(exec, propertyName), value, slot);
 }
 
+void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+{
+    putDirectInternal(*globalData, propertyName, value, attributes, checkReadOnly, slot);
+}
+
+void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
+{
+    putDirectInternal(*globalData, propertyName, value, attributes);
+}
+
+void JSObject::putWithAttributes(JSGlobalData* globalData, unsigned propertyName, JSValue value, unsigned attributes)
+{
+    putWithAttributes(globalData, Identifier::from(globalData, propertyName), value, attributes);
+}
+
 void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
 {
     putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot);
@@ -202,10 +219,10 @@ bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
 {
     unsigned attributes;
     JSCell* specificValue;
-    if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) {
+    if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound) {
         if ((attributes & DontDelete))
             return false;
-        removeDirect(propertyName);
+        removeDirect(exec->globalData(), propertyName);
         return true;
     }
 
@@ -233,7 +250,7 @@ static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSO
 {
     JSValue function = object->get(exec, propertyName);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
         return exec->exception();
 
@@ -280,7 +297,7 @@ JSValue JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) con
 
     ASSERT(!exec->hadException());
 
-    return throwError(exec, TypeError, "No default value");
+    return throwError(exec, createTypeError(exec, "No default value"));
 }
 
 const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const
@@ -296,37 +313,36 @@ const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifi
 
 void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
 {
-    JSValue object = getDirect(propertyName);
+    JSValue object = getDirect(exec->globalData(), propertyName);
     if (object && object.isGetterSetter()) {
         ASSERT(m_structure->hasGetterSetterProperties());
-        asGetterSetter(object)->setGetter(getterFunction);
+        asGetterSetter(object)->setGetter(exec->globalData(), getterFunction);
         return;
     }
 
+    JSGlobalData& globalData = exec->globalData();
     PutPropertySlot slot;
     GetterSetter* getterSetter = new (exec) GetterSetter(exec);
-    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot);
+    putDirectInternal(globalData, propertyName, getterSetter, attributes | Getter, true, slot);
 
     // putDirect will change our Structure if we add a new property. For
     // getters and setters, though, we also need to change our Structure
     // if we override an existing non-getter or non-setter.
     if (slot.type() != PutPropertySlot::NewProperty) {
-        if (!m_structure->isDictionary()) {
-            RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure);
-            setStructure(structure.release());
-        }
+        if (!m_structure->isDictionary())
+            setStructure(exec->globalData(), Structure::getterSetterTransition(globalData, m_structure.get()));
     }
 
     m_structure->setHasGetterSetterProperties(true);
-    getterSetter->setGetter(getterFunction);
+    getterSetter->setGetter(globalData, getterFunction);
 }
 
 void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
 {
-    JSValue object = getDirect(propertyName);
+    JSValue object = getDirect(exec->globalData(), propertyName);
     if (object && object.isGetterSetter()) {
         ASSERT(m_structure->hasGetterSetterProperties());
-        asGetterSetter(object)->setSetter(setterFunction);
+        asGetterSetter(object)->setSetter(exec->globalData(), setterFunction);
         return;
     }
 
@@ -338,21 +354,19 @@ void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSO
     // getters and setters, though, we also need to change our Structure
     // if we override an existing non-getter or non-setter.
     if (slot.type() != PutPropertySlot::NewProperty) {
-        if (!m_structure->isDictionary()) {
-            RefPtr<Structure> structure = Structure::getterSetterTransition(m_structure);
-            setStructure(structure.release());
-        }
+        if (!m_structure->isDictionary())
+            setStructure(exec->globalData(), Structure::getterSetterTransition(exec->globalData(), m_structure.get()));
     }
 
     m_structure->setHasGetterSetterProperties(true);
-    getterSetter->setSetter(setterFunction);
+    getterSetter->setSetter(exec->globalData(), setterFunction);
 }
 
-JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
+JSValue JSObject::lookupGetter(ExecState* exec, const Identifier& propertyName)
 {
     JSObject* object = this;
     while (true) {
-        if (JSValue value = object->getDirect(propertyName)) {
+        if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
             if (!value.isGetterSetter())
                 return jsUndefined();
             JSObject* functionObject = asGetterSetter(value)->getter();
@@ -367,11 +381,11 @@ JSValue JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
     }
 }
 
-JSValue JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
+JSValue JSObject::lookupSetter(ExecState* exec, const Identifier& propertyName)
 {
     JSObject* object = this;
     while (true) {
-        if (JSValue value = object->getDirect(propertyName)) {
+        if (JSValue value = object->getDirect(exec->globalData(), propertyName)) {
             if (!value.isGetterSetter())
                 return jsUndefined();
             JSObject* functionObject = asGetterSetter(value)->setter();
@@ -392,7 +406,7 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto)
         return false;
 
     if (!proto.isObject()) {
-        throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
+        throwError(exec, createTypeError(exec, "instanceof called on an object with an invalid prototype property."));
         return false;
     }
 
@@ -412,10 +426,10 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN
     return descriptor.enumerable();
 }
 
-bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const
+bool JSObject::getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificValue) const
 {
     unsigned attributes;
-    if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound)
+    if (m_structure->get(exec->globalData(), propertyName, attributes, specificValue) != WTF::notFound)
         return true;
 
     // This could be a function within the static table? - should probably
@@ -448,7 +462,7 @@ void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyName
 
 void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
-    m_structure->getPropertyNames(propertyNames, mode);
+    m_structure->getPropertyNames(exec->globalData(), propertyNames, mode);
     getClassPropertyNames(exec, classInfo(), propertyNames, mode);
 }
 
@@ -473,7 +487,7 @@ UString JSObject::toString(ExecState* exec) const
     return primitive.toString(exec);
 }
 
-JSObject* JSObject::toObject(ExecState*) const
+JSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const
 {
     return const_cast<JSObject*>(this);
 }
@@ -483,40 +497,79 @@ JSObject* JSObject::toThisObject(ExecState*) const
     return const_cast<JSObject*>(this);
 }
 
+JSValue JSObject::toStrictThisObject(ExecState*) const
+{
+    return const_cast<JSObject*>(this);
+}
+
 JSObject* JSObject::unwrappedObject()
 {
     return this;
 }
 
-void JSObject::removeDirect(const Identifier& propertyName)
+void JSObject::seal(JSGlobalData& globalData)
+{
+    if (isSealed(globalData))
+        return;
+    preventExtensions(globalData);
+    setStructure(globalData, Structure::sealTransition(globalData, m_structure.get()));
+}
+
+void JSObject::freeze(JSGlobalData& globalData)
+{
+    if (isFrozen(globalData))
+        return;
+    preventExtensions(globalData);
+    setStructure(globalData, Structure::freezeTransition(globalData, m_structure.get()));
+}
+
+void JSObject::preventExtensions(JSGlobalData& globalData)
+{
+    if (isExtensible())
+        setStructure(globalData, Structure::preventExtensionsTransition(globalData, m_structure.get()));
+}
+
+void JSObject::removeDirect(JSGlobalData& globalData, const Identifier& propertyName)
 {
+    if (m_structure->get(globalData, propertyName) == WTF::notFound)
+        return;
+
     size_t offset;
     if (m_structure->isUncacheableDictionary()) {
-        offset = m_structure->removePropertyWithoutTransition(propertyName);
+        offset = m_structure->removePropertyWithoutTransition(globalData, propertyName);
         if (offset != WTF::notFound)
-            putDirectOffset(offset, jsUndefined());
+            putUndefinedAtDirectOffset(offset);
         return;
     }
 
-    RefPtr<Structure> structure = Structure::removePropertyTransition(m_structure, propertyName, offset);
-    setStructure(structure.release());
+    setStructure(globalData, Structure::removePropertyTransition(globalData, m_structure.get(), propertyName, offset));
     if (offset != WTF::notFound)
-        putDirectOffset(offset, jsUndefined());
+        putUndefinedAtDirectOffset(offset);
 }
 
 void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
 {
-    putDirectFunction(Identifier(exec, function->name(exec)), function, attr);
+    putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
+}
+
+void JSObject::putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr)
+{
+    putDirectFunction(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
 }
 
 void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr)
 {
-    putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr);
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
 }
 
-NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location)
+void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr)
 {
-    if (JSObject* getterFunction = asGetterSetter(*location)->getter()) {
+    putDirectFunctionWithoutTransition(exec->globalData(), Identifier(exec, function->name(exec)), function, attr);
+}
+
+NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarrierBase<Unknown>* location)
+{
+    if (JSObject* getterFunction = asGetterSetter(location->get())->getter()) {
         if (!structure()->isDictionary())
             slot.setCacheableGetterSlot(this, getterFunction, offsetForLocation(location));
         else
@@ -525,22 +578,38 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue*
         slot.setUndefined();
 }
 
-Structure* JSObject::createInheritorID()
+Structure* JSObject::createInheritorID(JSGlobalData& globalData)
 {
-    m_inheritorID = JSObject::createStructure(this);
+    m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, this));
+    ASSERT(m_inheritorID->isEmpty());
     return m_inheritorID.get();
 }
 
 void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize)
 {
-    allocatePropertyStorageInline(oldSize, newSize);
+    ASSERT(newSize > oldSize);
+
+    // It's important that this function not rely on m_structure, since
+    // we might be in the middle of a transition.
+    bool wasInline = (oldSize < JSObject::baseExternalStorageCapacity);
+
+    PropertyStorage oldPropertyStorage = m_propertyStorage;
+    PropertyStorage newPropertyStorage = new WriteBarrierBase<Unknown>[newSize];
+
+    for (unsigned i = 0; i < oldSize; ++i)
+       newPropertyStorage[i] = oldPropertyStorage[i];
+
+    if (!wasInline)
+        delete [] oldPropertyStorage;
+
+    m_propertyStorage = newPropertyStorage;
 }
 
-bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor)
+bool JSObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
     unsigned attributes = 0;
     JSCell* cell = 0;
-    size_t offset = m_structure->get(propertyName, attributes, cell);
+    size_t offset = m_structure->get(exec->globalData(), propertyName, attributes, cell);
     if (offset == WTF::notFound)
         return false;
     descriptor.setDescriptor(getDirectOffset(offset), attributes);
@@ -560,10 +629,28 @@ bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& property
     }
 }
 
-static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue)
+static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, const PropertyDescriptor& oldDescriptor)
 {
     if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
-        target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter));
+        if (descriptor.isGenericDescriptor() && oldDescriptor.isAccessorDescriptor()) {
+            GetterSetter* accessor = new (exec) GetterSetter(exec);
+            if (oldDescriptor.getter()) {
+                attributes |= Getter;
+                accessor->setGetter(exec->globalData(), asObject(oldDescriptor.getter()));
+            }
+            if (oldDescriptor.setter()) {
+                attributes |= Setter;
+                accessor->setSetter(exec->globalData(), asObject(oldDescriptor.setter()));
+            }
+            target->putWithAttributes(exec, propertyName, accessor, attributes);
+            return true;
+        }
+        JSValue newValue = jsUndefined();
+        if (descriptor.value())
+            newValue = descriptor.value();
+        else if (oldDescriptor.value())
+            newValue = oldDescriptor.value();
+        target->putWithAttributes(exec, propertyName, newValue, attributes & ~(Getter | Setter));
         return true;
     }
     attributes &= ~ReadOnly;
@@ -580,8 +667,17 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
 {
     // If we have a new property we can just put it on normally
     PropertyDescriptor current;
-    if (!getOwnPropertyDescriptor(exec, propertyName, current))
-        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined());
+    if (!getOwnPropertyDescriptor(exec, propertyName, current)) {
+        // unless extensions are prevented!
+        if (!isExtensible()) {
+            if (throwException)
+                throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible."));
+            return false;
+        }
+        PropertyDescriptor oldDescriptor;
+        oldDescriptor.setValue(jsUndefined());
+        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), oldDescriptor);
+    }
 
     if (descriptor.isEmpty())
         return true;
@@ -593,12 +689,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
     if (!current.configurable()) {
         if (descriptor.configurable()) {
             if (throwException)
-                throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property.");
+                throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property."));
             return false;
         }
         if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
             if (throwException)
-                throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property.");
+                throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property."));
             return false;
         }
     }
@@ -607,7 +703,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
     if (descriptor.isGenericDescriptor()) {
         if (!current.attributesEqual(descriptor)) {
             deleteProperty(exec, propertyName);
-            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
         }
         return true;
     }
@@ -616,11 +712,11 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
     if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
         if (!current.configurable()) {
             if (throwException)
-                throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property.");
+                throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property."));
             return false;
         }
         deleteProperty(exec, propertyName);
-        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined());
+        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
     }
 
     // Changing the value and attributes of an existing property
@@ -628,13 +724,13 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
         if (!current.configurable()) {
             if (!current.writable() && descriptor.writable()) {
                 if (throwException)
-                    throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property.");
+                    throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property."));
                 return false;
             }
             if (!current.writable()) {
                 if (descriptor.value() || !JSValue::strictEqual(exec, current.value(), descriptor.value())) {
                     if (throwException)
-                        throwError(exec, TypeError, "Attempting to change value of a readonly property.");
+                        throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property."));
                     return false;
                 }
             }
@@ -648,32 +744,32 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
             return true;
         }
         deleteProperty(exec, propertyName);
-        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
+        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current);
     }
 
     // Changing the accessor functions of an existing accessor property
     ASSERT(descriptor.isAccessorDescriptor());
     if (!current.configurable()) {
-        if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
+        if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
             if (throwException)
-                throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property.");
+                throwError(exec, createTypeError(exec, "Attempting to change the setter of an unconfigurable property."));
             return false;
         }
-        if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
+        if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
             if (throwException)
-                throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property.");
+                throwError(exec, createTypeError(exec, "Attempting to change the getter of an unconfigurable property."));
             return false;
         }
     }
-    JSValue accessor = getDirect(propertyName);
+    JSValue accessor = getDirect(exec->globalData(), propertyName);
     if (!accessor)
         return false;
     GetterSetter* getterSetter = asGetterSetter(accessor);
     if (current.attributesEqual(descriptor)) {
         if (descriptor.setter())
-            getterSetter->setSetter(asObject(descriptor.setter()));
+            getterSetter->setSetter(exec->globalData(), asObject(descriptor.setter()));
         if (descriptor.getter())
-            getterSetter->setGetter(asObject(descriptor.getter()));
+            getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter()));
         return true;
     }
     deleteProperty(exec, propertyName);
@@ -682,8 +778,13 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
         attrs |= Setter;
     if (descriptor.getter())
         attrs |= Getter;
-    putDirect(propertyName, getterSetter, attrs);
+    putDirect(exec->globalData(), propertyName, getterSetter, attrs);
     return true;
 }
 
+JSObject* throwTypeError(ExecState* exec, const UString& message)
+{
+    return throwError(exec, createTypeError(exec, message));
+}
+
 } // namespace JSC
index 6824c23fea7c39a79aa1e518febfaaf724ea73e4..60def6e9cea26a06dac76a6f50a645474aed69ca 100644 (file)
@@ -29,7 +29,6 @@
 #include "Completion.h"
 #include "CallFrame.h"
 #include "JSCell.h"
-#include "JSNumberCell.h"
 #include "MarkStack.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
@@ -55,6 +54,9 @@ namespace JSC {
     class Structure;
     struct HashTable;
 
+    JSObject* throwTypeError(ExecState*, const UString&);
+    extern const char* StrictModeReadonlyPropertyWriteError;
+
     // ECMA 262-3 8.6.1
     // Property attributes
     enum Attribute {
@@ -67,29 +69,29 @@ namespace JSC {
         Setter       = 1 << 6   // property is a setter
     };
 
-    typedef EncodedJSValue* PropertyStorage;
-    typedef const EncodedJSValue* ConstPropertyStorage;
+    typedef WriteBarrierBase<Unknown>* PropertyStorage;
+    typedef const WriteBarrierBase<Unknown>* ConstPropertyStorage;
 
     class JSObject : public JSCell {
         friend class BatchedTransitionOptimizer;
         friend class JIT;
         friend class JSCell;
+        friend void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot);
 
     public:
-        explicit JSObject(NonNullPassRefPtr<Structure>);
-
-        virtual void markChildren(MarkStack&);
-        ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack);
+        virtual void visitChildren(SlotVisitor&);
+        ALWAYS_INLINE void visitChildrenDirect(SlotVisitor&);
 
         // The inline virtual destructor cannot be the first virtual function declared
         // in the class as it results in the vtable being generated as a weak symbol
         virtual ~JSObject();
 
         JSValue prototype() const;
-        void setPrototype(JSValue prototype);
+        void setPrototype(JSGlobalData&, JSValue prototype);
+        bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype);
         
-        void setStructure(NonNullPassRefPtr<Structure>);
-        Structure* inheritorID();
+        void setStructure(JSGlobalData&, Structure*);
+        Structure* inheritorID(JSGlobalData&);
 
         virtual UString className() const;
 
@@ -107,6 +109,9 @@ namespace JSC {
         virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
         virtual void put(ExecState*, unsigned propertyName, JSValue value);
 
+        virtual void putWithAttributes(JSGlobalData*, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot);
+        virtual void putWithAttributes(JSGlobalData*, const Identifier& propertyName, JSValue value, unsigned attributes);
+        virtual void putWithAttributes(JSGlobalData*, unsigned propertyName, JSValue value, unsigned attributes);
         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot);
         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
         virtual void putWithAttributes(ExecState*, unsigned propertyName, JSValue value, unsigned attributes);
@@ -132,61 +137,65 @@ namespace JSC {
         virtual bool toBoolean(ExecState*) const;
         virtual double toNumber(ExecState*) const;
         virtual UString toString(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
+        virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         virtual JSObject* toThisObject(ExecState*) const;
+        virtual JSValue toStrictThisObject(ExecState*) const;
         virtual JSObject* unwrappedObject();
 
         bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const;
 
         // This get function only looks at the property map.
-        JSValue getDirect(const Identifier& propertyName) const
+        JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const
         {
-            size_t offset = m_structure->get(propertyName);
+            size_t offset = m_structure->get(globalData, propertyName);
             return offset != WTF::notFound ? getDirectOffset(offset) : JSValue();
         }
 
-        JSValue* getDirectLocation(const Identifier& propertyName)
+        WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName)
         {
-            size_t offset = m_structure->get(propertyName);
+            size_t offset = m_structure->get(globalData, propertyName);
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
-        JSValue* getDirectLocation(const Identifier& propertyName, unsigned& attributes)
+        WriteBarrierBase<Unknown>* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes)
         {
             JSCell* specificFunction;
-            size_t offset = m_structure->get(propertyName, attributes, specificFunction);
+            size_t offset = m_structure->get(globalData, propertyName, attributes, specificFunction);
             return offset != WTF::notFound ? locationForOffset(offset) : 0;
         }
 
-        size_t offsetForLocation(JSValue* location) const
+        size_t offsetForLocation(WriteBarrierBase<Unknown>* location) const
         {
-            return location - reinterpret_cast<const JSValue*>(propertyStorage());
+            return location - propertyStorage();
         }
 
-        void transitionTo(Structure*);
+        void transitionTo(JSGlobalData&, Structure*);
 
-        void removeDirect(const Identifier& propertyName);
-        bool hasCustomProperties() { return !m_structure->isEmpty(); }
+        void removeDirect(JSGlobalData&, const Identifier& propertyName);
+        bool hasCustomProperties() { return m_structure->didTransition(); }
         bool hasGetterSetterProperties() { return m_structure->hasGetterSetterProperties(); }
 
-        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
-        void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0);
-        void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&);
+        bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&);
+        void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0);
+        bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
-        void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
-        void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
+        void putDirectFunction(JSGlobalData&, const Identifier& propertyName, JSCell*, unsigned attr = 0);
+        void putDirectFunction(JSGlobalData&, const Identifier& propertyName, JSCell*, unsigned attr, bool checkReadOnly, PutPropertySlot&);
         void putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr = 0);
+        void putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr = 0);
 
-        void putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attr = 0);
-        void putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attr = 0);
+        void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0);
+        void putDirectFunctionWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSCell* value, unsigned attr = 0);
         void putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr = 0);
+        void putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr = 0);
 
         // Fast access to known property offsets.
-        JSValue getDirectOffset(size_t offset) const { return JSValue::decode(propertyStorage()[offset]); }
-        void putDirectOffset(size_t offset, JSValue value) { propertyStorage()[offset] = JSValue::encode(value); }
+        JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); }
+        void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); }
+        void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); }
 
-        void fillGetterPropertySlot(PropertySlot&, JSValue* location);
+        void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location);
 
         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
@@ -197,39 +206,68 @@ namespace JSC {
         virtual bool isGlobalObject() const { return false; }
         virtual bool isVariableObject() const { return false; }
         virtual bool isActivationObject() const { return false; }
-        virtual bool isNotAnObjectErrorStub() const { return false; }
+        virtual bool isStrictModeFunction() const { return false; }
+        virtual bool isErrorInstance() const { return false; }
+
+        void seal(JSGlobalData&);
+        void freeze(JSGlobalData&);
+        virtual void preventExtensions(JSGlobalData&);
+        bool isSealed(JSGlobalData& globalData) { return m_structure->isSealed(globalData); }
+        bool isFrozen(JSGlobalData& globalData) { return m_structure->isFrozen(globalData); }
+        bool isExtensible() { return m_structure->isExtensible(); }
 
         virtual ComplType exceptionType() const { return Throw; }
 
         void allocatePropertyStorage(size_t oldSize, size_t newSize);
-        void allocatePropertyStorageInline(size_t oldSize, size_t newSize);
-        bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); }
+        bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage) == static_cast<const void*>(this + 1); }
 
-        static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3;
-        static const unsigned nonInlineBaseStorageCapacity = 16;
+        static const unsigned baseExternalStorageCapacity = 16;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        void flattenDictionaryObject(JSGlobalData& globalData)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            m_structure->flattenDictionaryStructure(globalData, this);
         }
 
-        void flattenDictionaryObject()
+        void putAnonymousValue(JSGlobalData& globalData, unsigned index, JSValue value)
+        {
+            ASSERT(index < m_structure->anonymousSlotCount());
+            locationForOffset(index)->set(globalData, this, value);
+        }
+        void clearAnonymousValue(unsigned index)
+        {
+            ASSERT(index < m_structure->anonymousSlotCount());
+            locationForOffset(index)->clear();
+        }
+        JSValue getAnonymousValue(unsigned index) const
         {
-            m_structure->flattenDictionaryStructure(this);
+            ASSERT(index < m_structure->anonymousSlotCount());
+            return locationForOffset(index)->get();
         }
 
+        static size_t offsetOfInlineStorage();
+        
+        static JS_EXPORTDATA const ClassInfo s_info;
+
     protected:
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
         static const unsigned StructureFlags = 0;
 
-        void putAnonymousValue(unsigned index, JSValue value)
+        void putThisToAnonymousValue(unsigned index)
         {
-            ASSERT(index < m_structure->anonymousSlotCount());
-            *locationForOffset(index) = value;
+            locationForOffset(index)->setWithoutWriteBarrier(this);
         }
-        JSValue getAnonymousValue(unsigned index) const
+
+        // To instantiate objects you likely want JSFinalObject, below.
+        // To create derived types you likely want JSNonFinalObject, below.
+        JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage);
+        JSObject(VPtrStealingHackType, PropertyStorage inlineStorage)
+            : JSCell(VPtrStealingHack)
+            , m_propertyStorage(inlineStorage)
         {
-            ASSERT(index < m_structure->anonymousSlotCount());
-            return *locationForOffset(index);
         }
 
     private:
@@ -241,40 +279,118 @@ namespace JSC {
         void getString(ExecState* exec);
         void isObject();
         void isString();
-#if USE(JSVALUE32)
-        void isNumber();
-#endif
-
-        ConstPropertyStorage propertyStorage() const { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
-        PropertyStorage propertyStorage() { return (isUsingInlineStorage() ? m_inlineStorage : m_externalStorage); }
+        
+        ConstPropertyStorage propertyStorage() const { return m_propertyStorage; }
+        PropertyStorage propertyStorage() { return m_propertyStorage; }
 
-        const JSValue* locationForOffset(size_t offset) const
+        const WriteBarrierBase<Unknown>* locationForOffset(size_t offset) const
         {
-            return reinterpret_cast<const JSValue*>(&propertyStorage()[offset]);
+            return &propertyStorage()[offset];
         }
 
-        JSValue* locationForOffset(size_t offset)
+        WriteBarrierBase<Unknown>* locationForOffset(size_t offset)
         {
-            return reinterpret_cast<JSValue*>(&propertyStorage()[offset]);
+            return &propertyStorage()[offset];
         }
 
-        void putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot, JSCell*);
-        void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot);
+        bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&, JSCell*);
+        bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&);
         void putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue value, unsigned attr = 0);
 
         bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
 
         const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const;
-        Structure* createInheritorID();
-
-        union {
-            PropertyStorage m_externalStorage;
-            EncodedJSValue m_inlineStorage[inlineStorageCapacity];
-        };
+        Structure* createInheritorID(JSGlobalData&);
 
-        RefPtr<Structure> m_inheritorID;
+        PropertyStorage m_propertyStorage;
+        WriteBarrier<Structure> m_inheritorID;
     };
+
+
+#if USE(JSVALUE32_64)
+#define JSNonFinalObject_inlineStorageCapacity 4
+#define JSFinalObject_inlineStorageCapacity 6
+#else
+#define JSNonFinalObject_inlineStorageCapacity 2
+#define JSFinalObject_inlineStorageCapacity 4
+#endif
+
+COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineStorageCapacity), final_storage_is_at_least_as_large_as_non_final);
+
+    // JSNonFinalObject is a type of JSObject that has some internal storage,
+    // but also preserves some space in the collector cell for additional
+    // data members in derived types.
+    class JSNonFinalObject : public JSObject {
+        friend class JSObject;
+
+    public:
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        explicit JSNonFinalObject(VPtrStealingHackType)
+            : JSObject(VPtrStealingHack, m_inlineStorage)
+        {
+        }
     
+        explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure)
+            : JSObject(globalData, structure, m_inlineStorage)
+        {
+            ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
+            ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
+        }
+
+    private:
+        WriteBarrier<Unknown> m_inlineStorage[JSNonFinalObject_inlineStorageCapacity];
+    };
+
+    // JSFinalObject is a type of JSObject that contains sufficent internal
+    // storage to fully make use of the colloctor cell containing it.
+    class JSFinalObject : public JSObject {
+        friend class JSObject;
+
+    public:
+        static JSFinalObject* create(ExecState* exec, Structure* structure)
+        {
+            return new (exec) JSFinalObject(exec->globalData(), structure);
+        }
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    private:
+        explicit JSFinalObject(JSGlobalData& globalData, Structure* structure)
+            : JSObject(globalData, structure, m_inlineStorage)
+        {
+            ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double) == 0);
+            ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
+        }
+
+        static const unsigned StructureFlags = JSObject::StructureFlags | IsJSFinalObject;
+
+        WriteBarrierBase<Unknown> m_inlineStorage[JSFinalObject_inlineStorageCapacity];
+    };
+
+inline size_t JSObject::offsetOfInlineStorage()
+{
+    ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage));
+    return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage);
+}
+
+inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure)
+{
+    return JSFinalObject::create(exec, structure);
+}
+
+inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSValue prototype)
+{
+    return JSFinalObject::createStructure(globalData, prototype);
+}
+
 inline JSObject* asObject(JSCell* cell)
 {
     ASSERT(cell->isObject());
@@ -286,23 +402,22 @@ inline JSObject* asObject(JSValue value)
     return asObject(value.asCell());
 }
 
-inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure)
-    : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
+inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, PropertyStorage inlineStorage)
+    : JSCell(globalData, structure)
+    , m_propertyStorage(inlineStorage)
 {
-    ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity);
+    ASSERT(inherits(&s_info));
+    ASSERT(m_structure->propertyStorageCapacity() < baseExternalStorageCapacity);
     ASSERT(m_structure->isEmpty());
     ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
-#if USE(JSVALUE64) || USE(JSVALUE32_64)
-    ASSERT(OBJECT_OFFSETOF(JSObject, m_inlineStorage) % sizeof(double) == 0);
-#endif
+    ASSERT(static_cast<void*>(inlineStorage) == static_cast<void*>(this + 1));
+    ASSERT(m_structure->typeInfo().type() == ObjectType);
 }
 
 inline JSObject::~JSObject()
 {
-    ASSERT(m_structure);
     if (!isUsingInlineStorage())
-        delete [] m_externalStorage;
-    m_structure->deref();
+        delete [] m_propertyStorage;
 }
 
 inline JSValue JSObject::prototype() const
@@ -310,29 +425,43 @@ inline JSValue JSObject::prototype() const
     return m_structure->storedPrototype();
 }
 
-inline void JSObject::setPrototype(JSValue prototype)
+inline bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype)
+{
+    JSValue nextPrototypeValue = prototype;
+    while (nextPrototypeValue && nextPrototypeValue.isObject()) {
+        JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject();
+        if (nextPrototype == this)
+            return false;
+        nextPrototypeValue = nextPrototype->prototype();
+    }
+    setPrototype(globalData, prototype);
+    return true;
+}
+
+inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype)
 {
     ASSERT(prototype);
-    RefPtr<Structure> newStructure = Structure::changePrototypeTransition(m_structure, prototype);
-    setStructure(newStructure.release());
+    setStructure(globalData, Structure::changePrototypeTransition(globalData, m_structure.get(), prototype));
 }
 
-inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure)
+inline void JSObject::setStructure(JSGlobalData& globalData, Structure* structure)
 {
-    m_structure->deref();
-    m_structure = structure.releaseRef(); // ~JSObject balances this ref()
+    ASSERT(structure->typeInfo().overridesVisitChildren() == m_structure->typeInfo().overridesVisitChildren());
+    m_structure.set(globalData, this, structure);
 }
 
-inline Structure* JSObject::inheritorID()
+inline Structure* JSObject::inheritorID(JSGlobalData& globalData)
 {
-    if (m_inheritorID)
+    if (m_inheritorID) {
+        ASSERT(m_inheritorID->isEmpty());
         return m_inheritorID.get();
-    return createInheritorID();
+    }
+    return createInheritorID(globalData);
 }
 
 inline bool Structure::isUsingInlineStorage() const
 {
-    return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
+    return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity;
 }
 
 inline bool JSCell::inherits(const ClassInfo* info) const
@@ -352,11 +481,11 @@ inline bool JSValue::inherits(const ClassInfo* classInfo) const
 
 ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    if (JSValue* location = getDirectLocation(propertyName)) {
-        if (m_structure->hasGetterSetterProperties() && location[0].isGetterSetter())
+    if (WriteBarrierBase<Unknown>* location = getDirectLocation(exec->globalData(), propertyName)) {
+        if (m_structure->hasGetterSetterProperties() && location->isGetterSetter())
             fillGetterPropertySlot(slot, location);
         else
-            slot.setValueSlot(this, location, offsetForLocation(location));
+            slot.setValue(this, location->get(), offsetForLocation(location));
         return true;
     }
 
@@ -430,7 +559,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
     return jsUndefined();
 }
 
-inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
+inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction)
 {
     ASSERT(value);
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
@@ -438,15 +567,16 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue
     if (m_structure->isDictionary()) {
         unsigned currentAttributes;
         JSCell* currentSpecificFunction;
-        size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
+        size_t offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
         if (offset != WTF::notFound) {
             // If there is currently a specific function, and there now either isn't,
             // or the new value is different, then despecify.
             if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
-                m_structure->despecifyDictionaryFunction(propertyName);
+                m_structure->despecifyDictionaryFunction(globalData, propertyName);
             if (checkReadOnly && currentAttributes & ReadOnly)
-                return;
-            putDirectOffset(offset, value);
+                return false;
+
+            putDirectOffset(globalData, offset, value);
             // At this point, the objects structure only has a specific value set if previously there
             // had been one set, and if the new value being specified is the same (otherwise we would
             // have despecified, above).  So, if currentSpecificFunction is not set, or if the new
@@ -455,44 +585,47 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue
             // If there was previously a value, and the new value is the same, then we cannot cache.
             if (!currentSpecificFunction || (specificFunction != currentSpecificFunction))
                 slot.setExistingProperty(this, offset);
-            return;
+            return true;
         }
 
+        if (checkReadOnly && !isExtensible())
+            return false;
+
         size_t currentCapacity = m_structure->propertyStorageCapacity();
-        offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction);
+        offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction);
         if (currentCapacity != m_structure->propertyStorageCapacity())
             allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
 
         ASSERT(offset < m_structure->propertyStorageCapacity());
-        putDirectOffset(offset, value);
+        putDirectOffset(globalData, offset, value);
         // See comment on setNewProperty call below.
         if (!specificFunction)
             slot.setNewProperty(this, offset);
-        return;
+        return true;
     }
 
     size_t offset;
     size_t currentCapacity = m_structure->propertyStorageCapacity();
-    if (RefPtr<Structure> structure = Structure::addPropertyTransitionToExistingStructure(m_structure, propertyName, attributes, specificFunction, offset)) {    
+    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(m_structure.get(), propertyName, attributes, specificFunction, offset)) {    
         if (currentCapacity != structure->propertyStorageCapacity())
             allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
 
         ASSERT(offset < structure->propertyStorageCapacity());
-        setStructure(structure.release());
-        putDirectOffset(offset, value);
+        setStructure(globalData, structure);
+        putDirectOffset(globalData, offset, value);
         // This is a new property; transitions with specific values are not currently cachable,
         // so leave the slot in an uncachable state.
         if (!specificFunction)
             slot.setNewProperty(this, offset);
-        return;
+        return true;
     }
 
     unsigned currentAttributes;
     JSCell* currentSpecificFunction;
-    offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction);
+    offset = m_structure->get(globalData, propertyName, currentAttributes, currentSpecificFunction);
     if (offset != WTF::notFound) {
         if (checkReadOnly && currentAttributes & ReadOnly)
-            return;
+            return false;
 
         // There are three possibilities here:
         //  (1) There is an existing specific value set, and we're overwriting with *the same value*.
@@ -506,110 +639,104 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue
         if (currentSpecificFunction) {
             // case (1) Do the put, then return leaving the slot uncachable.
             if (specificFunction == currentSpecificFunction) {
-                putDirectOffset(offset, value);
-                return;
+                putDirectOffset(globalData, offset, value);
+                return true;
             }
             // case (2) Despecify, fall through to (3).
-            setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName));
+            setStructure(globalData, Structure::despecifyFunctionTransition(globalData, m_structure.get(), propertyName));
         }
 
         // case (3) set the slot, do the put, return.
         slot.setExistingProperty(this, offset);
-        putDirectOffset(offset, value);
-        return;
+        putDirectOffset(globalData, offset, value);
+        return true;
     }
 
-    // If we have a specific function, we may have got to this point if there is
-    // already a transition with the correct property name and attributes, but
-    // specialized to a different function.  In this case we just want to give up
-    // and despecialize the transition.
-    // In this case we clear the value of specificFunction which will result
-    // in us adding a non-specific transition, and any subsequent lookup in
-    // Structure::addPropertyTransitionToExistingStructure will just use that.
-    if (specificFunction && m_structure->hasTransition(propertyName, attributes))
-        specificFunction = 0;
+    if (checkReadOnly && !isExtensible())
+        return false;
 
-    RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset);
+    Structure* structure = Structure::addPropertyTransition(globalData, m_structure.get(), propertyName, attributes, specificFunction, offset);
 
     if (currentCapacity != structure->propertyStorageCapacity())
         allocatePropertyStorage(currentCapacity, structure->propertyStorageCapacity());
 
     ASSERT(offset < structure->propertyStorageCapacity());
-    setStructure(structure.release());
-    putDirectOffset(offset, value);
+    setStructure(globalData, structure);
+    putDirectOffset(globalData, offset, value);
     // This is a new property; transitions with specific values are not currently cachable,
     // so leave the slot in an uncachable state.
     if (!specificFunction)
         slot.setNewProperty(this, offset);
+    return true;
 }
 
-inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
 {
     ASSERT(value);
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
+    return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, getJSFunction(globalData, value));
 }
 
 inline void JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
     PutPropertySlot slot;
-    putDirectInternal(propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
+    putDirectInternal(globalData, propertyName, value, attributes, false, slot, getJSFunction(globalData, value));
 }
 
-inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
 {
     ASSERT(value);
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, 0);
+    return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, 0);
 }
 
-inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, unsigned attributes)
+inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
     PutPropertySlot slot;
-    putDirectInternal(propertyName, value, attributes, false, slot, 0);
+    putDirectInternal(globalData, propertyName, value, attributes, false, slot, 0);
 }
 
-inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
-    putDirectInternal(propertyName, value, 0, false, slot, 0);
+    return putDirectInternal(globalData, propertyName, value, 0, false, slot, 0);
 }
 
-inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
+inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot)
 {
-    putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value);
+    putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, value);
 }
 
-inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr)
+inline void JSObject::putDirectFunction(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attr)
 {
     PutPropertySlot slot;
-    putDirectInternal(propertyName, value, attr, false, slot, value);
+    putDirectInternal(globalData, propertyName, value, attr, false, slot, value);
 }
 
-inline void JSObject::putDirectWithoutTransition(const Identifier& propertyName, JSValue value, unsigned attributes)
+inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
     size_t currentCapacity = m_structure->propertyStorageCapacity();
-    size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, 0);
+    size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, 0);
     if (currentCapacity != m_structure->propertyStorageCapacity())
         allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
-    putDirectOffset(offset, value);
+    putDirectOffset(globalData, offset, value);
 }
 
-inline void JSObject::putDirectFunctionWithoutTransition(const Identifier& propertyName, JSCell* value, unsigned attributes)
+inline void JSObject::putDirectFunctionWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSCell* value, unsigned attributes)
 {
     size_t currentCapacity = m_structure->propertyStorageCapacity();
-    size_t offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, value);
+    size_t offset = m_structure->addPropertyWithoutTransition(globalData, propertyName, attributes, value);
     if (currentCapacity != m_structure->propertyStorageCapacity())
         allocatePropertyStorage(currentCapacity, m_structure->propertyStorageCapacity());
-    putDirectOffset(offset, value);
+    putDirectOffset(globalData, offset, value);
 }
 
-inline void JSObject::transitionTo(Structure* newStructure)
+inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure)
 {
     if (m_structure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
         allocatePropertyStorage(m_structure->propertyStorageCapacity(), newStructure->propertyStorageCapacity());
-    setStructure(newStructure);
+    setStructure(globalData, newStructure);
 }
 
 inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
@@ -678,10 +805,11 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu
     asCell()->put(exec, propertyName, value, slot);
 }
 
-inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
     ASSERT(isCell() && isObject());
-    asObject(asCell())->putDirect(propertyName, value, slot);
+    if (!asObject(asCell())->putDirect(exec->globalData(), propertyName, value, slot) && slot.isStrictMode())
+        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
 }
 
 inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
@@ -693,35 +821,15 @@ inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value)
     asCell()->put(exec, propertyName, value);
 }
 
-ALWAYS_INLINE void JSObject::allocatePropertyStorageInline(size_t oldSize, size_t newSize)
-{
-    ASSERT(newSize > oldSize);
-
-    // It's important that this function not rely on m_structure, since
-    // we might be in the middle of a transition.
-    bool wasInline = (oldSize == JSObject::inlineStorageCapacity);
-
-    PropertyStorage oldPropertyStorage = (wasInline ? m_inlineStorage : m_externalStorage);
-    PropertyStorage newPropertyStorage = new EncodedJSValue[newSize];
-
-    for (unsigned i = 0; i < oldSize; ++i)
-       newPropertyStorage[i] = oldPropertyStorage[i];
-
-    if (!wasInline)
-        delete [] oldPropertyStorage;
-
-    m_externalStorage = newPropertyStorage;
-}
-
-ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack)
+ALWAYS_INLINE void JSObject::visitChildrenDirect(SlotVisitor& visitor)
 {
-    JSCell::markChildren(markStack);
+    JSCell::visitChildren(visitor);
 
-    markStack.append(prototype());
-    
     PropertyStorage storage = propertyStorage();
     size_t storageSize = m_structure->propertyStorageSize();
-    markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize);
+    visitor.appendValues(storage, storageSize);
+    if (m_inheritorID)
+        visitor.append(&m_inheritorID);
 }
 
 // --- JSValue inlines ----------------------------
@@ -736,6 +844,27 @@ inline JSString* JSValue::toThisJSString(ExecState* exec) const
     return isString() ? static_cast<JSString*>(asCell()) : jsString(exec, toThisObject(exec)->toString(exec));
 }
 
+inline JSValue JSValue::toStrictThisObject(ExecState* exec) const
+{
+    if (!isObject())
+        return *this;
+    return asObject(asCell())->toStrictThisObject(exec);
+}
+
+ALWAYS_INLINE JSObject* Register::function() const
+{
+    if (!jsValue())
+        return 0;
+    return asObject(jsValue());
+}
+
+ALWAYS_INLINE Register Register::withCallee(JSObject* callee)
+{
+    Register r;
+    r = JSValue(callee);
+    return r;
+}
+
 } // namespace JSC
 
 #endif // JSObject_h
diff --git a/runtime/JSObjectWithGlobalObject.cpp b/runtime/JSObjectWithGlobalObject.cpp
new file mode 100644 (file)
index 0000000..2b489a2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "JSObjectWithGlobalObject.h"
+
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalObject* globalObject, Structure* structure)
+    : JSNonFinalObject(globalObject->globalData(), structure)
+{
+    COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one);
+    ASSERT(!globalObject || globalObject->isGlobalObject());
+    if (!globalObject)
+        clearAnonymousValue(GlobalObjectSlot);
+    else
+        putAnonymousValue(globalObject->globalData(), GlobalObjectSlot, globalObject);
+}
+
+JSObjectWithGlobalObject::JSObjectWithGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject, Structure* structure)
+    : JSNonFinalObject(globalData, structure)
+{
+    COMPILE_ASSERT(AnonymousSlotCount == 1, AnonymousSlotCount_must_be_one);
+    ASSERT(!globalObject || globalObject->isGlobalObject());
+    if (!globalObject)
+        clearAnonymousValue(GlobalObjectSlot);
+    else
+        putAnonymousValue(globalData, GlobalObjectSlot, globalObject);
+}
+
+} // namespace JSC
diff --git a/runtime/JSObjectWithGlobalObject.h b/runtime/JSObjectWithGlobalObject.h
new file mode 100644 (file)
index 0000000..844bcd8
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 JSObjectWithGlobalObject_h
+#define JSObjectWithGlobalObject_h
+
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+class JSGlobalObject;
+
+class JSObjectWithGlobalObject : public JSNonFinalObject {
+public:
+    static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+    {
+        return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+    }
+
+    JSGlobalObject* globalObject() const
+    {
+        return asGlobalObject((getAnonymousValue(GlobalObjectSlot).asCell()));
+    }
+
+protected:
+    JSObjectWithGlobalObject(JSGlobalObject*, Structure*);
+    JSObjectWithGlobalObject(JSGlobalData&, JSGlobalObject*, Structure*);
+
+    JSObjectWithGlobalObject(VPtrStealingHackType)
+        : JSNonFinalObject(VPtrStealingHack)
+    {
+        // Should only be used by JSFunction when we aquire the JSFunction vptr.
+    }
+    static const unsigned AnonymousSlotCount = JSObject::AnonymousSlotCount + 1;
+    static const unsigned GlobalObjectSlot = 0;
+};
+
+} // namespace JSC
+
+#endif // JSObjectWithGlobalObject_h
index a5d4da01b67ca4984802b02c42613459ac1e1c74..e05bb3f44d5a01657b5edeb95d74c897a5261bc3 100644 (file)
@@ -35,22 +35,17 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator);
 
+const ClassInfo JSPropertyNameIterator::s_info = { "JSPropertyNameIterator", 0, 0, 0 };
+
 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots)
-    : JSCell(exec->globalData().propertyNameIteratorStructure.get())
-    , m_cachedStructure(0)
+    : JSCell(exec->globalData(), exec->globalData().propertyNameIteratorStructure.get())
     , m_numCacheableSlots(numCacheableSlots)
     , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size())
-    , m_jsStrings(new JSValue[m_jsStringsSize])
+    , m_jsStrings(adoptArrayPtr(new WriteBarrier<Unknown>[m_jsStringsSize]))
 {
     PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector();
     for (size_t i = 0; i < m_jsStringsSize; ++i)
-        m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring());
-}
-
-JSPropertyNameIterator::~JSPropertyNameIterator()
-{
-    if (m_cachedStructure)
-        m_cachedStructure->clearEnumerationCache(this);
+        m_jsStrings[i].set(exec->globalData(), this, jsOwnedString(exec, propertyNameVector[i].ustring()));
 }
 
 JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o)
@@ -77,22 +72,22 @@ JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject
     
     size_t count = normalizePrototypeChain(exec, o);
     StructureChain* structureChain = o->structure()->prototypeChain(exec);
-    RefPtr<Structure>* structure = structureChain->head();
+    WriteBarrier<Structure>* structure = structureChain->head();
     for (size_t i = 0; i < count; ++i) {
         if (structure[i]->typeInfo().overridesGetPropertyNames())
             return jsPropertyNameIterator;
     }
 
-    jsPropertyNameIterator->setCachedPrototypeChain(structureChain);
-    jsPropertyNameIterator->setCachedStructure(o->structure());
-    o->structure()->setEnumerationCache(jsPropertyNameIterator);
+    jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain);
+    jsPropertyNameIterator->setCachedStructure(exec->globalData(), o->structure());
+    o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator);
     return jsPropertyNameIterator;
 }
 
 JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
 {
-    JSValue& identifier = m_jsStrings[i];
-    if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec))
+    JSValue identifier = m_jsStrings[i].get();
+    if (m_cachedStructure.get() == base->structure() && m_cachedPrototypeChain.get() == base->structure()->prototypeChain(exec))
         return identifier;
 
     if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec))))
@@ -100,9 +95,13 @@ JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i)
     return identifier;
 }
 
-void JSPropertyNameIterator::markChildren(MarkStack& markStack)
+void JSPropertyNameIterator::visitChildren(SlotVisitor& visitor)
 {
-    markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    visitor.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues);
+    if (m_cachedPrototypeChain)
+        visitor.append(&m_cachedPrototypeChain);
 }
 
 } // namespace JSC
index 01700ac212155b4fe9b97faaad1bfdcc74042ffa..ff129f0549a1324b9a48080874680b347adf6d27 100644 (file)
@@ -45,16 +45,14 @@ namespace JSC {
     public:
         static JSPropertyNameIterator* create(ExecState*, JSObject*);
         
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren), AnonymousSlotCount, &s_info);
         }
-        
-        virtual ~JSPropertyNameIterator();
 
         virtual bool isPropertyNameIterator() const { return true; }
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
         bool getOffset(size_t i, int& offset)
         {
@@ -67,41 +65,43 @@ namespace JSC {
         JSValue get(ExecState*, JSObject*, size_t i);
         size_t size() { return m_jsStringsSize; }
 
-        void setCachedStructure(Structure* structure)
+        void setCachedStructure(JSGlobalData& globalData, Structure* structure)
         {
             ASSERT(!m_cachedStructure);
             ASSERT(structure);
-            m_cachedStructure = structure;
+            m_cachedStructure.set(globalData, this, structure);
         }
         Structure* cachedStructure() { return m_cachedStructure.get(); }
 
-        void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }
+        void setCachedPrototypeChain(JSGlobalData& globalData, StructureChain* cachedPrototypeChain) { m_cachedPrototypeChain.set(globalData, this, cachedPrototypeChain); }
         StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+        
+        static const ClassInfo s_info;
 
     private:
         JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
 
-        RefPtr<Structure> m_cachedStructure;
-        RefPtr<StructureChain> m_cachedPrototypeChain;
+        WriteBarrier<Structure> m_cachedStructure;
+        WriteBarrier<StructureChain> m_cachedPrototypeChain;
         uint32_t m_numCacheableSlots;
         uint32_t m_jsStringsSize;
-        OwnArrayPtr<JSValue> m_jsStrings;
+        OwnArrayPtr<WriteBarrier<Unknown> > m_jsStrings;
     };
 
-    inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache)
+    inline void Structure::setEnumerationCache(JSGlobalData& globalData, JSPropertyNameIterator* enumerationCache)
     {
         ASSERT(!isDictionary());
-        m_enumerationCache = enumerationCache;
+        m_enumerationCache.set(globalData, this, enumerationCache);
     }
 
-    inline void Structure::clearEnumerationCache(JSPropertyNameIterator* enumerationCache)
+    inline JSPropertyNameIterator* Structure::enumerationCache()
     {
-        m_enumerationCache.clear(enumerationCache);
+        return m_enumerationCache.get();
     }
 
-    inline JSPropertyNameIterator* Structure::enumerationCache()
+    ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const
     {
-        return m_enumerationCache.get();
+        return static_cast<JSPropertyNameIterator*>(jsValue().asCell());
     }
 
 } // namespace JSC
index ad1021809386f695e7e22538aa3edf36598384d3..5206510d6cd2a7724a73b5bed12a1f2d6d8cc716 100644 (file)
 
 #include "JSStaticScopeObject.h"
 
-namespace JSC {
+#include "Error.h"
 
+namespace JSC {
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
-void JSStaticScopeObject::markChildren(MarkStack& markStack)
+void JSStaticScopeObject::visitChildren(SlotVisitor& visitor)
 {
-    JSVariableObject::markChildren(markStack);
-    markStack.append(d()->registerStore.jsValue());
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSVariableObject::visitChildren(visitor);
+    visitor.append(&m_registerStore);
 }
 
 JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
@@ -42,17 +46,37 @@ JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
     return exec->globalThisValue();
 }
 
-void JSStaticScopeObject::put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&)
+JSValue JSStaticScopeObject::toStrictThisObject(ExecState*) const
+{
+    return jsNull();
+}
+
+void JSStaticScopeObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
-    if (symbolTablePut(propertyName, value))
+    if (slot.isStrictMode()) {
+        // Double lookup in strict mode, but this only occurs when
+        // a) indirectly writing to an exception slot
+        // b) writing to a function expression name
+        // (a) is unlikely, and (b) is an error.
+        // Also with a single entry the symbol table lookup should simply be
+        // a pointer compare.
+        PropertySlot slot;
+        bool isWritable = true;
+        symbolTableGet(propertyName, slot, isWritable);
+        if (!isWritable) {
+            throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+            return;
+        }
+    }
+    if (symbolTablePut(exec->globalData(), propertyName, value))
         return;
     
     ASSERT_NOT_REACHED();
 }
 
-void JSStaticScopeObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes)
+void JSStaticScopeObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
 {
-    if (symbolTablePutWithAttributes(propertyName, value, attributes))
+    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
     
     ASSERT_NOT_REACHED();
@@ -63,13 +87,7 @@ bool JSStaticScopeObject::isDynamicScope(bool&) const
     return false;
 }
 
-JSStaticScopeObject::~JSStaticScopeObject()
-{
-    ASSERT(d());
-    delete d();
-}
-
-inline bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
+bool JSStaticScopeObject::getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot& slot)
 {
     return symbolTableGet(propertyName, slot);
 }
index dcece9d97346c6e32f49060fdcaf888e98da50e8..b201fe05676b2f17171a74caea418a99af31c928 100644 (file)
 namespace JSC{
     
     class JSStaticScopeObject : public JSVariableObject {
-    protected:
-        using JSVariableObject::JSVariableObjectData;
-        struct JSStaticScopeObjectData : public JSVariableObjectData {
-            JSStaticScopeObjectData()
-                : JSVariableObjectData(&symbolTable, &registerStore + 1)
-            {
-            }
-            SymbolTable symbolTable;
-            Register registerStore;
-        };
-        
     public:
         JSStaticScopeObject(ExecState* exec, const Identifier& ident, JSValue value, unsigned attributes)
-            : JSVariableObject(exec->globalData().staticScopeStructure, new JSStaticScopeObjectData())
+            : JSVariableObject(exec->globalData(), exec->globalData().staticScopeStructure.get(), &m_symbolTable, reinterpret_cast<Register*>(&m_registerStore + 1))
         {
-            d()->registerStore = value;
-            symbolTable().add(ident.ustring().rep(), SymbolTableEntry(-1, attributes));
+            m_registerStore.set(exec->globalData(), this, value);
+            symbolTable().add(ident.impl(), SymbolTableEntry(-1, attributes));
         }
-        virtual ~JSStaticScopeObject();
-        virtual void markChildren(MarkStack&);
+
+        virtual void visitChildren(SlotVisitor&);
         bool isDynamicScope(bool& requiresDynamicChecks) const;
         virtual JSObject* toThisObject(ExecState*) const;
+        virtual JSValue toStrictThisObject(ExecState*) const;
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
         void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes);
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); }
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
-        JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); }
+        SymbolTable m_symbolTable;
+        WriteBarrier<Unknown> m_registerStore;
     };
 
 }
index 6128790f8e572ad784c123ba207a7ada0a783c21..da15997d32db78aed7b57f07f0cc4b529331f010 100644 (file)
@@ -24,6 +24,7 @@
 #include "JSString.h"
 
 #include "JSGlobalObject.h"
+#include "JSGlobalObjectFunctions.h"
 #include "JSObject.h"
 #include "Operations.h"
 #include "StringObject.h"
 
 namespace JSC {
     
-static const unsigned resolveRopeForSubstringCutoff = 4;
+static const unsigned substringFromRopeCutoff = 4;
+
+const ClassInfo JSString::s_info = { "string", 0, 0, 0 };
+
+void JSString::resolveRope(ExecState* exec) const
+{
+    ASSERT(isRope());
+
+    UChar* buffer;
+    if (PassRefPtr<StringImpl> newImpl = StringImpl::tryCreateUninitialized(m_length, buffer))
+        m_value = newImpl;
+    else {
+        outOfMemory(exec);
+        return;
+    }
+
+    RopeImpl::Fiber currentFiber = m_fibers[0];
+
+    if ((m_fiberCount > 2) || (RopeImpl::isRope(currentFiber)) 
+        || ((m_fiberCount == 2) && (RopeImpl::isRope(m_fibers[1])))) {
+        resolveRopeSlowCase(exec, buffer);
+        return;
+    }
+
+    UChar* position = buffer;
+    StringImpl* string = static_cast<StringImpl*>(currentFiber);
+    unsigned length = string->length();
+    StringImpl::copyChars(position, string->characters(), length);
+
+    if (m_fiberCount > 1) {
+        position += length;
+        currentFiber = m_fibers[1];
+        string = static_cast<StringImpl*>(currentFiber);
+        length = string->length();
+        StringImpl::copyChars(position, string->characters(), length);
+        position += length;
+    }
+
+    ASSERT((buffer + m_length) == position);
+    for (unsigned i = 0; i < m_fiberCount; ++i) {
+        RopeImpl::deref(m_fibers[i]);
+        m_fibers[i] = 0;
+    }
+    m_fiberCount = 0;
+
+    ASSERT(!isRope());
+}
 
 // Overview: this methods converts a JSString from holding a string in rope form
 // down to a simple UString representation.  It does so by building up the string
@@ -39,38 +86,22 @@ static const unsigned resolveRopeForSubstringCutoff = 4;
 // representing the rope is likely imbalanced with more nodes down the left side
 // (since appending to the string is likely more common) - and as such resolving
 // in this fashion should minimize work queue size.  (If we built the queue forwards
-// we would likely have to place all of the constituent UStringImpls into the
+// we would likely have to place all of the constituent StringImpls into the
 // Vector before performing any concatenation, but by working backwards we likely
 // only fill the queue with the number of substrings at any given level in a
-// rope-of-ropes.)
-void JSString::resolveRope(ExecState* exec) const
+// rope-of-ropes.)    
+void JSString::resolveRopeSlowCase(ExecState* exec, UChar* buffer) const
 {
-    ASSERT(isRope());
+    UNUSED_PARAM(exec);
 
-    // Allocate the buffer to hold the final string, position initially points to the end.
-    UChar* buffer;
-    if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_length, buffer))
-        m_value = newImpl;
-    else {
-        for (unsigned i = 0; i < m_fiberCount; ++i) {
-            RopeImpl::deref(m_other.m_fibers[i]);
-            m_other.m_fibers[i] = 0;
-        }
-        m_fiberCount = 0;
-        ASSERT(!isRope());
-        ASSERT(m_value == UString());
-        if (exec)
-            throwOutOfMemoryError(exec);
-        return;
-    }
     UChar* position = buffer + m_length;
 
     // Start with the current RopeImpl.
     Vector<RopeImpl::Fiber, 32> workQueue;
     RopeImpl::Fiber currentFiber;
     for (unsigned i = 0; i < (m_fiberCount - 1); ++i)
-        workQueue.append(m_other.m_fibers[i]);
-    currentFiber = m_other.m_fibers[m_fiberCount - 1];
+        workQueue.append(m_fibers[i]);
+    currentFiber = m_fibers[m_fiberCount - 1];
     while (true) {
         if (RopeImpl::isRope(currentFiber)) {
             RopeImpl* rope = static_cast<RopeImpl*>(currentFiber);
@@ -81,21 +112,21 @@ void JSString::resolveRope(ExecState* exec) const
                 workQueue.append(rope->fibers()[i]);
             currentFiber = rope->fibers()[fiberCountMinusOne];
         } else {
-            UStringImpl* string = static_cast<UStringImpl*>(currentFiber);
+            StringImpl* string = static_cast<StringImpl*>(currentFiber);
             unsigned length = string->length();
             position -= length;
-            UStringImpl::copyChars(position, string->characters(), length);
+            StringImpl::copyChars(position, string->characters(), length);
 
             // Was this the last item in the work queue?
             if (workQueue.isEmpty()) {
                 // Create a string from the UChar buffer, clear the rope RefPtr.
                 ASSERT(buffer == position);
                 for (unsigned i = 0; i < m_fiberCount; ++i) {
-                    RopeImpl::deref(m_other.m_fibers[i]);
-                    m_other.m_fibers[i] = 0;
+                    RopeImpl::deref(m_fibers[i]);
+                    m_fibers[i] = 0;
                 }
                 m_fiberCount = 0;
-
+                
                 ASSERT(!isRope());
                 return;
             }
@@ -106,14 +137,28 @@ void JSString::resolveRope(ExecState* exec) const
         }
     }
 }
-    
+
+void JSString::outOfMemory(ExecState* exec) const
+{
+    for (unsigned i = 0; i < m_fiberCount; ++i) {
+        RopeImpl::deref(m_fibers[i]);
+        m_fibers[i] = 0;
+    }
+    m_fiberCount = 0;
+    ASSERT(!isRope());
+    ASSERT(m_value == UString());
+    if (exec)
+        throwOutOfMemoryError(exec);
+}
+
 // This function construsts a substring out of a rope without flattening by reusing the existing fibers.
 // This can reduce memory usage substantially. Since traversing ropes is slow the function will revert 
 // back to flattening if the rope turns out to be long.
 JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart, unsigned substringLength)
 {
     ASSERT(isRope());
-
+    ASSERT(substringLength);
+    
     JSGlobalData* globalData = &exec->globalData();
 
     UString substringFibers[3];
@@ -124,9 +169,9 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart,
     unsigned fiberEnd = 0;
 
     RopeIterator end;
-    for (RopeIterator it(m_other.m_fibers, m_fiberCount); it != end; ++it) {
+    for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) {
         ++fiberCount;
-        UStringImpl* fiberString = *it;
+        StringImpl* fiberString = *it;
         unsigned fiberStart = fiberEnd;
         fiberEnd = fiberStart + fiberString->length();
         if (fiberEnd <= substringStart)
@@ -136,10 +181,10 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart,
         if (copyStart == fiberStart && copyEnd == fiberEnd)
             substringFibers[substringFiberCount++] = UString(fiberString);
         else
-            substringFibers[substringFiberCount++] = UString(UStringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart));
+            substringFibers[substringFiberCount++] = UString(StringImpl::create(fiberString, copyStart - fiberStart, copyEnd - copyStart));
         if (fiberEnd >= substringEnd)
             break;
-        if (fiberCount > resolveRopeForSubstringCutoff || substringFiberCount >= 3) {
+        if (fiberCount > substringFromRopeCutoff || substringFiberCount >= 3) {
             // This turned out to be a really inefficient rope. Just flatten it.
             resolveRope(exec);
             return jsSubstring(&exec->globalData(), m_value, substringStart, substringLength);
@@ -149,8 +194,8 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart,
 
     if (substringLength == 1) {
         ASSERT(substringFiberCount == 1);
-        UChar c = substringFibers[0].data()[0];
-        if (c <= 0xFF)
+        UChar c = substringFibers[0].characters()[0];
+        if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
     }
     if (substringFiberCount == 1)
@@ -163,26 +208,26 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart,
 JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UString& replacement)
 {
     if (!isRope()) {
-        unsigned matchPosition = m_value.find(character);
-        if (matchPosition == UString::NotFound)
+        size_t matchPosition = m_value.find(character);
+        if (matchPosition == notFound)
             return JSValue(this);
-        return jsString(exec, m_value.substr(0, matchPosition), replacement, m_value.substr(matchPosition + 1));
+        return jsString(exec, m_value.substringSharingImpl(0, matchPosition), replacement, m_value.substringSharingImpl(matchPosition + 1));
     }
 
     RopeIterator end;
     
     // Count total fibers and find matching string.
     size_t fiberCount = 0;
-    UStringImpl* matchString = 0;
-    int matchPosition = -1;
-    for (RopeIterator it(m_other.m_fibers, m_fiberCount); it != end; ++it) {
+    StringImpl* matchString = 0;
+    size_t matchPosition = notFound;
+    for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) {
         ++fiberCount;
         if (matchString)
             continue;
 
-        UStringImpl* string = *it;
+        StringImpl* string = *it;
         matchPosition = string->find(character);
-        if (matchPosition == -1)
+        if (matchPosition == notFound)
             continue;
         matchString = string;
     }
@@ -190,21 +235,21 @@ JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UStri
     if (!matchString)
         return this;
 
-    RopeBuilder builder(replacement.size() ? fiberCount + 2 : fiberCount + 1);
+    RopeBuilder builder(replacement.length() ? fiberCount + 2 : fiberCount + 1);
     if (UNLIKELY(builder.isOutOfMemory()))
         return throwOutOfMemoryError(exec);
 
-    for (RopeIterator it(m_other.m_fibers, m_fiberCount); it != end; ++it) {
-        UStringImpl* string = *it;
+    for (RopeIterator it(m_fibers.data(), m_fiberCount); it != end; ++it) {
+        StringImpl* string = *it;
         if (string != matchString) {
             builder.append(UString(string));
             continue;
         }
 
-        builder.append(UString(string).substr(0, matchPosition));
-        if (replacement.size())
+        builder.append(UString(string).substringSharingImpl(0, matchPosition));
+        if (replacement.length())
             builder.append(replacement);
-        builder.append(UString(string).substr(matchPosition + 1));
+        builder.append(UString(string).substringSharingImpl(matchPosition + 1));
         matchString = 0;
     }
 
@@ -220,7 +265,7 @@ JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i)
     if (exec->exception())
         return jsString(exec, "");
     ASSERT(!isRope());
-    ASSERT(i < m_value.size());
+    ASSERT(i < m_value.length());
     return jsSingleCharacterSubstring(exec, m_value, i);
 }
 
@@ -232,7 +277,7 @@ JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const
 bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
 {
     result = this;
-    number = value(exec).toDouble();
+    number = jsToNumber(value(exec));
     return false;
 }
 
@@ -243,7 +288,7 @@ bool JSString::toBoolean(ExecState*) const
 
 double JSString::toNumber(ExecState* exec) const
 {
-    return value(exec).toDouble();
+    return jsToNumber(value(exec));
 }
 
 UString JSString::toString(ExecState* exec) const
@@ -251,19 +296,19 @@ UString JSString::toString(ExecState* exec) const
     return value(exec);
 }
 
-inline StringObject* StringObject::create(ExecState* exec, JSString* string)
+inline StringObject* StringObject::create(ExecState* exec, JSGlobalObject* globalObject, JSString* string)
 {
-    return new (exec) StringObject(exec->lexicalGlobalObject()->stringObjectStructure(), string);
+    return new (exec) StringObject(exec->globalData(), globalObject->stringObjectStructure(), string);
 }
 
-JSObject* JSString::toObject(ExecState* exec) const
+JSObject* JSString::toObject(ExecState* exec, JSGlobalObject* globalObject) const
 {
-    return StringObject::create(exec, const_cast<JSString*>(this));
+    return StringObject::create(exec, globalObject, const_cast<JSString*>(this));
 }
 
 JSObject* JSString::toThisObject(ExecState* exec) const
 {
-    return StringObject::create(exec, const_cast<JSString*>(this));
+    return StringObject::create(exec, exec->lexicalGlobalObject(), const_cast<JSString*>(this));
 }
 
 bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -290,12 +335,12 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam
 bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
     if (propertyName == exec->propertyNames().length) {
-        descriptor.setDescriptor(jsNumber(exec, m_length), DontEnum | DontDelete | ReadOnly);
+        descriptor.setDescriptor(jsNumber(m_length), DontEnum | DontDelete | ReadOnly);
         return true;
     }
     
     bool isStrictUInt32;
-    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+    unsigned i = propertyName.toUInt32(isStrictUInt32);
     if (isStrictUInt32 && i < m_length) {
         descriptor.setDescriptor(getIndex(exec, i), DontDelete | ReadOnly);
         return true;
index 08d525fd5aa86f96a421e462f03218b0608ce469..668064f854a8030ad383ddc66d11d0c92d732317 100644 (file)
 #include "CallFrame.h"
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
-#include "JSNumberCell.h"
 #include "PropertyDescriptor.h"
 #include "PropertySlot.h"
 #include "RopeImpl.h"
+#include "Structure.h"
 
 namespace JSC {
 
@@ -59,9 +59,6 @@ namespace JSC {
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
-    typedef void (*JSStringFinalizerCallback)(JSString*, void* context);
-    JSString* jsStringWithFinalizer(ExecState*, const UString&, JSStringFinalizerCallback callback, void* context);
-
     class JS_EXPORTCLASS JSString : public JSCell {
     public:
         friend class JIT;
@@ -87,13 +84,13 @@ namespace JSC {
             void append(const UString& string)
             {
                 ASSERT(m_rope);
-                m_rope->initializeFiber(m_index, string.rep());
+                m_rope->initializeFiber(m_index, string.impl());
             }
             void append(JSString* jsString)
             {
                 if (jsString->isRope()) {
                     for (unsigned i = 0; i < jsString->m_fiberCount; ++i)
-                        append(jsString->m_other.m_fibers[i]);
+                        append(jsString->m_fibers[i]);
                 } else
                     append(jsString->string());
             }
@@ -132,12 +129,12 @@ namespace JSC {
                     return *this;
                 }
 
-                UStringImpl* operator*()
+                StringImpl* operator*()
                 {
                     WorkItem& item = m_workQueue.last();
                     RopeImpl::Fiber fiber = item.fibers[item.i];
                     ASSERT(!RopeImpl::isRope(fiber));
-                    return static_cast<UStringImpl*>(fiber);
+                    return static_cast<StringImpl*>(fiber);
                 }
 
                 bool operator!=(const RopeIterator& other) const
@@ -185,26 +182,26 @@ namespace JSC {
         };
 
         ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(value.size())
+            : JSCell(*globalData, globalData->stringStructure.get())
+            , m_length(value.length())
             , m_value(value)
             , m_fiberCount(0)
         {
             ASSERT(!m_value.isNull());
-            Heap::heap(this)->reportExtraMemoryCost(value.cost());
+            Heap::heap(this)->reportExtraMemoryCost(value.impl()->cost());
         }
 
         enum HasOtherOwnerType { HasOtherOwner };
         JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(value.size())
+            : JSCell(*globalData, globalData->stringStructure.get())
+            , m_length(value.length())
             , m_value(value)
             , m_fiberCount(0)
         {
             ASSERT(!m_value.isNull());
         }
-        JSString(JSGlobalData* globalData, PassRefPtr<UStringImpl> value, HasOtherOwnerType)
-            : JSCell(globalData->stringStructure.get())
+        JSString(JSGlobalData* globalData, PassRefPtr<StringImpl> value, HasOtherOwnerType)
+            : JSCell(*globalData, globalData->stringStructure.get())
             , m_length(value->length())
             , m_value(value)
             , m_fiberCount(0)
@@ -212,16 +209,16 @@ namespace JSC {
             ASSERT(!m_value.isNull());
         }
         JSString(JSGlobalData* globalData, PassRefPtr<RopeImpl> rope)
-            : JSCell(globalData->stringStructure.get())
+            : JSCell(*globalData, globalData->stringStructure.get())
             , m_length(rope->length())
             , m_fiberCount(1)
         {
-            m_other.m_fibers[0] = rope.releaseRef();
+            m_fibers[0] = rope.leakRef();
         }
         // This constructor constructs a new string by concatenating s1 & s2.
         // This should only be called with fiberCount <= 3.
         JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, JSString* s2)
-            : JSCell(globalData->stringStructure.get())
+            : JSCell(*globalData, globalData->stringStructure.get())
             , m_length(s1->length() + s2->length())
             , m_fiberCount(fiberCount)
         {
@@ -234,8 +231,8 @@ namespace JSC {
         // This constructor constructs a new string by concatenating s1 & s2.
         // This should only be called with fiberCount <= 3.
         JSString(JSGlobalData* globalData, unsigned fiberCount, JSString* s1, const UString& u2)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(s1->length() + u2.size())
+            : JSCell(*globalData, globalData->stringStructure.get())
+            , m_length(s1->length() + u2.length())
             , m_fiberCount(fiberCount)
         {
             ASSERT(fiberCount <= s_maxInternalRopeLength);
@@ -247,8 +244,8 @@ namespace JSC {
         // This constructor constructs a new string by concatenating s1 & s2.
         // This should only be called with fiberCount <= 3.
         JSString(JSGlobalData* globalData, unsigned fiberCount, const UString& u1, JSString* s2)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(u1.size() + s2->length())
+            : JSCell(*globalData, globalData->stringStructure.get())
+            , m_length(u1.length() + s2->length())
             , m_fiberCount(fiberCount)
         {
             ASSERT(fiberCount <= s_maxInternalRopeLength);
@@ -262,7 +259,7 @@ namespace JSC {
         // value must require a fiberCount of at least one implies that the length
         // for each value must be exactly 1!
         JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3)
-            : JSCell(exec->globalData().stringStructure.get())
+            : JSCell(exec->globalData(), exec->globalData().stringStructure.get())
             , m_length(0)
             , m_fiberCount(s_maxInternalRopeLength)
         {
@@ -275,8 +272,8 @@ namespace JSC {
 
         // This constructor constructs a new string by concatenating u1 & u2.
         JSString(JSGlobalData* globalData, const UString& u1, const UString& u2)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(u1.size() + u2.size())
+            : JSCell(*globalData, globalData->stringStructure.get())
+            , m_length(u1.length() + u2.length())
             , m_fiberCount(2)
         {
             unsigned index = 0;
@@ -287,8 +284,8 @@ namespace JSC {
 
         // This constructor constructs a new string by concatenating u1, u2 & u3.
         JSString(JSGlobalData* globalData, const UString& u1, const UString& u2, const UString& u3)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(u1.size() + u2.size() + u3.size())
+            : JSCell(*globalData, globalData->stringStructure.get())
+            , m_length(u1.length() + u2.length() + u3.length())
             , m_fiberCount(s_maxInternalRopeLength)
         {
             unsigned index = 0;
@@ -298,27 +295,11 @@ namespace JSC {
             ASSERT(index <= s_maxInternalRopeLength);
         }
 
-        JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context)
-            : JSCell(globalData->stringStructure.get())
-            , m_length(value.size())
-            , m_value(value)
-            , m_fiberCount(0)
-        {
-            ASSERT(!m_value.isNull());
-            // nasty hack because we can't union non-POD types
-            m_other.m_finalizerCallback = finalizer;
-            m_other.m_finalizerContext = context;
-            Heap::heap(this)->reportExtraMemoryCost(value.cost());
-        }
-
         ~JSString()
         {
             ASSERT(vptr() == JSGlobalData::jsStringVPtr);
             for (unsigned i = 0; i < m_fiberCount; ++i)
-                RopeImpl::deref(m_other.m_fibers[i]);
-
-            if (!m_fiberCount && m_other.m_finalizerCallback)
-                m_other.m_finalizerCallback(this, m_other.m_finalizerContext);
+                RopeImpl::deref(m_fibers[i]);
         }
 
         const UString& value(ExecState* exec) const
@@ -345,33 +326,39 @@ namespace JSC {
 
         JSValue replaceCharacter(ExecState*, UChar, const UString& replacement);
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); }
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto)
+        {
+            return Structure::create(globalData, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount, &s_info);
+        }
+        
+        static const ClassInfo s_info;
 
     private:
-        enum VPtrStealingHackType { VPtrStealingHack };
         JSString(VPtrStealingHackType) 
-            : JSCell(0)
+            : JSCell(VPtrStealingHack)
             , m_fiberCount(0)
         {
         }
 
         void resolveRope(ExecState*) const;
+        void resolveRopeSlowCase(ExecState*, UChar*) const;
+        void outOfMemory(ExecState*) const;
         JSString* substringFromRope(ExecState*, unsigned offset, unsigned length);
 
         void appendStringInConstruct(unsigned& index, const UString& string)
         {
-            UStringImpl* impl = string.rep();
+            StringImpl* impl = string.impl();
             impl->ref();
-            m_other.m_fibers[index++] = impl;
+            m_fibers[index++] = impl;
         }
 
         void appendStringInConstruct(unsigned& index, JSString* jsString)
         {
             if (jsString->isRope()) {
                 for (unsigned i = 0; i < jsString->m_fiberCount; ++i) {
-                    RopeImpl::Fiber fiber = jsString->m_other.m_fibers[i];
+                    RopeImpl::Fiber fiber = jsString->m_fibers[i];
                     fiber->ref();
-                    m_other.m_fibers[index++] = fiber;
+                    m_fibers[index++] = fiber;
                 }
             } else
                 appendStringInConstruct(index, jsString->string());
@@ -380,17 +367,17 @@ namespace JSC {
         void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
         {
             if (v.isString()) {
-                ASSERT(asCell(v)->isString());
-                JSString* s = static_cast<JSString*>(asCell(v));
-                ASSERT(s->size() == 1);
+                ASSERT(v.asCell()->isString());
+                JSString* s = static_cast<JSString*>(v.asCell());
+                ASSERT(s->fiberCount() == 1);
                 appendStringInConstruct(index, s);
                 m_length += s->length();
             } else {
                 UString u(v.toString(exec));
-                UStringImpl* impl = u.rep();
+                StringImpl* impl = u.impl();
                 impl->ref();
-                m_other.m_fibers[index++] = impl;
-                m_length += u.size();
+                m_fibers[index++] = impl;
+                m_length += u.length();
             }
         }
 
@@ -398,7 +385,7 @@ namespace JSC {
         virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value);
         virtual bool toBoolean(ExecState*) const;
         virtual double toNumber(ExecState*) const;
-        virtual JSObject* toObject(ExecState*) const;
+        virtual JSObject* toObject(ExecState*, JSGlobalObject*) const;
         virtual UString toString(ExecState*) const;
 
         virtual JSObject* toThisObject(ExecState*) const;
@@ -414,28 +401,17 @@ namespace JSC {
         unsigned m_length;
         mutable UString m_value;
         mutable unsigned m_fiberCount;
-        // This structure exists to support a temporary workaround for a GC issue.
-        struct JSStringFinalizerStruct {
-            JSStringFinalizerStruct() : m_finalizerCallback(0) {}
-            union {
-                mutable RopeImpl::Fiber m_fibers[s_maxInternalRopeLength];
-                struct {
-                    JSStringFinalizerCallback m_finalizerCallback;
-                    void* m_finalizerContext;
-                };
-            };
-        } m_other;
+        mutable FixedArray<RopeImpl::Fiber, s_maxInternalRopeLength> m_fibers;
 
         bool isRope() const { return m_fiberCount; }
         UString& string() { ASSERT(!isRope()); return m_value; }
-        unsigned size() { return m_fiberCount ? m_fiberCount : 1; }
+        unsigned fiberCount() { return m_fiberCount ? m_fiberCount : 1; }
 
         friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2);
         friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2);
         friend JSValue jsString(ExecState* exec, JSString* s1, const UString& u2);
         friend JSValue jsString(ExecState* exec, Register* strings, unsigned count);
-        friend JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args);
-        friend JSString* jsStringWithFinalizer(ExecState*, const UString&, JSStringFinalizerCallback callback, void* context);
+        friend JSValue jsString(ExecState* exec, JSValue thisValue);
         friend JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length);
     };
 
@@ -453,8 +429,8 @@ namespace JSC {
 
     inline JSString* asString(JSValue value)
     {
-        ASSERT(asCell(value)->isString());
-        return static_cast<JSString*>(asCell(value));
+        ASSERT(value.asCell()->isString());
+        return static_cast<JSString*>(value.asCell());
     }
 
     inline JSString* jsEmptyString(JSGlobalData* globalData)
@@ -464,7 +440,7 @@ namespace JSC {
 
     inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
     {
-        if (c <= 0xFF)
+        if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
         return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1)));
     }
@@ -472,11 +448,11 @@ namespace JSC {
     inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset)
     {
         JSGlobalData* globalData = &exec->globalData();
-        ASSERT(offset < static_cast<unsigned>(s.size()));
-        UChar c = s.data()[offset];
-        if (c <= 0xFF)
+        ASSERT(offset < static_cast<unsigned>(s.length()));
+        UChar c = s.characters()[offset];
+        if (c <= maxSingleCharacterString)
             return globalData->smallStrings.singleCharacterString(globalData, c);
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UStringImpl::create(s.rep(), offset, 1))));
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, 1))));
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
@@ -489,7 +465,7 @@ namespace JSC {
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
-        ASSERT(s.size() > 1);
+        ASSERT(s.length() > 1);
         return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
     }
 
@@ -498,30 +474,23 @@ namespace JSC {
         ASSERT(canGetIndex(i));
         if (isRope())
             return getIndexSlowCase(exec, i);
-        ASSERT(i < m_value.size());
+        ASSERT(i < m_value.length());
         return jsSingleCharacterSubstring(exec, m_value, i);
     }
 
     inline JSString* jsString(JSGlobalData* globalData, const UString& s)
     {
-        int size = s.size();
+        int size = s.length();
         if (!size)
             return globalData->smallStrings.emptyString(globalData);
         if (size == 1) {
-            UChar c = s.data()[0];
-            if (c <= 0xFF)
+            UChar c = s.characters()[0];
+            if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
         return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
     }
 
-    inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context)
-    {
-        ASSERT(s.size() && (s.size() > 1 || s.data()[0] > 0xFF));
-        JSGlobalData* globalData = &exec->globalData();
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context));
-    }
-    
     inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length)
     {
         ASSERT(offset <= static_cast<unsigned>(s->length()));
@@ -537,27 +506,27 @@ namespace JSC {
 
     inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
     {
-        ASSERT(offset <= static_cast<unsigned>(s.size()));
-        ASSERT(length <= static_cast<unsigned>(s.size()));
-        ASSERT(offset + length <= static_cast<unsigned>(s.size()));
+        ASSERT(offset <= static_cast<unsigned>(s.length()));
+        ASSERT(length <= static_cast<unsigned>(s.length()));
+        ASSERT(offset + length <= static_cast<unsigned>(s.length()));
         if (!length)
             return globalData->smallStrings.emptyString(globalData);
         if (length == 1) {
-            UChar c = s.data()[offset];
-            if (c <= 0xFF)
+            UChar c = s.characters()[offset];
+            if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
-        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UStringImpl::create(s.rep(), offset, length)), JSString::HasOtherOwner));
+        return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(StringImpl::create(s.impl(), offset, length)), JSString::HasOtherOwner));
     }
 
     inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s)
     {
-        int size = s.size();
+        int size = s.length();
         if (!size)
             return globalData->smallStrings.emptyString(globalData);
         if (size == 1) {
-            UChar c = s.data()[0];
-            if (c <= 0xFF)
+            UChar c = s.characters()[0];
+            if (c <= maxSingleCharacterString)
                 return globalData->smallStrings.singleCharacterString(globalData, c);
         }
         return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner));
@@ -574,12 +543,12 @@ namespace JSC {
     ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
     {
         if (propertyName == exec->propertyNames().length) {
-            slot.setValue(jsNumber(exec, m_length));
+            slot.setValue(jsNumber(m_length));
             return true;
         }
 
         bool isStrictUInt32;
-        unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+        unsigned i = propertyName.toUInt32(isStrictUInt32);
         if (isStrictUInt32 && i < m_length) {
             slot.setValue(getIndex(exec, i));
             return true;
@@ -624,8 +593,7 @@ namespace JSC {
 
     inline UString JSValue::toPrimitiveString(ExecState* exec) const
     {
-        if (isString())
-            return static_cast<JSString*>(asCell())->value(exec);
+        ASSERT(!isString());
         if (isInt32())
             return exec->globalData().numericStrings.add(asInt32());
         if (isDouble())
index 8f208a1f31e14e0657b7564c4b536b34f878b7ec..49d4a6377735ec9a0bb06beb1c2588be2fec973b 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "ExceptionHelpers.h"
 #include "JSString.h"
+#include "UStringConcatenate.h"
 #include "Vector.h"
 
 namespace JSC {
@@ -65,7 +66,7 @@ public:
 
     void append(const UString& str)
     {
-        m_okay &= buffer.tryAppend(str.data(), str.size());
+        m_okay &= buffer.tryAppend(str.characters(), str.length());
     }
 
     JSValue build(ExecState* exec)
@@ -86,7 +87,7 @@ protected:
 template<typename StringType1, typename StringType2>
 inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2)
 {
-    PassRefPtr<UStringImpl> result = tryMakeString(string1, string2);
+    PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2);
     if (!result)
         return throwOutOfMemoryError(exec);
     return jsNontrivialString(exec, result);
@@ -95,7 +96,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri
 template<typename StringType1, typename StringType2, typename StringType3>
 inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3)
 {
-    PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3);
+    PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3);
     if (!result)
         return throwOutOfMemoryError(exec);
     return jsNontrivialString(exec, result);
@@ -104,7 +105,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
 inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
 {
-    PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4);
+    PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4);
     if (!result)
         return throwOutOfMemoryError(exec);
     return jsNontrivialString(exec, result);
@@ -113,7 +114,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
 inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
 {
-    PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4, string5);
+    PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5);
     if (!result)
         return throwOutOfMemoryError(exec);
     return jsNontrivialString(exec, result);
@@ -122,7 +123,7 @@ inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, Stri
 template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
 inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
 {
-    PassRefPtr<UStringImpl> result = tryMakeString(string1, string2, string3, string4, string5, string6);
+    PassRefPtr<StringImpl> result = WTF::tryMakeString(string1, string2, string3, string4, string5, string6);
     if (!result)
         return throwOutOfMemoryError(exec);
     return jsNontrivialString(exec, result);
index 882b2188e97b886eb484437dc4cdefc35f9ab192..dba03f63d148a4dba35d605a43d54fe46ddad01e 100644 (file)
@@ -33,10 +33,11 @@ namespace JSC {
         NumberType        = 3,
         NullType          = 4,
         StringType        = 5,
+        LeafType          = 6,
         // The CompoundType value must come before any JSType that may have children
-        CompoundType      = 6,
-        ObjectType        = 7,
-        GetterSetterType  = 8
+        CompoundType      = 7,
+        ObjectType        = 8,
+        GetterSetterType  = 9
     };
 
 } // namespace JSC
index e225bc72ce78a6958f004329e930bc051ba88e8b..1c63a91e7870b02f142b4deca0e657cada284aa5 100644 (file)
 
 namespace JSC {
 
-    // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
-    static const unsigned MasqueradesAsUndefined = 1;
+    static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all and style.filter undetectable.
     static const unsigned ImplementsHasInstance = 1 << 1;
     static const unsigned OverridesHasInstance = 1 << 2;
     static const unsigned ImplementsDefaultHasInstance = 1 << 3;
     static const unsigned NeedsThisConversion = 1 << 4;
     static const unsigned OverridesGetOwnPropertySlot = 1 << 5;
-    static const unsigned OverridesMarkChildren = 1 << 6;
+    static const unsigned OverridesVisitChildren = 1 << 6;
     static const unsigned OverridesGetPropertyNames = 1 << 7;
+    static const unsigned IsJSFinalObject = 1 << 8;
+    static const unsigned ProhibitsPropertyCaching = 1 << 9;
 
     class TypeInfo {
-        friend class JIT;
     public:
         TypeInfo(JSType type, unsigned flags = 0)
             : m_type(type)
+            , m_flags(flags & 0xff)
+            , m_flags2(flags >> 8)
         {
-            ASSERT(flags <= 0xFF);
-            ASSERT(type <= 0xFF);
+            ASSERT(flags <= 0x3ff);
+            ASSERT(type <= 0xff);
+            ASSERT(type >= CompoundType || !(flags & OverridesVisitChildren));
             // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance)
-            if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
-                m_flags = flags | ImplementsDefaultHasInstance;
-            else
-                m_flags = flags;
+            if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance)
+                m_flags |= ImplementsDefaultHasInstance;
         }
 
         JSType type() const { return (JSType)m_type; }
@@ -66,13 +67,26 @@ namespace JSC {
         bool overridesHasInstance() const { return m_flags & OverridesHasInstance; }
         bool needsThisConversion() const { return m_flags & NeedsThisConversion; }
         bool overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; }
-        bool overridesMarkChildren() const { return m_flags & OverridesMarkChildren; }
+        bool overridesVisitChildren() const { return m_flags & OverridesVisitChildren; }
         bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; }
+        unsigned isFinal() const { return m_flags2 & (IsJSFinalObject >> 8); }
+        unsigned prohibitsPropertyCaching() const { return m_flags2 & (ProhibitsPropertyCaching >> 8); }
         unsigned flags() const { return m_flags; }
 
+        static ptrdiff_t flagsOffset()
+        {
+            return OBJECT_OFFSETOF(TypeInfo, m_flags);
+        }
+
+        static ptrdiff_t typeOffset()
+        {
+            return OBJECT_OFFSETOF(TypeInfo, m_type);
+        }
+
     private:
         unsigned char m_type;
         unsigned char m_flags;
+        unsigned char m_flags2;
     };
 
 }
index 502312caeaac6b1415c9f7c7a17010fe89102bd2..d3ee89ea86b75d9bb7714110b5084488aa7a060f 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "BooleanConstructor.h"
 #include "BooleanPrototype.h"
+#include "Error.h"
 #include "ExceptionHelpers.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
@@ -53,18 +54,18 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const
     return trunc(toNumber(exec));
 }
 
-JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
+JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
 {
     ASSERT(!isCell());
 
     if (isInt32() || isDouble())
-        return constructNumber(exec, asValue());
+        return constructNumber(exec, globalObject, asValue());
     if (isTrue() || isFalse())
-        return constructBooleanFromImmediateBoolean(exec, asValue());
+        return constructBooleanFromImmediateBoolean(exec, globalObject, asValue());
+
     ASSERT(isUndefinedOrNull());
-    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
-    exec->setException(exception);
-    return new (exec) JSNotAnObject(exec, exception);
+    throwError(exec, createNotAnObjectError(exec, *this));
+    return new (exec) JSNotAnObject(exec);
 }
 
 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
@@ -72,9 +73,9 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
     ASSERT(!isCell());
 
     if (isInt32() || isDouble())
-        return constructNumber(exec, asValue());
+        return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
     if (isTrue() || isFalse())
-        return constructBooleanFromImmediateBoolean(exec, asValue());
+        return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
     ASSERT(isUndefinedOrNull());
     return exec->globalThisValue();
 }
@@ -83,13 +84,13 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const
 {
     ASSERT(!isCell());
     if (isNumber())
-        return constructNumber(exec, asValue());
+        return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
     if (isBoolean())
-        return constructBooleanFromImmediateBoolean(exec, asValue());
-    
-    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
-    exec->setException(exception);
-    return new (exec) JSNotAnObject(exec, exception);
+        return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
+
+    ASSERT(isUndefinedOrNull());
+    throwError(exec, createNotAnObjectError(exec, *this));
+    return new (exec) JSNotAnObject(exec);
 }
 
 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
@@ -100,9 +101,9 @@ JSObject* JSValue::synthesizePrototype(ExecState* exec) const
     if (isBoolean())
         return exec->lexicalGlobalObject()->booleanPrototype();
 
-    JSNotAnObjectErrorStub* exception = createNotAnObjectErrorStub(exec, isNull());
-    exec->setException(exception);
-    return new (exec) JSNotAnObject(exec, exception);
+    ASSERT(isUndefinedOrNull());
+    throwError(exec, createNotAnObjectError(exec, *this));
+    return new (exec) JSNotAnObject(exec);
 }
 
 #ifndef NDEBUG
@@ -125,51 +126,58 @@ char* JSValue::description()
         snprintf(description, size, "False");
     else if (isNull())
         snprintf(description, size, "Null");
-    else {
-        ASSERT(isUndefined());
+    else if (isUndefined())
         snprintf(description, size, "Undefined");
-    }
+    else
+        snprintf(description, size, "INVALID");
 
     return description;
 }
 #endif
 
-int32_t toInt32SlowCase(double d, bool& ok)
+// This in the ToInt32 operation is defined in section 9.5 of the ECMA-262 spec.
+// Note that this operation is identical to ToUInt32 other than to interpretation
+// of the resulting bit-pattern (as such this metod is also called to implement
+// ToUInt32).
+//
+// The operation can be descibed as round towards zero, then select the 32 least
+// bits of the resulting value in 2s-complement representation.
+int32_t toInt32(double number)
 {
-    ok = true;
-
-    if (d >= -D32 / 2 && d < D32 / 2)
-        return static_cast<int32_t>(d);
-
-    if (isnan(d) || isinf(d)) {
-        ok = false;
+    int64_t bits = WTF::bitwise_cast<int64_t>(number);
+    int32_t exp = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff;
+
+    // If exponent < 0 there will be no bits to the left of the decimal point
+    // after rounding; if the exponent is > 83 then no bits of precision can be
+    // left in the low 32-bit range of the result (IEEE-754 doubles have 52 bits
+    // of fractional precision).
+    // Note this case handles 0, -0, and all infinte, NaN, & denormal value. 
+    if (exp < 0 || exp > 83)
         return 0;
-    }
 
-    double d32 = fmod(trunc(d), D32);
-    if (d32 >= D32 / 2)
-        d32 -= D32;
-    else if (d32 < -D32 / 2)
-        d32 += D32;
-    return static_cast<int32_t>(d32);
-}
-
-uint32_t toUInt32SlowCase(double d, bool& ok)
-{
-    ok = true;
-
-    if (d >= 0.0 && d < D32)
-        return static_cast<uint32_t>(d);
-
-    if (isnan(d) || isinf(d)) {
-        ok = false;
-        return 0;
+    // Select the appropriate 32-bits from the floating point mantissa.  If the
+    // exponent is 52 then the bits we need to select are already aligned to the
+    // lowest bits of the 64-bit integer representation of tghe number, no need
+    // to shift.  If the exponent is greater than 52 we need to shift the value
+    // left by (exp - 52), if the value is less than 52 we need to shift right
+    // accordingly.
+    int32_t result = (exp > 52)
+        ? static_cast<int32_t>(bits << (exp - 52))
+        : static_cast<int32_t>(bits >> (52 - exp));
+
+    // IEEE-754 double precision values are stored omitting an implicit 1 before
+    // the decimal point; we need to reinsert this now.  We may also the shifted
+    // invalid bits into the result that are not a part of the mantissa (the sign
+    // and exponent bits from the floatingpoint representation); mask these out.
+    if (exp < 32) {
+        int32_t missingOne = 1 << exp;
+        result &= missingOne - 1;
+        result += missingOne;
     }
 
-    double d32 = fmod(trunc(d), D32);
-    if (d32 < 0)
-        d32 += D32;
-    return static_cast<uint32_t>(d32);
+    // If the input value was negative (we could test either 'number' or 'bits',
+    // but testing 'bits' is likely faster) invert the result appropriately.
+    return bits < 0 ? -result : result;
 }
 
 NEVER_INLINE double nonInlineNaN()
@@ -181,4 +189,9 @@ NEVER_INLINE double nonInlineNaN()
 #endif
 }
 
+bool JSValue::isValidCallee()
+{
+    return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject();
+}
+
 } // namespace JSC
index 283b3da942f5dd6f27f21928b760c9fe72c2aedb..de50011327c0dc2a1e50e3c49f3f9d3edafcc3cf 100644 (file)
@@ -23,8 +23,6 @@
 #ifndef JSValue_h
 #define JSValue_h
 
-#include "CallData.h"
-#include "ConstructData.h"
 #include <math.h>
 #include <stddef.h> // for size_t
 #include <stdint.h>
 #include <wtf/Assertions.h>
 #include <wtf/HashTraits.h>
 #include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
+    extern const double NaN;
+    extern const double Inf;
+
+    class ExecState;
     class Identifier;
     class JSCell;
     class JSGlobalData;
-    class JSImmediate;
+    class JSGlobalObject;
     class JSObject;
     class JSString;
     class PropertySlot;
@@ -48,20 +51,52 @@ namespace JSC {
     struct ClassInfo;
     struct Instruction;
 
+    template <class T> class WriteBarrierBase;
+
     enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
 
+
 #if USE(JSVALUE32_64)
     typedef int64_t EncodedJSValue;
 #else
     typedef void* EncodedJSValue;
 #endif
+    
+    union EncodedValueDescriptor {
+        int64_t asInt64;
+#if USE(JSVALUE32_64)
+        double asDouble;
+#elif USE(JSVALUE64)
+        JSCell* ptr;
+#endif
+        
+#if CPU(BIG_ENDIAN)
+        struct {
+            int32_t tag;
+            int32_t payload;
+        } asBits;
+#else
+        struct {
+            int32_t payload;
+            int32_t tag;
+        } asBits;
+#endif
+    };
 
     double nonInlineNaN();
-    int32_t toInt32SlowCase(double, bool& ok);
-    uint32_t toUInt32SlowCase(double, bool& ok);
+
+    // This implements ToInt32, defined in ECMA-262 9.5.
+    int32_t toInt32(double);
+
+    // This implements ToUInt32, defined in ECMA-262 9.6.
+    inline uint32_t toUInt32(double number)
+    {
+        // As commented in the spec, the operation of ToInt32 and ToUint32 only differ
+        // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6.
+        return toInt32(number);
+    }
 
     class JSValue {
-        friend class JSImmediate;
         friend struct EncodedJSValueHashTraits;
         friend class JIT;
         friend class JITStubs;
@@ -70,14 +105,9 @@ namespace JSC {
         friend class SpecializedThunkJIT;
 
     public:
-        static EncodedJSValue encode(JSValue value);
-        static JSValue decode(EncodedJSValue ptr);
-#if !USE(JSVALUE32_64)
-    private:
-        static JSValue makeImmediate(intptr_t value);
-        intptr_t immediateValue();
-    public:
-#endif
+        static EncodedJSValue encode(JSValue);
+        static JSValue decode(EncodedJSValue);
+
         enum JSNullTag { JSNull };
         enum JSUndefinedTag { JSUndefined };
         enum JSTrueTag { JSTrue };
@@ -93,21 +123,18 @@ namespace JSC {
         JSValue(const JSCell* ptr);
 
         // Numbers
-        JSValue(EncodeAsDoubleTag, ExecState*, double);
-        JSValue(ExecState*, double);
-        JSValue(ExecState*, char);
-        JSValue(ExecState*, unsigned char);
-        JSValue(ExecState*, short);
-        JSValue(ExecState*, unsigned short);
-        JSValue(ExecState*, int);
-        JSValue(ExecState*, unsigned);
-        JSValue(ExecState*, long);
-        JSValue(ExecState*, unsigned long);
-        JSValue(ExecState*, long long);
-        JSValue(ExecState*, unsigned long long);
-        JSValue(JSGlobalData*, double);
-        JSValue(JSGlobalData*, int);
-        JSValue(JSGlobalData*, unsigned);
+        JSValue(EncodeAsDoubleTag, double);
+        explicit JSValue(double);
+        explicit JSValue(char);
+        explicit JSValue(unsigned char);
+        explicit JSValue(short);
+        explicit JSValue(unsigned short);
+        explicit JSValue(int);
+        explicit JSValue(unsigned);
+        explicit JSValue(long);
+        explicit JSValue(unsigned long);
+        explicit JSValue(long long);
+        explicit JSValue(unsigned long long);
 
         operator bool() const;
         bool operator==(const JSValue& other) const;
@@ -143,9 +170,6 @@ namespace JSC {
         UString getString(ExecState* exec) const; // null string if not a string
         JSObject* getObject() const; // 0 if not an object
 
-        CallType getCallData(CallData&);
-        ConstructType getConstructData(ConstructData&);
-
         // Extracting integer values.
         bool getUInt32(uint32_t&) const;
         
@@ -162,14 +186,13 @@ namespace JSC {
         UString toString(ExecState*) const;
         UString toPrimitiveString(ExecState*) const;
         JSObject* toObject(ExecState*) const;
+        JSObject* toObject(ExecState*, JSGlobalObject*) const;
 
         // Integer conversions.
         double toInteger(ExecState*) const;
         double toIntegerPreserveNaN(ExecState*) const;
         int32_t toInt32(ExecState*) const;
-        int32_t toInt32(ExecState*, bool& ok) const;
         uint32_t toUInt32(ExecState*) const;
-        uint32_t toUInt32(ExecState*, bool& ok) const;
 
 #if ENABLE(JSC_ZOMBIES)
         bool isZombie() const;
@@ -190,6 +213,7 @@ namespace JSC {
 
         bool needsThisConversion() const;
         JSObject* toThisObject(ExecState*) const;
+        JSValue toStrictThisObject(ExecState*) const;
         UString toThisString(ExecState*) const;
         JSString* toThisJSString(ExecState*) const;
 
@@ -204,55 +228,140 @@ namespace JSC {
 
         bool isCell() const;
         JSCell* asCell() const;
+        bool isValidCallee();
 
 #ifndef NDEBUG
         char* description();
 #endif
 
     private:
+        template <class T> JSValue(WriteBarrierBase<T>);
+
         enum HashTableDeletedValueTag { HashTableDeletedValue };
         JSValue(HashTableDeletedValueTag);
 
         inline const JSValue asValue() const { return *this; }
-        JSObject* toObjectSlowCase(ExecState*) const;
+        JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
         JSObject* toThisObjectSlowCase(ExecState*) const;
 
         JSObject* synthesizePrototype(ExecState*) const;
         JSObject* synthesizeObject(ExecState*) const;
 
 #if USE(JSVALUE32_64)
+        /*
+         * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded
+         * form for immediates.
+         *
+         * The encoding makes use of unused NaN space in the IEEE754 representation.  Any value
+         * with the top 13 bits set represents a QNaN (with the sign bit set).  QNaN values
+         * can encode a 51-bit payload.  Hardware produced and C-library payloads typically
+         * have a payload of zero.  We assume that non-zero payloads are available to encode
+         * pointer and integer values.  Since any 64-bit bit pattern where the top 15 bits are
+         * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+         * ranges to encode other values (however there are also other ranges of NaN space that
+         * could have been selected).
+         *
+         * For JSValues that do not contain a double value, the high 32 bits contain the tag
+         * values listed in the enums below, which all correspond to NaN-space. In the case of
+         * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer
+         * integer or boolean value; in the case of all other tags the payload is 0.
+         */
         enum { Int32Tag =        0xffffffff };
-        enum { CellTag =         0xfffffffe };
-        enum { TrueTag =         0xfffffffd };
-        enum { FalseTag =        0xfffffffc };
-        enum { NullTag =         0xfffffffb };
-        enum { UndefinedTag =    0xfffffffa };
-        enum { EmptyValueTag =   0xfffffff9 };
-        enum { DeletedValueTag = 0xfffffff8 };
-        
+        enum { BooleanTag =      0xfffffffe };
+        enum { NullTag =         0xfffffffd };
+        enum { UndefinedTag =    0xfffffffc };
+        enum { CellTag =         0xfffffffb };
+        enum { EmptyValueTag =   0xfffffffa };
+        enum { DeletedValueTag = 0xfffffff9 };
+
         enum { LowestTag =  DeletedValueTag };
-        
+
         uint32_t tag() const;
         int32_t payload() const;
-
-        union {
-            EncodedJSValue asEncodedJSValue;
-            double asDouble;
-#if CPU(BIG_ENDIAN)
-            struct {
-                int32_t tag;
-                int32_t payload;
-            } asBits;
-#else
-            struct {
-                int32_t payload;
-                int32_t tag;
-            } asBits;
+#elif USE(JSVALUE64)
+        /*
+         * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded
+         * form for immediates.
+         *
+         * The encoding makes use of unused NaN space in the IEEE754 representation.  Any value
+         * with the top 13 bits set represents a QNaN (with the sign bit set).  QNaN values
+         * can encode a 51-bit payload.  Hardware produced and C-library payloads typically
+         * have a payload of zero.  We assume that non-zero payloads are available to encode
+         * pointer and integer values.  Since any 64-bit bit pattern where the top 15 bits are
+         * all set represents a NaN with a non-zero payload, we can use this space in the NaN
+         * ranges to encode other values (however there are also other ranges of NaN space that
+         * could have been selected).
+         *
+         * This range of NaN space is represented by 64-bit numbers begining with the 16-bit
+         * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision
+         * numbers will begin fall in these ranges.
+         *
+         * The top 16-bits denote the type of the encoded JSValue:
+         *
+         *     Pointer {  0000:PPPP:PPPP:PPPP
+         *              / 0001:****:****:****
+         *     Double  {         ...
+         *              \ FFFE:****:****:****
+         *     Integer {  FFFF:0000:IIII:IIII
+         *
+         * The scheme we have implemented encodes double precision values by performing a
+         * 64-bit integer addition of the value 2^48 to the number. After this manipulation
+         * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF.
+         * Values must be decoded by reversing this operation before subsequent floating point
+         * operations my be peformed.
+         *
+         * 32-bit signed integers are marked with the 16-bit tag 0xFFFF.
+         *
+         * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean,
+         * null and undefined values are represented by specific, invalid pointer values:
+         *
+         *     False:     0x06
+         *     True:      0x07
+         *     Undefined: 0x0a
+         *     Null:      0x02
+         *
+         * These values have the following properties:
+         * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be
+         *   quickly distinguished from all immediate values, including these invalid pointers.
+         * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the
+         *   same value, allowing null & undefined to be quickly detected.
+         *
+         * No valid JSValue will have the bit pattern 0x0, this is used to represent array
+         * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0).
+         */
+
+        // These values are #defines since using static const integers here is a ~1% regression!
+
+        // This value is 2^48, used to encode doubles such that the encoded value will begin
+        // with a 16-bit pattern within the range 0x0001..0xFFFE.
+        #define DoubleEncodeOffset 0x1000000000000ll
+        // If all bits in the mask are set, this indicates an integer number,
+        // if any but not all are set this value is a double precision number.
+        #define TagTypeNumber 0xffff000000000000ll
+
+        // All non-numeric (bool, null, undefined) immediates have bit 2 set.
+        #define TagBitTypeOther 0x2ll
+        #define TagBitBool      0x4ll
+        #define TagBitUndefined 0x8ll
+        // Combined integer value for non-numeric immediates.
+        #define ValueFalse     (TagBitTypeOther | TagBitBool | false)
+        #define ValueTrue      (TagBitTypeOther | TagBitBool | true)
+        #define ValueUndefined (TagBitTypeOther | TagBitUndefined)
+        #define ValueNull      (TagBitTypeOther)
+
+        // TagMask is used to check for all types of immediate values (either number or 'other').
+        #define TagMask (TagTypeNumber | TagBitTypeOther)
+
+        // These special values are never visible to JavaScript code; Empty is used to represent
+        // Array holes, and for uninitialized JSValues. Deleted is used in hash table code.
+        // These values would map to cell types in the JSValue encoding, but not valid GC cell
+        // pointer should have either of these values (Empty is null, deleted is at an invalid
+        // alignment for a GC cell, and in the zero page).
+        #define ValueEmpty   0x0ll
+        #define ValueDeleted 0x4ll
 #endif
-        } u;
-#else // USE(JSVALUE32_64)
-        JSCell* m_ptr;
-#endif // USE(JSVALUE32_64)
+
+        EncodedValueDescriptor u;
     };
 
 #if USE(JSVALUE32_64)
@@ -289,79 +398,64 @@ namespace JSC {
         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
     }
 
-    ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d)
-    {
-        return JSValue(JSValue::EncodeAsDouble, exec, d);
-    }
-
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d)
-    {
-        return JSValue(exec, d);
-    }
-
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, char i)
-    {
-        return JSValue(exec, i);
-    }
-
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned char i)
+    ALWAYS_INLINE JSValue jsDoubleNumber(double d)
     {
-        return JSValue(exec, i);
+        return JSValue(JSValue::EncodeAsDouble, d);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, short i)
+    ALWAYS_INLINE JSValue jsNumber(double d)
     {
-        return JSValue(exec, i);
+        return JSValue(d);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned short i)
+    ALWAYS_INLINE JSValue jsNumber(char i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, int i)
+    ALWAYS_INLINE JSValue jsNumber(unsigned char i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned i)
+    ALWAYS_INLINE JSValue jsNumber(short i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long i)
+    ALWAYS_INLINE JSValue jsNumber(unsigned short i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long i)
+    ALWAYS_INLINE JSValue jsNumber(int i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, long long i)
+    ALWAYS_INLINE JSValue jsNumber(unsigned i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(ExecState* exec, unsigned long long i)
+    ALWAYS_INLINE JSValue jsNumber(long i)
     {
-        return JSValue(exec, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, double d)
+    ALWAYS_INLINE JSValue jsNumber(unsigned long i)
     {
-        return JSValue(globalData, d);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, int i)
+    ALWAYS_INLINE JSValue jsNumber(long long i)
     {
-        return JSValue(globalData, i);
+        return JSValue(i);
     }
 
-    ALWAYS_INLINE JSValue jsNumber(JSGlobalData* globalData, unsigned i)
+    ALWAYS_INLINE JSValue jsNumber(unsigned long long i)
     {
-        return JSValue(globalData, i);
+        return JSValue(i);
     }
 
     inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); }
@@ -370,486 +464,8 @@ namespace JSC {
     inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); }
     inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; }
 
-    inline int32_t toInt32(double val)
-    {
-        if (!(val >= -2147483648.0 && val < 2147483648.0)) {
-            bool ignored;
-            return toInt32SlowCase(val, ignored);
-        }
-        return static_cast<int32_t>(val);
-    }
-
-    inline uint32_t toUInt32(double val)
-    {
-        if (!(val >= 0.0 && val < 4294967296.0)) {
-            bool ignored;
-            return toUInt32SlowCase(val, ignored);
-        }
-        return static_cast<uint32_t>(val);
-    }
-
-    // FIXME: We should deprecate this and just use JSValue::asCell() instead.
-    JSCell* asCell(JSValue);
-
-    inline JSCell* asCell(JSValue value)
-    {
-        return value.asCell();
-    }
-
-    ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
-    {
-        if (isInt32())
-            return asInt32();
-        bool ignored;
-        return toInt32SlowCase(toNumber(exec), ignored);
-    }
-
-    inline uint32_t JSValue::toUInt32(ExecState* exec) const
-    {
-        if (isUInt32())
-            return asInt32();
-        bool ignored;
-        return toUInt32SlowCase(toNumber(exec), ignored);
-    }
-
-    inline int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
-    {
-        if (isInt32()) {
-            ok = true;
-            return asInt32();
-        }
-        return toInt32SlowCase(toNumber(exec), ok);
-    }
-
-    inline uint32_t JSValue::toUInt32(ExecState* exec, bool& ok) const
-    {
-        if (isUInt32()) {
-            ok = true;
-            return asInt32();
-        }
-        return toUInt32SlowCase(toNumber(exec), ok);
-    }
-
-#if USE(JSVALUE32_64)
-    inline JSValue jsNaN(ExecState* exec)
-    {
-        return JSValue(exec, nonInlineNaN());
-    }
-
-    // JSValue member functions.
-    inline EncodedJSValue JSValue::encode(JSValue value)
-    {
-        return value.u.asEncodedJSValue;
-    }
-
-    inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
-    {
-        JSValue v;
-        v.u.asEncodedJSValue = encodedJSValue;
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!v.isZombie());
-#endif
-        return v;
-    }
-
-    inline JSValue::JSValue()
-    {
-        u.asBits.tag = EmptyValueTag;
-        u.asBits.payload = 0;
-    }
-
-    inline JSValue::JSValue(JSNullTag)
-    {
-        u.asBits.tag = NullTag;
-        u.asBits.payload = 0;
-    }
-    
-    inline JSValue::JSValue(JSUndefinedTag)
-    {
-        u.asBits.tag = UndefinedTag;
-        u.asBits.payload = 0;
-    }
-    
-    inline JSValue::JSValue(JSTrueTag)
-    {
-        u.asBits.tag = TrueTag;
-        u.asBits.payload = 0;
-    }
-    
-    inline JSValue::JSValue(JSFalseTag)
-    {
-        u.asBits.tag = FalseTag;
-        u.asBits.payload = 0;
-    }
-
-    inline JSValue::JSValue(HashTableDeletedValueTag)
-    {
-        u.asBits.tag = DeletedValueTag;
-        u.asBits.payload = 0;
-    }
-
-    inline JSValue::JSValue(JSCell* ptr)
-    {
-        if (ptr)
-            u.asBits.tag = CellTag;
-        else
-            u.asBits.tag = EmptyValueTag;
-        u.asBits.payload = reinterpret_cast<int32_t>(ptr);
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!isZombie());
-#endif
-    }
-
-    inline JSValue::JSValue(const JSCell* ptr)
-    {
-        if (ptr)
-            u.asBits.tag = CellTag;
-        else
-            u.asBits.tag = EmptyValueTag;
-        u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!isZombie());
-#endif
-    }
-
-    inline JSValue::operator bool() const
-    {
-        ASSERT(tag() != DeletedValueTag);
-        return tag() != EmptyValueTag;
-    }
-
-    inline bool JSValue::operator==(const JSValue& other) const
-    {
-        return u.asEncodedJSValue == other.u.asEncodedJSValue;
-    }
-
-    inline bool JSValue::operator!=(const JSValue& other) const
-    {
-        return u.asEncodedJSValue != other.u.asEncodedJSValue;
-    }
-
-    inline bool JSValue::isUndefined() const
-    {
-        return tag() == UndefinedTag;
-    }
-
-    inline bool JSValue::isNull() const
-    {
-        return tag() == NullTag;
-    }
-
-    inline bool JSValue::isUndefinedOrNull() const
-    {
-        return isUndefined() || isNull();
-    }
-
-    inline bool JSValue::isCell() const
-    {
-        return tag() == CellTag;
-    }
-
-    inline bool JSValue::isInt32() const
-    {
-        return tag() == Int32Tag;
-    }
-
-    inline bool JSValue::isUInt32() const
-    {
-        return tag() == Int32Tag && asInt32() > -1;
-    }
-
-    inline bool JSValue::isDouble() const
-    {
-        return tag() < LowestTag;
-    }
-
-    inline bool JSValue::isTrue() const
-    {
-        return tag() == TrueTag;
-    }
-
-    inline bool JSValue::isFalse() const
-    {
-        return tag() == FalseTag;
-    }
-
-    inline uint32_t JSValue::tag() const
-    {
-        return u.asBits.tag;
-    }
-    
-    inline int32_t JSValue::payload() const
-    {
-        return u.asBits.payload;
-    }
-    
-    inline int32_t JSValue::asInt32() const
-    {
-        ASSERT(isInt32());
-        return u.asBits.payload;
-    }
-    
-    inline uint32_t JSValue::asUInt32() const
-    {
-        ASSERT(isUInt32());
-        return u.asBits.payload;
-    }
-    
-    inline double JSValue::asDouble() const
-    {
-        ASSERT(isDouble());
-        return u.asDouble;
-    }
-    
-    ALWAYS_INLINE JSCell* JSValue::asCell() const
-    {
-        ASSERT(isCell());
-        return reinterpret_cast<JSCell*>(u.asBits.payload);
-    }
-
-    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d)
-    {
-        u.asDouble = d;
-    }
-
-    inline JSValue::JSValue(ExecState* exec, double d)
-    {
-        const int32_t asInt32 = static_cast<int32_t>(d);
-        if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
-            u.asDouble = d;
-            return;
-        }
-        *this = JSValue(exec, static_cast<int32_t>(d));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, char i)
-    {
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned char i)
-    {
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, short i)
-    {
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned short i)
-    {
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState*, int i)
-    {
-        u.asBits.tag = Int32Tag;
-        u.asBits.payload = i;
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned i)
-    {
-        if (static_cast<int32_t>(i) < 0) {
-            *this = JSValue(exec, static_cast<double>(i));
-            return;
-        }
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, long i)
-    {
-        if (static_cast<int32_t>(i) != i) {
-            *this = JSValue(exec, static_cast<double>(i));
-            return;
-        }
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned long i)
-    {
-        if (static_cast<uint32_t>(i) != i) {
-            *this = JSValue(exec, static_cast<double>(i));
-            return;
-        }
-        *this = JSValue(exec, static_cast<uint32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, long long i)
-    {
-        if (static_cast<int32_t>(i) != i) {
-            *this = JSValue(exec, static_cast<double>(i));
-            return;
-        }
-        *this = JSValue(exec, static_cast<int32_t>(i));
-    }
-
-    inline JSValue::JSValue(ExecState* exec, unsigned long long i)
-    {
-        if (static_cast<uint32_t>(i) != i) {
-            *this = JSValue(exec, static_cast<double>(i));
-            return;
-        }
-        *this = JSValue(exec, static_cast<uint32_t>(i));
-    }
-
-    inline JSValue::JSValue(JSGlobalData* globalData, double d)
-    {
-        const int32_t asInt32 = static_cast<int32_t>(d);
-        if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
-            u.asDouble = d;
-            return;
-        }
-        *this = JSValue(globalData, static_cast<int32_t>(d));
-    }
-    
-    inline JSValue::JSValue(JSGlobalData*, int i)
-    {
-        u.asBits.tag = Int32Tag;
-        u.asBits.payload = i;
-    }
-    
-    inline JSValue::JSValue(JSGlobalData* globalData, unsigned i)
-    {
-        if (static_cast<int32_t>(i) < 0) {
-            *this = JSValue(globalData, static_cast<double>(i));
-            return;
-        }
-        *this = JSValue(globalData, static_cast<int32_t>(i));
-    }
-
-    inline bool JSValue::isNumber() const
-    {
-        return isInt32() || isDouble();
-    }
-
-    inline bool JSValue::isBoolean() const
-    {
-        return isTrue() || isFalse();
-    }
-
-    inline bool JSValue::getBoolean(bool& v) const
-    {
-        if (isTrue()) {
-            v = true;
-            return true;
-        }
-        if (isFalse()) {
-            v = false;
-            return true;
-        }
-        
-        return false;
-    }
-
-    inline bool JSValue::getBoolean() const
-    {
-        ASSERT(isBoolean());
-        return tag() == TrueTag;
-    }
-
-    inline double JSValue::uncheckedGetNumber() const
-    {
-        ASSERT(isNumber());
-        return isInt32() ? asInt32() : asDouble();
-    }
-
-    ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
-    {
-        return isNumber() ? asValue() : jsNumber(exec, this->toNumber(exec));
-    }
-
-    inline bool JSValue::getNumber(double& result) const
-    {
-        if (isInt32()) {
-            result = asInt32();
-            return true;
-        }
-        if (isDouble()) {
-            result = asDouble();
-            return true;
-        }
-        return false;
-    }
-
-#else // USE(JSVALUE32_64)
-
-    // JSValue member functions.
-    inline EncodedJSValue JSValue::encode(JSValue value)
-    {
-        return reinterpret_cast<EncodedJSValue>(value.m_ptr);
-    }
-
-    inline JSValue JSValue::decode(EncodedJSValue ptr)
-    {
-        return JSValue(reinterpret_cast<JSCell*>(ptr));
-    }
-
-    inline JSValue JSValue::makeImmediate(intptr_t value)
-    {
-        return JSValue(reinterpret_cast<JSCell*>(value));
-    }
-
-    inline intptr_t JSValue::immediateValue()
-    {
-        return reinterpret_cast<intptr_t>(m_ptr);
-    }
-    
-    // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
-    inline JSValue::JSValue()
-        : m_ptr(0)
-    {
-    }
+    bool isZombie(const JSCell*);
 
-    // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
-    inline JSValue::JSValue(HashTableDeletedValueTag)
-        : m_ptr(reinterpret_cast<JSCell*>(0x4))
-    {
-    }
-
-    inline JSValue::JSValue(JSCell* ptr)
-        : m_ptr(ptr)
-    {
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!isZombie());
-#endif
-    }
-
-    inline JSValue::JSValue(const JSCell* ptr)
-        : m_ptr(const_cast<JSCell*>(ptr))
-    {
-#if ENABLE(JSC_ZOMBIES)
-        ASSERT(!isZombie());
-#endif
-    }
-
-    inline JSValue::operator bool() const
-    {
-        return m_ptr;
-    }
-
-    inline bool JSValue::operator==(const JSValue& other) const
-    {
-        return m_ptr == other.m_ptr;
-    }
-
-    inline bool JSValue::operator!=(const JSValue& other) const
-    {
-        return m_ptr != other.m_ptr;
-    }
-
-    inline bool JSValue::isUndefined() const
-    {
-        return asValue() == jsUndefined();
-    }
-
-    inline bool JSValue::isNull() const
-    {
-        return asValue() == jsNull();
-    }
-#endif // USE(JSVALUE32_64)
-    
-    typedef std::pair<JSValue, UString> ValueStringPair;
 } // namespace JSC
 
 #endif // JSValue_h
diff --git a/runtime/JSValueInlineMethods.h b/runtime/JSValueInlineMethods.h
new file mode 100644 (file)
index 0000000..b4f6f80
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2011 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 JSValueInlineMethods_h
+#define JSValueInlineMethods_h
+
+#include "JSValue.h"
+
+namespace JSC {
+
+    ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
+    {
+        if (isInt32())
+            return asInt32();
+        return JSC::toInt32(toNumber(exec));
+    }
+
+    inline uint32_t JSValue::toUInt32(ExecState* exec) const
+    {
+        // See comment on JSC::toUInt32, above.
+        return toInt32(exec);
+    }
+
+    inline bool JSValue::isUInt32() const
+    {
+        return isInt32() && asInt32() >= 0;
+    }
+
+    inline uint32_t JSValue::asUInt32() const
+    {
+        ASSERT(isUInt32());
+        return asInt32();
+    }
+
+    inline double JSValue::uncheckedGetNumber() const
+    {
+        ASSERT(isNumber());
+        return isInt32() ? asInt32() : asDouble();
+    }
+
+    ALWAYS_INLINE JSValue JSValue::toJSNumber(ExecState* exec) const
+    {
+        return isNumber() ? asValue() : jsNumber(this->toNumber(exec));
+    }
+
+    inline JSValue jsNaN()
+    {
+        return JSValue(nonInlineNaN());
+    }
+
+    inline bool JSValue::getNumber(double& result) const
+    {
+        if (isInt32()) {
+            result = asInt32();
+            return true;
+        }
+        if (isDouble()) {
+            result = asDouble();
+            return true;
+        }
+        return false;
+    }
+
+    inline bool JSValue::getBoolean(bool& v) const
+    {
+        if (isTrue()) {
+            v = true;
+            return true;
+        }
+        if (isFalse()) {
+            v = false;
+            return true;
+        }
+        
+        return false;
+    }
+
+    inline JSValue::JSValue(char i)
+    {
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(unsigned char i)
+    {
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(short i)
+    {
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(unsigned short i)
+    {
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(unsigned i)
+    {
+        if (static_cast<int32_t>(i) < 0) {
+            *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+            return;
+        }
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(long i)
+    {
+        if (static_cast<int32_t>(i) != i) {
+            *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+            return;
+        }
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(unsigned long i)
+    {
+        if (static_cast<uint32_t>(i) != i) {
+            *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+            return;
+        }
+        *this = JSValue(static_cast<uint32_t>(i));
+    }
+
+    inline JSValue::JSValue(long long i)
+    {
+        if (static_cast<int32_t>(i) != i) {
+            *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+            return;
+        }
+        *this = JSValue(static_cast<int32_t>(i));
+    }
+
+    inline JSValue::JSValue(unsigned long long i)
+    {
+        if (static_cast<uint32_t>(i) != i) {
+            *this = JSValue(EncodeAsDouble, static_cast<double>(i));
+            return;
+        }
+        *this = JSValue(static_cast<uint32_t>(i));
+    }
+
+    inline JSValue::JSValue(double d)
+    {
+        const int32_t asInt32 = static_cast<int32_t>(d);
+        if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0
+            *this = JSValue(EncodeAsDouble, d);
+            return;
+        }
+        *this = JSValue(static_cast<int32_t>(d));
+    }
+
+#if USE(JSVALUE32_64)
+    inline EncodedJSValue JSValue::encode(JSValue value)
+    {
+        return value.u.asInt64;
+    }
+
+    inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
+    {
+        JSValue v;
+        v.u.asInt64 = encodedJSValue;
+        return v;
+    }
+
+    inline JSValue::JSValue()
+    {
+        u.asBits.tag = EmptyValueTag;
+        u.asBits.payload = 0;
+    }
+
+    inline JSValue::JSValue(JSNullTag)
+    {
+        u.asBits.tag = NullTag;
+        u.asBits.payload = 0;
+    }
+    
+    inline JSValue::JSValue(JSUndefinedTag)
+    {
+        u.asBits.tag = UndefinedTag;
+        u.asBits.payload = 0;
+    }
+    
+    inline JSValue::JSValue(JSTrueTag)
+    {
+        u.asBits.tag = BooleanTag;
+        u.asBits.payload = 1;
+    }
+    
+    inline JSValue::JSValue(JSFalseTag)
+    {
+        u.asBits.tag = BooleanTag;
+        u.asBits.payload = 0;
+    }
+
+    inline JSValue::JSValue(HashTableDeletedValueTag)
+    {
+        u.asBits.tag = DeletedValueTag;
+        u.asBits.payload = 0;
+    }
+
+    inline JSValue::JSValue(JSCell* ptr)
+    {
+        if (ptr)
+            u.asBits.tag = CellTag;
+        else
+            u.asBits.tag = EmptyValueTag;
+        u.asBits.payload = reinterpret_cast<int32_t>(ptr);
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
+    }
+
+    inline JSValue::JSValue(const JSCell* ptr)
+    {
+        if (ptr)
+            u.asBits.tag = CellTag;
+        else
+            u.asBits.tag = EmptyValueTag;
+        u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
+    }
+
+    inline JSValue::operator bool() const
+    {
+        ASSERT(tag() != DeletedValueTag);
+        return tag() != EmptyValueTag;
+    }
+
+    inline bool JSValue::operator==(const JSValue& other) const
+    {
+        return u.asInt64 == other.u.asInt64;
+    }
+
+    inline bool JSValue::operator!=(const JSValue& other) const
+    {
+        return u.asInt64 != other.u.asInt64;
+    }
+
+    inline bool JSValue::isUndefined() const
+    {
+        return tag() == UndefinedTag;
+    }
+
+    inline bool JSValue::isNull() const
+    {
+        return tag() == NullTag;
+    }
+
+    inline bool JSValue::isUndefinedOrNull() const
+    {
+        return isUndefined() || isNull();
+    }
+
+    inline bool JSValue::isCell() const
+    {
+        return tag() == CellTag;
+    }
+
+    inline bool JSValue::isInt32() const
+    {
+        return tag() == Int32Tag;
+    }
+
+    inline bool JSValue::isDouble() const
+    {
+        return tag() < LowestTag;
+    }
+
+    inline bool JSValue::isTrue() const
+    {
+        return tag() == BooleanTag && payload();
+    }
+
+    inline bool JSValue::isFalse() const
+    {
+        return tag() == BooleanTag && !payload();
+    }
+
+    inline uint32_t JSValue::tag() const
+    {
+        return u.asBits.tag;
+    }
+    
+    inline int32_t JSValue::payload() const
+    {
+        return u.asBits.payload;
+    }
+    
+    inline int32_t JSValue::asInt32() const
+    {
+        ASSERT(isInt32());
+        return u.asBits.payload;
+    }
+    
+    inline double JSValue::asDouble() const
+    {
+        ASSERT(isDouble());
+        return u.asDouble;
+    }
+    
+    ALWAYS_INLINE JSCell* JSValue::asCell() const
+    {
+        ASSERT(isCell());
+        return reinterpret_cast<JSCell*>(u.asBits.payload);
+    }
+
+    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
+    {
+        u.asDouble = d;
+    }
+
+    inline JSValue::JSValue(int i)
+    {
+        u.asBits.tag = Int32Tag;
+        u.asBits.payload = i;
+    }
+
+    inline bool JSValue::isNumber() const
+    {
+        return isInt32() || isDouble();
+    }
+
+    inline bool JSValue::isBoolean() const
+    {
+        return isTrue() || isFalse();
+    }
+
+    inline bool JSValue::getBoolean() const
+    {
+        ASSERT(isBoolean());
+        return payload();
+    }
+
+#else // USE(JSVALUE32_64)
+
+    // JSValue member functions.
+    inline EncodedJSValue JSValue::encode(JSValue value)
+    {
+        return value.u.ptr;
+    }
+
+    inline JSValue JSValue::decode(EncodedJSValue ptr)
+    {
+        return JSValue(reinterpret_cast<JSCell*>(ptr));
+    }
+
+    // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
+    inline JSValue::JSValue()
+    {
+        u.asInt64 = ValueEmpty;
+    }
+
+    // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
+    inline JSValue::JSValue(HashTableDeletedValueTag)
+    {
+        u.asInt64 = ValueDeleted;
+    }
+
+    inline JSValue::JSValue(JSCell* ptr)
+    {
+        u.ptr = ptr;
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
+    }
+
+    inline JSValue::JSValue(const JSCell* ptr)
+    {
+        u.ptr = const_cast<JSCell*>(ptr);
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie());
+#endif
+    }
+
+    inline JSValue::operator bool() const
+    {
+        return u.ptr;
+    }
+
+    inline bool JSValue::operator==(const JSValue& other) const
+    {
+        return u.ptr == other.u.ptr;
+    }
+
+    inline bool JSValue::operator!=(const JSValue& other) const
+    {
+        return u.ptr != other.u.ptr;
+    }
+
+    inline bool JSValue::isUndefined() const
+    {
+        return asValue() == jsUndefined();
+    }
+
+    inline bool JSValue::isNull() const
+    {
+        return asValue() == jsNull();
+    }
+
+    inline bool JSValue::isTrue() const
+    {
+        return asValue() == JSValue(JSTrue);
+    }
+
+    inline bool JSValue::isFalse() const
+    {
+        return asValue() == JSValue(JSFalse);
+    }
+
+    inline bool JSValue::getBoolean() const
+    {
+        ASSERT(asValue() == jsBoolean(true) || asValue() == jsBoolean(false));
+        return asValue() == jsBoolean(true);
+    }
+
+    inline int32_t JSValue::asInt32() const
+    {
+        ASSERT(isInt32());
+        return static_cast<int32_t>(u.asInt64);
+    }
+
+    inline bool JSValue::isDouble() const
+    {
+        return isNumber() && !isInt32();
+    }
+
+    inline JSValue::JSValue(JSNullTag)
+    {
+        u.asInt64 = ValueNull;
+    }
+    
+    inline JSValue::JSValue(JSUndefinedTag)
+    {
+        u.asInt64 = ValueUndefined;
+    }
+
+    inline JSValue::JSValue(JSTrueTag)
+    {
+        u.asInt64 = ValueTrue;
+    }
+
+    inline JSValue::JSValue(JSFalseTag)
+    {
+        u.asInt64 = ValueFalse;
+    }
+
+    inline bool JSValue::isUndefinedOrNull() const
+    {
+        // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
+        return (u.asInt64 & ~TagBitUndefined) == ValueNull;
+    }
+
+    inline bool JSValue::isBoolean() const
+    {
+        return (u.asInt64 & ~1) == ValueFalse;
+    }
+
+    inline bool JSValue::isCell() const
+    {
+        return !(u.asInt64 & TagMask);
+    }
+
+    inline bool JSValue::isInt32() const
+    {
+        return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
+    }
+
+    inline intptr_t reinterpretDoubleToIntptr(double value)
+    {
+        return bitwise_cast<intptr_t>(value);
+    }
+    inline double reinterpretIntptrToDouble(intptr_t value)
+    {
+        return bitwise_cast<double>(value);
+    }
+
+    ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
+    {
+        u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset;
+    }
+
+    inline JSValue::JSValue(int i)
+    {
+        u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
+    }
+
+    inline double JSValue::asDouble() const
+    {
+        return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset);
+    }
+
+    inline bool JSValue::isNumber() const
+    {
+        return u.asInt64 & TagTypeNumber;
+    }
+
+    ALWAYS_INLINE JSCell* JSValue::asCell() const
+    {
+        ASSERT(isCell());
+        return u.ptr;
+    }
+
+#endif // USE(JSVALUE64)
+
+} // namespace JSC
+
+#endif // JSValueInlineMethods_h
index 73650016a9f21c0b169a793ae11bae5c171b1286..abe9bbbc2f5d62953fe59c417b36c729eaa82a30 100644 (file)
@@ -36,7 +36,7 @@ namespace JSC {
 
 bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName)
 {
-    if (symbolTable().contains(propertyName.ustring().rep()))
+    if (symbolTable().contains(propertyName.impl()))
         return false;
 
     return JSObject::deleteProperty(exec, propertyName);
@@ -60,9 +60,9 @@ bool JSVariableObject::isVariableObject() const
 
 bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
-    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
     if (!entry.isNull()) {
-        descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete);
+        descriptor.setDescriptor(registerAt(entry.getIndex()).get(), entry.getAttributes() | DontDelete);
         return true;
     }
     return false;
index f2efcdf3989affb0b2ef4b6765ce5f8c6a0939ad..89bb6b02b67d99ac2dc3d45cf538379fcdfcf4b5 100644 (file)
@@ -40,11 +40,11 @@ namespace JSC {
 
     class Register;
 
-    class JSVariableObject : public JSObject {
+    class JSVariableObject : public JSNonFinalObject {
         friend class JIT;
 
     public:
-        SymbolTable& symbolTable() const { return *d->symbolTable; }
+        SymbolTable& symbolTable() const { return *m_symbolTable; }
 
         virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0;
 
@@ -54,58 +54,46 @@ namespace JSC {
         virtual bool isVariableObject() const;
         virtual bool isDynamicScope(bool& requiresDynamicChecks) const = 0;
 
-        Register& registerAt(int index) const { return d->registers[index]; }
+        WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
         
     protected:
         static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags;
-        // Subclasses of JSVariableObject can subclass this struct to add data
-        // without increasing their own size (since there's a hard limit on the
-        // size of a JSCell).
-        struct JSVariableObjectData {
-            JSVariableObjectData(SymbolTable* symbolTable, Register* registers)
-                : symbolTable(symbolTable)
-                , registers(registers)
-            {
-                ASSERT(symbolTable);
-            }
-
-            SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
-            Register* registers; // "r" in the register file.
-            OwnArrayPtr<Register> registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
-
-        private:
-            JSVariableObjectData(const JSVariableObjectData&);
-            JSVariableObjectData& operator=(const JSVariableObjectData&);
-        };
-
-        JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data)
-            : JSObject(structure)
-            , d(data) // Subclass owns this pointer.
+
+        JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers)
+            : JSNonFinalObject(globalData, structure)
+            , m_symbolTable(symbolTable)
+            , m_registers(reinterpret_cast<WriteBarrier<Unknown>*>(registers))
         {
+            ASSERT(m_symbolTable);
+            COMPILE_ASSERT(sizeof(WriteBarrier<Unknown>) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier);
         }
 
-        Register* copyRegisterArray(Register* src, size_t count);
-        void setRegisters(Register* r, Register* registerArray);
+        PassOwnArrayPtr<WriteBarrier<Unknown> > copyRegisterArray(JSGlobalData&, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts);
+        void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray);
 
         bool symbolTableGet(const Identifier&, PropertySlot&);
         bool symbolTableGet(const Identifier&, PropertyDescriptor&);
         bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
-        bool symbolTablePut(const Identifier&, JSValue);
-        bool symbolTablePutWithAttributes(const Identifier&, JSValue, unsigned attributes);
+        bool symbolTablePut(JSGlobalData&, const Identifier&, JSValue);
+        bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes);
 
-        JSVariableObjectData* d;
+        SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file.
+        WriteBarrier<Unknown>* m_registers; // "r" in the register file.
+        OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file.
     };
 
     inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
     {
-        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
         if (!entry.isNull()) {
-            slot.setRegisterSlot(&registerAt(entry.getIndex()));
+            slot.setValue(registerAt(entry.getIndex()).get());
             return true;
         }
         return false;
@@ -113,55 +101,58 @@ namespace JSC {
 
     inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
     {
-        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
         if (!entry.isNull()) {
-            slot.setRegisterSlot(&registerAt(entry.getIndex()));
+            slot.setValue(registerAt(entry.getIndex()).get());
             slotIsWriteable = !entry.isReadOnly();
             return true;
         }
         return false;
     }
 
-    inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue value)
+    inline bool JSVariableObject::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
     {
         ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+        SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
         if (entry.isNull())
             return false;
         if (entry.isReadOnly())
             return true;
-        registerAt(entry.getIndex()) = value;
+        registerAt(entry.getIndex()).set(globalData, this, value);
         return true;
     }
 
-    inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue value, unsigned attributes)
+    inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
     {
         ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-        SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep());
+        SymbolTable::iterator iter = symbolTable().find(propertyName.impl());
         if (iter == symbolTable().end())
             return false;
         SymbolTableEntry& entry = iter->second;
         ASSERT(!entry.isNull());
         entry.setAttributes(attributes);
-        registerAt(entry.getIndex()) = value;
+        registerAt(entry.getIndex()).set(globalData, this, value);
         return true;
     }
 
-    inline Register* JSVariableObject::copyRegisterArray(Register* src, size_t count)
+    inline PassOwnArrayPtr<WriteBarrier<Unknown> > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier<Unknown>* src, size_t count, size_t callframeStarts)
     {
-        Register* registerArray = new Register[count];
-        memcpy(registerArray, src, count * sizeof(Register));
+        OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[count]);
+        for (size_t i = 0; i < callframeStarts; i++)
+            registerArray[i].set(globalData, this, src[i].get());
+        for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++)
+            registerArray[i].set(globalData, this, src[i].get());
 
-        return registerArray;
+        return registerArray.release();
     }
 
-    inline void JSVariableObject::setRegisters(Register* registers, Register* registerArray)
+    inline void JSVariableObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray)
     {
-        ASSERT(registerArray != d->registerArray.get());
-        d->registerArray.set(registerArray);
-        d->registers = registers;
+        ASSERT(registerArray != m_registerArray);
+        m_registerArray = registerArray;
+        m_registers = registers;
     }
 
 } // namespace JSC
index 2c39f5c23849fee2affa194d4c6ee59399aba741..8d6387ec0ab20adf7afa53e1f10fdad0430f01e2 100644 (file)
@@ -26,11 +26,14 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 
-void JSWrapperObject::markChildren(MarkStack& markStack
+void JSWrapperObject::visitChildren(SlotVisitor& visitor
 {
-    JSObject::markChildren(markStack);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSObject::visitChildren(visitor);
     if (m_internalValue)
-        markStack.append(m_internalValue);
+        visitor.append(&m_internalValue);
 }
 
 } // namespace JSC
index f19cd30c85049409a338cce27f617e899ede340b..89726486584f40753525a5d9a8201480c73d01f3 100644 (file)
@@ -28,40 +28,43 @@ namespace JSC {
 
     // This class is used as a base for classes such as String,
     // Number, Boolean and Date which are wrappers for primitive types.
-    class JSWrapperObject : public JSObject {
+    class JSWrapperObject : public JSNonFinalObject {
     protected:
-        explicit JSWrapperObject(NonNullPassRefPtr<Structure>);
+        explicit JSWrapperObject(JSGlobalData&, Structure*);
 
     public:
-        JSValue internalValue() const { return m_internalValue; }
-        void setInternalValue(JSValue);
+        JSValue internalValue() const;
+        void setInternalValue(JSGlobalData&, JSValue);
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) 
         { 
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     protected:
-        static const unsigned AnonymousSlotCount = 1 + JSObject::AnonymousSlotCount;
+        static const unsigned StructureFlags = OverridesVisitChildren | JSNonFinalObject::StructureFlags;
 
     private:
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
         
-        JSValue m_internalValue;
+        WriteBarrier<Unknown> m_internalValue;
     };
 
-    inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure)
-        : JSObject(structure)
+    inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, Structure* structure)
+        : JSNonFinalObject(globalData, structure)
     {
-        putAnonymousValue(0, jsNull());
     }
 
-    inline void JSWrapperObject::setInternalValue(JSValue value)
+    inline JSValue JSWrapperObject::internalValue() const
+    {
+        return m_internalValue.get();
+    }
+
+    inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value)
     {
         ASSERT(value);
         ASSERT(!value.isObject());
-        m_internalValue = value;
-        putAnonymousValue(0, value);
+        m_internalValue.set(globalData, this, value);
     }
 
 } // namespace JSC
index 072d29b6af9567418cdf99f42a455a97a472ec5e..efabc93fc1bc35196106cfd7d307509c5a3558cb 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "JSZombie.h"
 #include "ClassInfo.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 
 #if ENABLE(JSC_ZOMBIES)
 
@@ -33,16 +35,6 @@ namespace JSC {
 
 const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 };
 
-Structure* JSZombie::leakedZombieStructure() {
-    static Structure* structure = 0;
-    if (!structure) {
-        Structure::startIgnoringLeaks();
-        structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType)).releaseRef();
-        Structure::stopIgnoringLeaks();
-    }
-    return structure;
-}
-
 }
 
 #endif // ENABLE(JSC_ZOMBIES)
index 711f6732bcceaeb81c0e07770c234d2720150f54..795036ea1a33184ee0dd7fd24799f914f52d4d19 100644 (file)
 #define JSZombie_h
 
 #include "JSCell.h"
+#include "Structure.h"
 
 #if ENABLE(JSC_ZOMBIES)
 namespace JSC {
 
 class JSZombie : public JSCell {
 public:
-    JSZombie(const ClassInfo* oldInfo, Structure* structure)
-        : JSCell(structure)
+    JSZombie(JSGlobalData& globalData, const ClassInfo* oldInfo, Structure* structure)
+        : JSCell(globalData, structure)
         , m_oldInfo(oldInfo)
     {
+        ASSERT(inherits(&s_info));
     }
+
     virtual bool isZombie() const { return true; }
-    virtual const ClassInfo* classInfo() const { return &s_info; }
-    static Structure* leakedZombieStructure();
 
     virtual bool isGetterSetter() const { ASSERT_NOT_REACHED(); return false; }
     virtual bool isAPIValueWrapper() const { ASSERT_NOT_REACHED(); return false; }
@@ -54,17 +55,24 @@ public:
     virtual double toNumber(ExecState*) const { ASSERT_NOT_REACHED(); return 0.0; }
     virtual UString toString(ExecState*) const { ASSERT_NOT_REACHED(); return ""; }
     virtual JSObject* toObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; }
-    virtual void markChildren(MarkStack&) { ASSERT_NOT_REACHED(); }
+    virtual void visitChildren(SlotVisitor&) { ASSERT_NOT_REACHED(); }
     virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&) { ASSERT_NOT_REACHED(); }
     virtual void put(ExecState*, unsigned, JSValue) { ASSERT_NOT_REACHED(); }
     virtual bool deleteProperty(ExecState*, const Identifier&) { ASSERT_NOT_REACHED(); return false; }
     virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; }
     virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; }
+    virtual JSValue toStrictThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return JSValue(); }
     virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); }
     virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
     virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; }
     
+    static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+    {
+        return Structure::create(globalData, prototype, TypeInfo(LeafType, 0), AnonymousSlotCount, &s_info);
+    }
+
     static const ClassInfo s_info;
+
 private:
     const ClassInfo* m_oldInfo;
 };
index cc33bae187be78c14c6fb3a515cdc2577ecf4beb..ed42d0d2fd960f9ec0b26c59519437db1dfc9927 100644 (file)
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
-#include "StringBuilder.h"
+#include "UStringBuilder.h"
 #include <wtf/ASCIICType.h>
 #include <wtf/dtoa.h>
 
 namespace JSC {
 
-LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
+static inline bool isJSONWhiteSpace(const UChar& c)
 {
-    while (m_ptr < m_end && isASCIISpace(*m_ptr))
+    // The JSON RFC 4627 defines a list of allowed characters to be considered
+    // insignificant white space: http://www.ietf.org/rfc/rfc4627.txt (2. JSON Grammar).
+    return c == ' ' || c == 0x9 || c == 0xA || c == 0xD;
+}
+
+bool LiteralParser::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
+{
+    if (m_lexer.next() != TokIdentifier)
+        return false;
+    do {
+        Vector<JSONPPathEntry> path;
+        // Unguarded next to start off the lexer
+        Identifier name = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+        JSONPPathEntry entry;
+        if (name == m_exec->globalData().propertyNames->varKeyword) {
+            if (m_lexer.next() != TokIdentifier)
+                return false;
+            entry.m_type = JSONPPathEntryTypeDeclare;
+            entry.m_pathEntryName = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+            path.append(entry);
+        } else {
+            entry.m_type = JSONPPathEntryTypeDot;
+            entry.m_pathEntryName = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+            path.append(entry);
+        }
+        if (m_exec->globalData().lexer->isKeyword(entry.m_pathEntryName))
+            return false;
+        TokenType tokenType = m_lexer.next();
+        while (tokenType != TokAssign) {
+            switch (tokenType) {
+            case TokLBracket: {
+                entry.m_type = JSONPPathEntryTypeLookup;
+                if (m_lexer.next() != TokNumber)
+                    return false;
+                double doubleIndex = m_lexer.currentToken().numberToken;
+                int index = (int)doubleIndex;
+                if (index != doubleIndex || index < 0)
+                    return false;
+                entry.m_pathIndex = index;
+                if (m_lexer.next() != TokRBracket)
+                    return false;
+                break;
+            }
+            case TokDot: {
+                entry.m_type = JSONPPathEntryTypeDot;
+                if (m_lexer.next() != TokIdentifier)
+                    return false;
+                entry.m_pathEntryName = Identifier(m_exec, m_lexer.currentToken().start, m_lexer.currentToken().end - m_lexer.currentToken().start);
+                break;
+            }
+            case TokLParen: {
+                if (path.last().m_type != JSONPPathEntryTypeDot || needsFullSourceInfo)
+                    return false;
+                path.last().m_type = JSONPPathEntryTypeCall;
+                entry = path.last();
+                goto startJSON;
+            }
+            default:
+                return false;
+            }
+            path.append(entry);
+            tokenType = m_lexer.next();
+        }
+    startJSON:
+        m_lexer.next();
+        results.append(JSONPData());
+        results.last().m_value.set(m_exec->globalData(), parse(StartParseExpression));
+        if (!results.last().m_value)
+            return false;
+        results.last().m_path.swap(path);
+        if (entry.m_type == JSONPPathEntryTypeCall) {
+            if (m_lexer.currentToken().type != TokRParen)
+                return false;
+            m_lexer.next();
+        }
+        if (m_lexer.currentToken().type != TokSemi)
+            break;
+        m_lexer.next();
+    } while (m_lexer.currentToken().type == TokIdentifier);
+    return m_lexer.currentToken().type == TokEnd;
+}
+    
+ALWAYS_INLINE const Identifier LiteralParser::makeIdentifier(const UChar* characters, size_t length)
+{
+    if (!length)
+        return m_exec->globalData().propertyNames->emptyIdentifier;
+    if (characters[0] >= MaximumCachableCharacter)
+        return Identifier(&m_exec->globalData(), characters, length);
+
+    if (length == 1) {
+        if (!m_shortIdentifiers[characters[0]].isNull())
+            return m_shortIdentifiers[characters[0]];
+        m_shortIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+        return m_shortIdentifiers[characters[0]];
+    }
+    if (!m_recentIdentifiers[characters[0]].isNull() && Identifier::equal(m_recentIdentifiers[characters[0]].impl(), characters, length))
+        return m_recentIdentifiers[characters[0]];
+    m_recentIdentifiers[characters[0]] = Identifier(&m_exec->globalData(), characters, length);
+    return m_recentIdentifiers[characters[0]];
+}
+
+template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
+{
+    while (m_ptr < m_end && isJSONWhiteSpace(*m_ptr))
         ++m_ptr;
 
     ASSERT(m_ptr <= m_end);
@@ -60,11 +163,11 @@ LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
         case '(':
             token.type = TokLParen;
             token.end = ++m_ptr;
-            return TokLBracket;
+            return TokLParen;
         case ')':
             token.type = TokRParen;
             token.end = ++m_ptr;
-            return TokRBracket;
+            return TokRParen;
         case '{':
             token.type = TokLBrace;
             token.end = ++m_ptr;
@@ -82,9 +185,7 @@ LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
             token.end = ++m_ptr;
             return TokColon;
         case '"':
-            if (m_mode == StrictJSON)
-                return lexString<StrictJSON>(token);
-            return lexString<NonStrictJSON>(token);
+            return lexString<mode, '"'>(token);
         case 't':
             if (m_end - m_ptr >= 4 && m_ptr[1] == 'r' && m_ptr[2] == 'u' && m_ptr[3] == 'e') {
                 m_ptr += 4;
@@ -108,7 +209,7 @@ LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
                 token.end = m_ptr;
                 return TokNull;
             }
-            break;    
+            break;
         case '-':
         case '0':
         case '1':
@@ -122,27 +223,69 @@ LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
         case '9':
             return lexNumber(token);
     }
+    if (m_ptr < m_end) {
+        if (*m_ptr == '.') {
+            token.type = TokDot;
+            token.end = ++m_ptr;
+            return TokDot;
+        }
+        if (*m_ptr == '=') {
+            token.type = TokAssign;
+            token.end = ++m_ptr;
+            return TokAssign;
+        }
+        if (*m_ptr == ';') {
+            token.type = TokSemi;
+            token.end = ++m_ptr;
+            return TokAssign;
+        }
+        if (isASCIIAlpha(*m_ptr) || *m_ptr == '_' || *m_ptr == '$') {
+            while (m_ptr < m_end && (isASCIIAlphanumeric(*m_ptr) || *m_ptr == '_' || *m_ptr == '$'))
+                m_ptr++;
+            token.stringToken = token.start;
+            token.stringLength = m_ptr - token.start;
+            token.type = TokIdentifier;
+            token.end = m_ptr;
+            return TokIdentifier;
+        }
+        if (*m_ptr == '\'') {
+            if (mode == StrictJSON)
+                return TokError;
+            return lexString<mode, '\''>(token);
+        }
+    }
     return TokError;
 }
 
-template <LiteralParser::ParserMode mode> static inline bool isSafeStringCharacter(UChar c)
+LiteralParser::TokenType LiteralParser::Lexer::next()
+{
+    if (m_mode == NonStrictJSON)
+        return lex<NonStrictJSON>(m_currentToken);
+    if (m_mode == JSONP)
+        return lex<JSONP>(m_currentToken);
+    return lex<StrictJSON>(m_currentToken);
+}
+
+template <LiteralParser::ParserMode mode, UChar terminator> static inline bool isSafeStringCharacter(UChar c)
 {
-    return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != '"') || c == '\t';
+    return (c >= ' ' && (mode == LiteralParser::StrictJSON || c <= 0xff) && c != '\\' && c != terminator) || c == '\t';
 }
 
 // "inline" is required here to help WINSCW compiler resolve specialized argument in templated functions.
-template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
+template <LiteralParser::ParserMode mode, UChar terminator> inline LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
 {
     ++m_ptr;
-    const UChar* runStart;
-    StringBuilder builder;
+    const UChar* runStart = m_ptr;
+    UStringBuilder builder;
     do {
         runStart = m_ptr;
-        while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr))
+        while (m_ptr < m_end && isSafeStringCharacter<mode, terminator>(*m_ptr))
             ++m_ptr;
-        if (runStart < m_ptr)
+        if (builder.length())
             builder.append(runStart, m_ptr - runStart);
-        if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
+        if ((mode != NonStrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
+            if (builder.isEmpty() && runStart < m_ptr)
+                builder.append(runStart, m_ptr - runStart);
             ++m_ptr;
             if (m_ptr >= m_end)
                 return TokError;
@@ -192,15 +335,28 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera
                     break;
 
                 default:
+                    if (*m_ptr == '\'' && mode != StrictJSON) {
+                        builder.append('\'');
+                        m_ptr++;
+                        break;
+                    }
                     return TokError;
             }
         }
-    } while ((mode == StrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != '"');
+    } while ((mode != NonStrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != terminator);
 
-    if (m_ptr >= m_end || *m_ptr != '"')
+    if (m_ptr >= m_end || *m_ptr != terminator)
         return TokError;
 
-    token.stringToken = builder.build();
+    if (builder.isEmpty()) {
+        token.stringBuffer = UString();
+        token.stringToken = runStart;
+        token.stringLength = m_ptr - runStart;
+    } else {
+        token.stringBuffer = builder.toUString();
+        token.stringToken = token.stringBuffer.characters();
+        token.stringLength = token.stringBuffer.length();
+    }
     token.type = TokString;
     token.end = ++m_ptr;
     return TokString;
@@ -246,6 +402,22 @@ LiteralParser::TokenType LiteralParser::Lexer::lexNumber(LiteralParserToken& tok
         ++m_ptr;
         while (m_ptr < m_end && isASCIIDigit(*m_ptr))
             ++m_ptr;
+    } else if (m_ptr < m_end && (*m_ptr != 'e' && *m_ptr != 'E') && (m_ptr - token.start) < 10) {
+        int result = 0;
+        token.type = TokNumber;
+        token.end = m_ptr;
+        const UChar* digit = token.start;
+        int negative = 1;
+        if (*digit == '-') {
+            negative = -1;
+            digit++;
+        }
+        
+        while (digit < m_ptr)
+            result = result * 10 + (*digit++) - '0';
+        result *= negative;
+        token.numberToken = result;
+        return TokNumber;
     }
 
     //  ([eE][+-]? [0-9]+)?
@@ -330,7 +502,7 @@ JSValue LiteralParser::parse(ParserState initialState)
                 objectStack.append(object);
 
                 TokenType type = m_lexer.next();
-                if (type == TokString) {
+                if (type == TokString || (m_mode != StrictJSON && type == TokIdentifier)) {
                     Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
 
                     // Check for colon
@@ -338,10 +510,11 @@ JSValue LiteralParser::parse(ParserState initialState)
                         return JSValue();
                     
                     m_lexer.next();
-                    identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
+                    identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
                     stateStack.append(DoParseObjectEndExpression);
                     goto startParseExpression;
-                } else if (type != TokRBrace) 
+                }
+                if (type != TokRBrace) 
                     return JSValue();
                 m_lexer.next();
                 lastValue = objectStack.last();
@@ -351,7 +524,7 @@ JSValue LiteralParser::parse(ParserState initialState)
             doParseObjectStartExpression:
             case DoParseObjectStartExpression: {
                 TokenType type = m_lexer.next();
-                if (type != TokString)
+                if (type != TokString && (m_mode == StrictJSON || type != TokIdentifier))
                     return JSValue();
                 Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
 
@@ -360,13 +533,13 @@ JSValue LiteralParser::parse(ParserState initialState)
                     return JSValue();
 
                 m_lexer.next();
-                identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
+                identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
                 stateStack.append(DoParseObjectEndExpression);
                 goto startParseExpression;
             }
             case DoParseObjectEndExpression:
             {
-                asObject(objectStack.last())->putDirect(identifierStack.last(), lastValue);
+                asObject(objectStack.last())->putDirect(m_exec->globalData(), identifierStack.last(), lastValue);
                 identifierStack.removeLast();
                 if (m_lexer.currentToken().type == TokComma)
                     goto doParseObjectStartExpression;
@@ -387,13 +560,13 @@ JSValue LiteralParser::parse(ParserState initialState)
                     case TokString: {
                         Lexer::LiteralParserToken stringToken = m_lexer.currentToken();
                         m_lexer.next();
-                        lastValue = jsString(m_exec, stringToken.stringToken);
+                        lastValue = jsString(m_exec, makeIdentifier(stringToken.stringToken, stringToken.stringLength).ustring());
                         break;
                     }
                     case TokNumber: {
                         Lexer::LiteralParserToken numberToken = m_lexer.currentToken();
                         m_lexer.next();
-                        lastValue = jsNumber(m_exec, numberToken.numberToken);
+                        lastValue = jsNumber(numberToken.numberToken);
                         break;
                     }
                     case TokNull:
index 0f8072bd583d052931d616f9db809d660338a824..40c3d586f59ae64c627fbf3aa5f15b788c360bbb 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef LiteralParser_h
 #define LiteralParser_h
 
+#include "Identifier.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSValue.h"
 #include "UString.h"
@@ -34,10 +35,10 @@ namespace JSC {
 
     class LiteralParser {
     public:
-        typedef enum { StrictJSON, NonStrictJSON } ParserMode;
-        LiteralParser(ExecState* exec, const UString& s, ParserMode mode)
+        typedef enum { StrictJSON, NonStrictJSON, JSONP } ParserMode;
+        LiteralParser(ExecState* exec, const UChar* characters, unsigned length, ParserMode mode)
             : m_exec(exec)
-            , m_lexer(s, mode)
+            , m_lexer(characters, length, mode)
             , m_mode(mode)
         {
         }
@@ -46,10 +47,33 @@ namespace JSC {
         {
             m_lexer.next();
             JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
+            if (m_lexer.currentToken().type == TokSemi)
+                m_lexer.next();
             if (m_lexer.currentToken().type != TokEnd)
                 return JSValue();
             return result;
         }
+        
+        enum JSONPPathEntryType {
+            JSONPPathEntryTypeDeclare, // var pathEntryName = JSON
+            JSONPPathEntryTypeDot, // <prior entries>.pathEntryName = JSON
+            JSONPPathEntryTypeLookup, // <prior entries>[pathIndex] = JSON
+            JSONPPathEntryTypeCall // <prior entries>(JSON)
+        };
+
+        struct JSONPPathEntry {
+            JSONPPathEntryType m_type;
+            Identifier m_pathEntryName;
+            int m_pathIndex;
+        };
+
+        struct JSONPData {
+            Vector<JSONPPathEntry> m_path;
+            Strong<Unknown> m_value;
+        };
+
+        bool tryJSONPParse(Vector<JSONPData>&, bool needsFullSourceInfo);
+
     private:
         enum ParserState { StartParseObject, StartParseArray, StartParseExpression, 
                            StartParseStatement, StartParseStatementEndStatement, 
@@ -58,29 +82,31 @@ namespace JSC {
         enum TokenType { TokLBracket, TokRBracket, TokLBrace, TokRBrace, 
                          TokString, TokIdentifier, TokNumber, TokColon, 
                          TokLParen, TokRParen, TokComma, TokTrue, TokFalse,
-                         TokNull, TokEnd, TokError };
-
+                         TokNull, TokEnd, TokDot, TokAssign, TokSemi, TokError };
+        
         class Lexer {
         public:
             struct LiteralParserToken {
                 TokenType type;
                 const UChar* start;
                 const UChar* end;
-                UString stringToken;
-                double numberToken;
+                UString stringBuffer;
+                union {
+                    double numberToken;
+                    struct {
+                        const UChar* stringToken;
+                        int stringLength;
+                    };
+                };
             };
-            Lexer(const UString& s, ParserMode mode)
-                : m_string(s)
-                , m_mode(mode)
-                , m_ptr(s.data())
-                , m_end(s.data() + s.size())
+            Lexer(const UChar* characters, unsigned length, ParserMode mode)
+                : m_mode(mode)
+                , m_ptr(characters)
+                , m_end(characters + length)
             {
             }
             
-            TokenType next()
-            {
-                return lex(m_currentToken);
-            }
+            TokenType next();
             
             const LiteralParserToken& currentToken()
             {
@@ -88,9 +114,9 @@ namespace JSC {
             }
             
         private:
-            TokenType lex(LiteralParserToken&);
-            template <ParserMode mode> TokenType lexString(LiteralParserToken&);
-            TokenType lexNumber(LiteralParserToken&);
+            template <ParserMode mode> TokenType lex(LiteralParserToken&);
+            template <ParserMode mode, UChar terminator> ALWAYS_INLINE TokenType lexString(LiteralParserToken&);
+            ALWAYS_INLINE TokenType lexNumber(LiteralParserToken&);
             LiteralParserToken m_currentToken;
             UString m_string;
             ParserMode m_mode;
@@ -104,7 +130,12 @@ namespace JSC {
         ExecState* m_exec;
         LiteralParser::Lexer m_lexer;
         ParserMode m_mode;
+        static unsigned const MaximumCachableCharacter = 128;
+        FixedArray<Identifier, MaximumCachableCharacter> m_shortIdentifiers;
+        FixedArray<Identifier, MaximumCachableCharacter> m_recentIdentifiers;
+        ALWAYS_INLINE const Identifier makeIdentifier(const UChar* characters, size_t length);
     };
+
 }
 
 #endif
index cc1981257fed01b34fd80ca4df527e090ec9e086..25b516efb0fa26e1952f5432ff5199995ddfcb47 100644 (file)
@@ -20,8 +20,8 @@
 #include "config.h"
 #include "Lookup.h"
 
+#include "Executable.h"
 #include "JSFunction.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
@@ -33,7 +33,7 @@ void HashTable::createTable(JSGlobalData* globalData) const
     for (int i = 0; i < compactSize; ++i)
         entries[i].setKey(0);
     for (int i = 0; values[i].key; ++i) {
-        UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef();
+        StringImpl* identifier = Identifier::add(globalData, values[i].key).leakRef();
         int hashIndex = identifier->existingHash() & compactHashSizeMask;
         HashEntry* entry = &entries[hashIndex];
 
@@ -60,7 +60,7 @@ void HashTable::deleteTable() const
     if (table) {
         int max = compactSize;
         for (int i = 0; i != max; ++i) {
-            if (UString::Rep* key = table[i].key())
+            if (StringImpl* key = table[i].key())
                 key->deref();
         }
         delete [] table;
@@ -70,23 +70,26 @@ void HashTable::deleteTable() const
 
 void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot)
 {
+    ASSERT(thisObj->structure()->anonymousSlotCount() > 0);
+    ASSERT(thisObj->getAnonymousValue(0).isCell() && asObject(thisObj->getAnonymousValue(0).asCell())->isGlobalObject());
     ASSERT(entry->attributes() & Function);
-    JSValue* location = thisObj->getDirectLocation(propertyName);
+    WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName);
 
     if (!location) {
-        InternalFunction* function;
+        JSFunction* function;
+        JSGlobalObject* globalObject = asGlobalObject(thisObj->getAnonymousValue(0).asCell());
 #if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
         if (entry->generator())
-            function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, exec->globalData().getThunk(entry->generator()), entry->function());
+            function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->generator()));
         else
 #endif
-            function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function());
+            function = new (exec) JSFunction(exec, globalObject, globalObject->functionStructure(), entry->functionLength(), propertyName, entry->function());
 
-        thisObj->putDirectFunction(propertyName, function, entry->attributes());
-        location = thisObj->getDirectLocation(propertyName);
+        thisObj->putDirectFunction(exec->globalData(), propertyName, function, entry->attributes());
+        location = thisObj->getDirectLocation(exec->globalData(), propertyName);
     }
 
-    slot.setValueSlot(thisObj, location, thisObj->offsetForLocation(location));
+    slot.setValue(thisObj, location->get(), thisObj->offsetForLocation(location));
 }
 
 } // namespace JSC
index dd36400622424b51826e452718006ff41c38e6fc..43184e56dcaaed5e54a3daaa3165e7bc45f9a031 100644 (file)
@@ -53,9 +53,10 @@ namespace JSC {
     typedef PropertySlot::GetValueFunc GetFunction;
     typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
 
-    class HashEntry : public FastAllocBase {
+    class HashEntry {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
-        void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2
+        void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2
 #if ENABLE(JIT)
                         , ThunkGenerator generator = 0
 #endif
@@ -71,12 +72,12 @@ namespace JSC {
             m_next = 0;
         }
 
-        void setKey(UString::Rep* key) { m_key = key; }
-        UString::Rep* key() const { return m_key; }
+        void setKey(StringImpl* key) { m_key = key; }
+        StringImpl* key() const { return m_key; }
 
         unsigned char attributes() const { return m_attributes; }
 
-#if ENABLE(JIT)
+#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
         ThunkGenerator generator() const { ASSERT(m_attributes & Function); return m_u.function.generator; }
 #endif
         NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; }
@@ -91,7 +92,7 @@ namespace JSC {
         HashEntry* next() const { return m_next; }
 
     private:
-        UString::Rep* m_key;
+        StringImpl* m_key;
         unsigned char m_attributes; // JSObject attributes
 
         union {
@@ -159,13 +160,13 @@ namespace JSC {
         {
             ASSERT(table);
 
-            const HashEntry* entry = &table[identifier.ustring().rep()->existingHash() & compactHashSizeMask];
+            const HashEntry* entry = &table[identifier.impl()->existingHash() & compactHashSizeMask];
 
             if (!entry->key())
                 return 0;
 
             do {
-                if (entry->key() == identifier.ustring().rep())
+                if (entry->key() == identifier.impl())
                     return entry;
                 entry = entry->next();
             } while (entry);
@@ -311,9 +312,9 @@ namespace JSC {
 
         if (entry->attributes() & Function) { // function: put as override property
             if (LIKELY(value.isCell()))
-                thisObj->putDirectFunction(propertyName, value.asCell());
+                thisObj->putDirectFunction(exec->globalData(), propertyName, value.asCell());
             else
-                thisObj->putDirect(propertyName, value);
+                thisObj->putDirect(exec->globalData(), propertyName, value);
         } else if (!(entry->attributes() & ReadOnly))
             entry->propertyPutter()(exec, thisObj, value);
 
diff --git a/runtime/MarkStack.cpp b/runtime/MarkStack.cpp
deleted file mode 100644 (file)
index a350c35..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2009 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. 
- */
-
-#include "config.h"
-#include "MarkStack.h"
-
-namespace JSC {
-
-size_t MarkStack::s_pageSize = 0;
-
-void MarkStack::compact()
-{
-    ASSERT(s_pageSize);
-    m_values.shrinkAllocation(s_pageSize);
-    m_markSets.shrinkAllocation(s_pageSize);
-}
-
-}
diff --git a/runtime/MarkStack.h b/runtime/MarkStack.h
deleted file mode 100644 (file)
index c551bac..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2009 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 MarkStack_h
-#define MarkStack_h
-
-#include "JSValue.h"
-#include <wtf/Noncopyable.h>
-
-namespace JSC {
-
-    class JSGlobalData;
-    class Register;
-    
-    enum MarkSetProperties { MayContainNullValues, NoNullValues };
-    
-    class MarkStack : Noncopyable {
-    public:
-        MarkStack(void* jsArrayVPtr)
-            : m_jsArrayVPtr(jsArrayVPtr)
-#ifndef NDEBUG
-            , m_isCheckingForDefaultMarkViolation(false)
-#endif
-        {
-        }
-
-        ALWAYS_INLINE void append(JSValue);
-        void append(JSCell*);
-        
-        ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues)
-        {
-            appendValues(reinterpret_cast<JSValue*>(values), count, properties);
-        }
-
-        ALWAYS_INLINE void appendValues(JSValue* values, size_t count, MarkSetProperties properties = NoNullValues)
-        {
-            if (count)
-                m_markSets.append(MarkSet(values, values + count, properties));
-        }
-
-        inline void drain();
-        void compact();
-
-        ~MarkStack()
-        {
-            ASSERT(m_markSets.isEmpty());
-            ASSERT(m_values.isEmpty());
-        }
-
-    private:
-        void markChildren(JSCell*);
-
-        struct MarkSet {
-            MarkSet(JSValue* values, JSValue* end, MarkSetProperties properties)
-                : m_values(values)
-                , m_end(end)
-                , m_properties(properties)
-            {
-                ASSERT(values);
-            }
-            JSValue* m_values;
-            JSValue* m_end;
-            MarkSetProperties m_properties;
-        };
-
-        static void* allocateStack(size_t size);
-        static void releaseStack(void* addr, size_t size);
-
-        static void initializePagesize();
-        static size_t pageSize()
-        {
-            if (!s_pageSize)
-                initializePagesize();
-            return s_pageSize;
-        }
-
-        template <typename T> struct MarkStackArray {
-            MarkStackArray()
-                : m_top(0)
-                , m_allocated(MarkStack::pageSize())
-                , m_capacity(m_allocated / sizeof(T))
-            {
-                m_data = reinterpret_cast<T*>(allocateStack(m_allocated));
-            }
-
-            ~MarkStackArray()
-            {
-                releaseStack(m_data, m_allocated);
-            }
-
-            void expand()
-            {
-                size_t oldAllocation = m_allocated;
-                m_allocated *= 2;
-                m_capacity = m_allocated / sizeof(T);
-                void* newData = allocateStack(m_allocated);
-                memcpy(newData, m_data, oldAllocation);
-                releaseStack(m_data, oldAllocation);
-                m_data = reinterpret_cast<T*>(newData);
-            }
-
-            inline void append(const T& v)
-            {
-                if (m_top == m_capacity)
-                    expand();
-                m_data[m_top++] = v;
-            }
-
-            inline T removeLast()
-            {
-                ASSERT(m_top);
-                return m_data[--m_top];
-            }
-            
-            inline T& last()
-            {
-                ASSERT(m_top);
-                return m_data[m_top - 1];
-            }
-
-            inline bool isEmpty()
-            {
-                return m_top == 0;
-            }
-
-            inline size_t size() { return m_top; }
-
-            inline void shrinkAllocation(size_t size)
-            {
-                ASSERT(size <= m_allocated);
-                ASSERT(0 == (size % MarkStack::pageSize()));
-                if (size == m_allocated)
-                    return;
-#if OS(WINDOWS) || OS(SYMBIAN) || PLATFORM(BREWMP)
-                // We cannot release a part of a region with VirtualFree.  To get around this,
-                // we'll release the entire region and reallocate the size that we want.
-                releaseStack(m_data, m_allocated);
-                m_data = reinterpret_cast<T*>(allocateStack(size));
-#else
-                releaseStack(reinterpret_cast<char*>(m_data) + size, m_allocated - size);
-#endif
-                m_allocated = size;
-                m_capacity = m_allocated / sizeof(T);
-            }
-
-        private:
-            size_t m_top;
-            size_t m_allocated;
-            size_t m_capacity;
-            T* m_data;
-        };
-
-        void* m_jsArrayVPtr;
-        MarkStackArray<MarkSet> m_markSets;
-        MarkStackArray<JSCell*> m_values;
-        static size_t s_pageSize;
-
-#ifndef NDEBUG
-    public:
-        bool m_isCheckingForDefaultMarkViolation;
-#endif
-    };
-}
-
-#endif
diff --git a/runtime/MarkStackNone.cpp b/runtime/MarkStackNone.cpp
deleted file mode 100644 (file)
index b1ff48b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2009 Company 100, 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.
- */
-
-#include "config.h"
-
-#include "MarkStack.h"
-
-#include "FastMalloc.h"
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
-    MarkStack::s_pageSize = 4096;
-}
-
-void* MarkStack::allocateStack(size_t size)
-{
-    return fastMalloc(size);
-}
-
-void MarkStack::releaseStack(void* addr, size_t)
-{
-    return fastFree(addr);
-}
-
-}
diff --git a/runtime/MarkStackPosix.cpp b/runtime/MarkStackPosix.cpp
deleted file mode 100644 (file)
index c28bc0d..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 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. 
- */
-
-#include "config.h"
-#include "MarkStack.h"
-
-#if OS(UNIX) && !OS(SYMBIAN)
-
-#include <unistd.h>
-#include <sys/mman.h>
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
-    MarkStack::s_pageSize = getpagesize();
-}
-
-void* MarkStack::allocateStack(size_t size)
-{
-    return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
-}
-void MarkStack::releaseStack(void* addr, size_t size)
-{
-    munmap(addr, size);
-}
-
-}
-
-#endif
diff --git a/runtime/MarkStackSymbian.cpp b/runtime/MarkStackSymbian.cpp
deleted file mode 100644 (file)
index bda14ac..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public License
-    along with this library; see the file COPYING.LIB.  If not, write to
-    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-    Boston, MA 02110-1301, USA.
-*/
-
-#include "config.h"
-#include "MarkStack.h"
-
-#if OS(SYMBIAN)
-
-#include <e32hal.h>
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
-    TInt page_size;
-    UserHal::PageSizeInBytes(page_size);
-    MarkStack::s_pageSize = page_size;
-}
-
-void* MarkStack::allocateStack(size_t size)
-{
-    return fastMalloc(size);
-}
-
-void MarkStack::releaseStack(void* addr, size_t size)
-{
-    return fastFree(addr);
-}
-
-}
-
-#endif
diff --git a/runtime/MarkStackWin.cpp b/runtime/MarkStackWin.cpp
deleted file mode 100644 (file)
index a171c78..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2009 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. 
- */
-
-#include "config.h"
-#include "MarkStack.h"
-
-#if OS(WINDOWS)
-
-#include "windows.h"
-
-namespace JSC {
-
-void MarkStack::initializePagesize()
-{
-    SYSTEM_INFO system_info;
-    GetSystemInfo(&system_info);
-    MarkStack::s_pageSize = system_info.dwPageSize;
-}
-
-void* MarkStack::allocateStack(size_t size)
-{
-    return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
-}
-void MarkStack::releaseStack(void* addr, size_t)
-{
-    // According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx,
-    // dwSize must be 0 if dwFreeType is MEM_RELEASE.
-    VirtualFree(addr, 0, MEM_RELEASE);
-}
-
-}
-
-#endif
index 78e14e3c42b6e93c4149fe167312bf7409f855e2..9c85a697cda4038ab12058101071a856c8fccc43 100644 (file)
@@ -34,24 +34,24 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(MathObject);
 
-static JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncACos(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncASin(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncATan(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncCos(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncExp(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*);
 
 }
 
@@ -59,9 +59,7 @@ static JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*, JSObject*, JSValue, co
 
 namespace JSC {
 
-// ------------------------------ MathObject --------------------------------
-
-const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
+const ClassInfo MathObject::s_info = { "Math", &JSObjectWithGlobalObject::s_info, 0, ExecState::mathTable };
 
 /* Source for MathObject.lut.h
 @begin mathTable
@@ -86,20 +84,20 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
 @end
 */
 
-MathObject::MathObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
-    : JSObject(structure)
+MathObject::MathObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+    : JSObjectWithGlobalObject(globalObject, structure)
 {
-    putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "LN2"), jsNumber(exec, log(2.0)), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "LN10"), jsNumber(exec, log(10.0)), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "LOG2E"), jsNumber(exec, 1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "LOG10E"), jsNumber(exec, 1.0 / log(10.0)), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
-    putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
-}
+    ASSERT(inherits(&s_info));
 
-// ECMA 15.8
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "E"), jsNumber(exp(1.0)), DontDelete | DontEnum | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN2"), jsNumber(log(2.0)), DontDelete | DontEnum | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LN10"), jsNumber(log(10.0)), DontDelete | DontEnum | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG2E"), jsNumber(1.0 / log(2.0)), DontDelete | DontEnum | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "LOG10E"), jsNumber(0.4342944819032518), DontDelete | DontEnum | ReadOnly); // See ECMA-262 15.8.1.5
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "PI"), jsNumber(piDouble), DontDelete | DontEnum | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT1_2"), jsNumber(sqrt(0.5)), DontDelete | DontEnum | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SQRT2"), jsNumber(sqrt(2.0)), DontDelete | DontEnum | ReadOnly);
+}
 
 bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
@@ -113,62 +111,64 @@ bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro
 
 // ------------------------------ Functions --------------------------------
 
-JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec)
 {
-    return jsNumber(exec, fabs(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsNumber(fabs(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec)
 {
-    return jsDoubleNumber(exec, acos(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(acos(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec)
 {
-    return jsDoubleNumber(exec, asin(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(asin(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec)
 {
-    return jsDoubleNumber(exec, atan(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(atan(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec)
 {
-    return jsDoubleNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec)));
+    double arg0 = exec->argument(0).toNumber(exec);
+    double arg1 = exec->argument(1).toNumber(exec);
+    return JSValue::encode(jsDoubleNumber(atan2(arg0, arg1)));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec)
 {
-    return jsNumber(exec, ceil(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsNumber(ceil(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec)
 {
-    return jsDoubleNumber(exec, cos(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(cos(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec)
 {
-    return jsDoubleNumber(exec, exp(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(exp(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec)
 {
-    return jsNumber(exec, floor(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsNumber(floor(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec)
 {
-    return jsDoubleNumber(exec, log(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(log(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec)
 {
-    unsigned argsCount = args.size();
+    unsigned argsCount = exec->argumentCount();
     double result = -Inf;
     for (unsigned k = 0; k < argsCount; ++k) {
-        double val = args.at(k).toNumber(exec);
+        double val = exec->argument(k).toNumber(exec);
         if (isnan(val)) {
             result = NaN;
             break;
@@ -176,15 +176,15 @@ JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, cons
         if (val > result || (val == 0 && result == 0 && !signbit(val)))
             result = val;
     }
-    return jsNumber(exec, result);
+    return JSValue::encode(jsNumber(result));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec)
 {
-    unsigned argsCount = args.size();
+    unsigned argsCount = exec->argumentCount();
     double result = +Inf;
     for (unsigned k = 0; k < argsCount; ++k) {
-        double val = args.at(k).toNumber(exec);
+        double val = exec->argument(k).toNumber(exec);
         if (isnan(val)) {
             result = NaN;
             break;
@@ -192,48 +192,48 @@ JSValue JSC_HOST_CALL mathProtoFuncMin(ExecState* exec, JSObject*, JSValue, cons
         if (val < result || (val == 0 && result == 0 && signbit(val)))
             result = val;
     }
-    return jsNumber(exec, result);
+    return JSValue::encode(jsNumber(result));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec)
 {
     // ECMA 15.8.2.1.13
 
-    double arg = args.at(0).toNumber(exec);
-    double arg2 = args.at(1).toNumber(exec);
+    double arg = exec->argument(0).toNumber(exec);
+    double arg2 = exec->argument(1).toNumber(exec);
 
     if (isnan(arg2))
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
     if (isinf(arg2) && fabs(arg) == 1)
-        return jsNaN(exec);
-    return jsNumber(exec, pow(arg, arg2));
+        return JSValue::encode(jsNaN());
+    return JSValue::encode(jsNumber(pow(arg, arg2)));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec)
 {
-    return jsDoubleNumber(exec, exec->lexicalGlobalObject()->weakRandomNumber());
+    return JSValue::encode(jsDoubleNumber(exec->lexicalGlobalObject()->weakRandomNumber()));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec)
 {
-    double arg = args.at(0).toNumber(exec);
+    double arg = exec->argument(0).toNumber(exec);
     double integer = ceil(arg);
-    return jsNumber(exec, integer - (integer - arg > 0.5));
+    return JSValue::encode(jsNumber(integer - (integer - arg > 0.5)));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec)
 {
-    return exec->globalData().cachedSin(exec, args.at(0).toNumber(exec));
+    return JSValue::encode(exec->globalData().cachedSin(exec->argument(0).toNumber(exec)));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec)
 {
-    return jsDoubleNumber(exec, sqrt(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(sqrt(exec->argument(0).toNumber(exec))));
 }
 
-JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec)
 {
-    return jsDoubleNumber(exec, tan(args.at(0).toNumber(exec)));
+    return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
 }
 
 } // namespace JSC
index a9f70313d4feab9e12b30d484b4d588b9ec95df5..75753be2922e9b794be2a14820bd5af8175f48f5 100644 (file)
 #ifndef MathObject_h
 #define MathObject_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
 
-    class MathObject : public JSObject {
+    class MathObject : public JSObjectWithGlobalObject {
     public:
-        MathObject(ExecState*, NonNullPassRefPtr<Structure>);
+        MathObject(ExecState*, JSGlobalObject*, Structure*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     protected:
diff --git a/runtime/MemoryStatistics.cpp b/runtime/MemoryStatistics.cpp
new file mode 100644 (file)
index 0000000..86101f5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "MemoryStatistics.h"
+
+#include "ExecutableAllocator.h"
+#include "JSGlobalData.h"
+#include "RegisterFile.h"
+
+namespace JSC {
+
+GlobalMemoryStatistics globalMemoryStatistics() 
+{
+    GlobalMemoryStatistics stats;
+
+    stats.stackBytes = RegisterFile::committedByteCount();
+#if ENABLE(EXECUTABLE_ALLOCATOR_FIXED)
+    stats.JITBytes = ExecutableAllocator::committedByteCount();
+#else
+    stats.JITBytes = 0;
+#endif
+    return stats;
+}
+
+}
+
+
diff --git a/runtime/MemoryStatistics.h b/runtime/MemoryStatistics.h
new file mode 100644 (file)
index 0000000..d4b8b6f
--- /dev/null
@@ -0,0 +1,45 @@
+/* 
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 MemoryStatistics_h
+#define MemoryStatistics_h
+
+#include "Heap.h"
+
+class JSGlobalData;
+
+namespace JSC {
+
+struct GlobalMemoryStatistics {
+    size_t stackBytes;
+    size_t JITBytes;
+};
+
+GlobalMemoryStatistics globalMemoryStatistics();
+
+}
+
+#endif // MemoryStatistics_h
+
index 36b4fd1d257489ccb10130acb2ad47278a9e3e0a..2a7a7f5d45e3057ea6c550b34eae920d518d6b3b 100644 (file)
@@ -30,30 +30,38 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor);
 
-const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 };
+const ClassInfo NativeErrorConstructor::s_info = { "Function", &InternalFunction::s_info, 0, 0 };
 
-NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString& nameAndMessage)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, nameAndMessage))
+NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, Structure* prototypeStructure, const UString& nameAndMessage)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, nameAndMessage))
 {
-    NativeErrorPrototype* prototype = new (exec) NativeErrorPrototype(exec, prototypeStructure, nameAndMessage, this);
+    ASSERT(inherits(&s_info));
 
-    putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
-    putDirect(exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum);
-    m_errorStructure = ErrorInstance::createStructure(prototype);
-}
+    NativeErrorPrototype* prototype = new (exec) NativeErrorPrototype(exec, globalObject, prototypeStructure, nameAndMessage, this);
 
+    putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5
+    putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | ReadOnly | DontEnum);
+    m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), prototype));
+    ASSERT(m_errorStructure);
+    ASSERT(m_errorStructure->typeInfo().type() == ObjectType);
+}
 
-ErrorInstance* NativeErrorConstructor::construct(ExecState* exec, const ArgList& args)
+void NativeErrorConstructor::visitChildren(SlotVisitor& visitor)
 {
-    ErrorInstance* object = new (exec) ErrorInstance(m_errorStructure);
-    if (!args.at(0).isUndefined())
-        object->putDirect(exec->propertyNames().message, jsString(exec, args.at(0).toString(exec)));
-    return object;
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    InternalFunction::visitChildren(visitor);
+    if (m_errorStructure)
+        visitor.append(&m_errorStructure);
 }
 
-static JSObject* constructWithNativeErrorConstructor(ExecState* exec, JSObject* constructor, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithNativeErrorConstructor(ExecState* exec)
 {
-    return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
+    JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
+    Structure* errorStructure = static_cast<NativeErrorConstructor*>(exec->callee())->errorStructure();
+    ASSERT(errorStructure);
+    return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
 ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructData)
@@ -62,9 +70,11 @@ ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructD
     return ConstructTypeHost;
 }
     
-static JSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState* exec, JSObject* constructor, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callNativeErrorConstructor(ExecState* exec)
 {
-    return static_cast<NativeErrorConstructor*>(constructor)->construct(exec, args);
+    JSValue message = exec->argumentCount() ? exec->argument(0) : jsUndefined();
+    Structure* errorStructure = static_cast<NativeErrorConstructor*>(exec->callee())->errorStructure();
+    return JSValue::encode(ErrorInstance::create(exec, errorStructure, message));
 }
 
 CallType NativeErrorConstructor::getCallData(CallData& callData)
index 891f9226b128421e58efb55518700659f0274e32..4fb16f1a382e8b4c66119516282fb1687732f5e4 100644 (file)
@@ -31,19 +31,24 @@ namespace JSC {
 
     class NativeErrorConstructor : public InternalFunction {
     public:
-        NativeErrorConstructor(ExecState*, NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<Structure> prototypeStructure, const UString&);
+        NativeErrorConstructor(ExecState*, JSGlobalObject*, Structure*, Structure* prototypeStructure, const UString&);
 
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        ErrorInstance* construct(ExecState*, const ArgList&);
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+        Structure* errorStructure() { return m_errorStructure.get(); }
 
     private:
+        static const unsigned StructureFlags = OverridesVisitChildren | InternalFunction::StructureFlags;
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
+        virtual void visitChildren(SlotVisitor&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-
-        RefPtr<Structure> m_errorStructure;
+        WriteBarrier<Structure> m_errorStructure;
     };
 
 } // namespace JSC
index 43ae6664d939e1e4962c9e8ab92a1146ee1632b4..de27d59ee4e2ea05af5a00ac47d0fcb203ac82a1 100644 (file)
@@ -22,6 +22,7 @@
 #include "NativeErrorPrototype.h"
 
 #include "ErrorPrototype.h"
+#include "JSGlobalObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
 #include "UString.h"
@@ -30,12 +31,12 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
 
-NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& nameAndMessage, NativeErrorConstructor* constructor)
-    : JSObject(structure)
+NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& nameAndMessage, NativeErrorConstructor* constructor)
+    : JSObjectWithGlobalObject(globalObject, structure)
 {
-    putDirect(exec->propertyNames().name, jsString(exec, nameAndMessage), 0);
-    putDirect(exec->propertyNames().message, jsString(exec, nameAndMessage), 0);
-    putDirect(exec->propertyNames().constructor, constructor, DontEnum);
+    putDirect(exec->globalData(), exec->propertyNames().name, jsString(exec, nameAndMessage), 0);
+    putDirect(exec->globalData(), exec->propertyNames().message, jsString(exec, nameAndMessage), 0);
+    putDirect(exec->globalData(), exec->propertyNames().constructor, constructor, DontEnum);
 }
 
 } // namespace JSC
index 19468f7444817044155e37eb07f42b0fac2d8c0c..e1b05ceb82bc3f402f31d73659b3829257a10f6d 100644 (file)
 #ifndef NativeErrorPrototype_h
 #define NativeErrorPrototype_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
     class NativeErrorConstructor;
 
-    class NativeErrorPrototype : public JSObject {
+    class NativeErrorPrototype : public JSObjectWithGlobalObject {
     public:
-        NativeErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, const UString&, NativeErrorConstructor*);
+        NativeErrorPrototype(ExecState*, JSGlobalObject*, Structure*, const UString&, NativeErrorConstructor*);
     };
 
 } // namespace JSC
diff --git a/runtime/NativeFunctionWrapper.h b/runtime/NativeFunctionWrapper.h
deleted file mode 100644 (file)
index d4eeb3b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2009 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 NativeFunctionWrapper_h
-#define NativeFunctionWrapper_h
-
-namespace JSC {
-#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-    class JSFunction;
-    typedef JSFunction NativeFunctionWrapper;
-#else
-    class PrototypeFunction;
-    typedef PrototypeFunction NativeFunctionWrapper;
-#endif
-}
-
-#endif
index 0b7e8216e857c5bafa3b8b48fc2bb1bd81545abf..6e469699a8320693e3095940c0b7723525ecec8f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -42,10 +42,10 @@ static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&)
 
 namespace JSC {
 
-const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::numberTable };
+const ClassInfo NumberConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::numberConstructorTable };
 
 /* Source for NumberConstructor.lut.h
-@begin numberTable
+@begin numberConstructorTable
    NaN                   numberConstructorNaNValue       DontEnum|DontDelete|ReadOnly
    NEGATIVE_INFINITY     numberConstructorNegInfinity    DontEnum|DontDelete|ReadOnly
    POSITIVE_INFINITY     numberConstructorPosInfinity    DontEnum|DontDelete|ReadOnly
@@ -54,58 +54,60 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info,
 @end
 */
 
-NumberConstructor::NumberConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className))
+NumberConstructor::NumberConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, NumberPrototype* numberPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, numberPrototype->s_info.className))
 {
+    ASSERT(inherits(&s_info));
+
     // Number.Prototype
-    putDirectWithoutTransition(exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, numberPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
 bool NumberConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
-    return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, slot);
+    return getStaticValueSlot<NumberConstructor, InternalFunction>(exec, ExecState::numberConstructorTable(exec), this, propertyName, slot);
 }
 
 bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
-    return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, descriptor);
+    return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberConstructorTable(exec), this, propertyName, descriptor);
 }
 
-static JSValue numberConstructorNaNValue(ExecState* exec, JSValue, const Identifier&)
+static JSValue numberConstructorNaNValue(ExecState*, JSValue, const Identifier&)
 {
-    return jsNaN(exec);
+    return jsNaN();
 }
 
-static JSValue numberConstructorNegInfinity(ExecState* exec, JSValue, const Identifier&)
+static JSValue numberConstructorNegInfinity(ExecState*, JSValue, const Identifier&)
 {
-    return jsNumber(exec, -Inf);
+    return jsNumber(-Inf);
 }
 
-static JSValue numberConstructorPosInfinity(ExecState* exec, JSValue, const Identifier&)
+static JSValue numberConstructorPosInfinity(ExecState*, JSValue, const Identifier&)
 {
-    return jsNumber(exec, Inf);
+    return jsNumber(Inf);
 }
 
-static JSValue numberConstructorMaxValue(ExecState* exec, JSValue, const Identifier&)
+static JSValue numberConstructorMaxValue(ExecState*, JSValue, const Identifier&)
 {
-    return jsNumber(exec, 1.7976931348623157E+308);
+    return jsNumber(1.7976931348623157E+308);
 }
 
-static JSValue numberConstructorMinValue(ExecState* exec, JSValue, const Identifier&)
+static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&)
 {
-    return jsNumber(exec, 5E-324);
+    return jsNumber(5E-324);
 }
 
 // ECMA 15.7.1
-static JSObject* constructWithNumberConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithNumberConstructor(ExecState* exec)
 {
-    NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
-    double n = args.isEmpty() ? 0 : args.at(0).toNumber(exec);
-    object->setInternalValue(jsNumber(exec, n));
-    return object;
+    NumberObject* object = new (exec) NumberObject(exec->globalData(), asInternalFunction(exec->callee())->globalObject()->numberObjectStructure());
+    double n = exec->argumentCount() ? exec->argument(0).toNumber(exec) : 0;
+    object->setInternalValue(exec->globalData(), jsNumber(n));
+    return JSValue::encode(object);
 }
 
 ConstructType NumberConstructor::getConstructData(ConstructData& constructData)
@@ -115,9 +117,9 @@ ConstructType NumberConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.7.2
-static JSValue JSC_HOST_CALL callNumberConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callNumberConstructor(ExecState* exec)
 {
-    return jsNumber(exec, args.isEmpty() ? 0 : args.at(0).toNumber(exec));
+    return JSValue::encode(jsNumber(!exec->argumentCount() ? 0 : exec->argument(0).toNumber(exec)));
 }
 
 CallType NumberConstructor::getCallData(CallData& callData)
index 723c4b283152b01030225e3fae71b50fe926b918..69aa8a1320a70d8083754deeacdf013acb0039a1 100644 (file)
@@ -29,17 +29,17 @@ namespace JSC {
 
     class NumberConstructor : public InternalFunction {
     public:
-        NumberConstructor(ExecState*, NonNullPassRefPtr<Structure>, NumberPrototype*);
+        NumberConstructor(ExecState*, JSGlobalObject*, Structure*, NumberPrototype*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         JSValue getValueProperty(ExecState*, int token) const;
 
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
         { 
-            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
         }
 
         enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
@@ -50,8 +50,6 @@ namespace JSC {
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
-
-        virtual const ClassInfo* classInfo() const { return &info; }
     };
 
 } // namespace JSC
index 1a7e44ccedfd925eb1a5941a93d1775e21d2f2c9..6ee103b38562951e522c5835295a90a6315f2bc7 100644 (file)
@@ -29,11 +29,12 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NumberObject);
 
-const ClassInfo NumberObject::info = { "Number", 0, 0, 0 };
+const ClassInfo NumberObject::s_info = { "Number", &JSWrapperObject::s_info, 0, 0 };
 
-NumberObject::NumberObject(NonNullPassRefPtr<Structure> structure)
-    : JSWrapperObject(structure)
+NumberObject::NumberObject(JSGlobalData& globalData, Structure* structure)
+    : JSWrapperObject(globalData, structure)
 {
+    ASSERT(inherits(&s_info));
 }
 
 JSValue NumberObject::getJSNumber()
@@ -41,10 +42,10 @@ JSValue NumberObject::getJSNumber()
     return internalValue();
 }
 
-NumberObject* constructNumber(ExecState* exec, JSValue number)
+NumberObject* constructNumber(ExecState* exec, JSGlobalObject* globalObject, JSValue number)
 {
-    NumberObject* object = new (exec) NumberObject(exec->lexicalGlobalObject()->numberObjectStructure());
-    object->setInternalValue(number);
+    NumberObject* object = new (exec) NumberObject(exec->globalData(), globalObject->numberObjectStructure());
+    object->setInternalValue(exec->globalData(), number);
     return object;
 }
 
index 6c18cdd3bfa441ca588bd8b7cbb7e8c5ebdfb749..cba65dd0f724849f8da6ad7ee3737525b363f710 100644 (file)
@@ -27,29 +27,20 @@ namespace JSC {
 
     class NumberObject : public JSWrapperObject {
     public:
-        explicit NumberObject(NonNullPassRefPtr<Structure>);
+        explicit NumberObject(JSGlobalData&, Structure*);
 
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
-    protected:
-#if USE(JSVALUE32)
-        static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags;
-#else
-        static const unsigned StructureFlags = JSWrapperObject::StructureFlags;
-#endif
-
     private:
-        virtual const ClassInfo* classInfo() const { return &info; }
-
         virtual JSValue getJSNumber();
     };
 
-    NumberObject* constructNumber(ExecState*, JSValue);
+    NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
 
 } // namespace JSC
 
index 16ceb5cd5525fee84a30e383dad0771d6b680cbb..cbf29da1a3711980a8ea9cd0607f98b0be6c13fb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
- *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include "Error.h"
 #include "JSFunction.h"
 #include "JSString.h"
-#include "JSStringBuilder.h"
 #include "Operations.h"
-#include "PrototypeFunction.h"
-#include "StringBuilder.h"
 #include "dtoa.h"
 #include <wtf/Assertions.h>
+#include <wtf/DecimalNumber.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
-ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+static EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState*);
+static EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState*);
+static EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*);
+
+}
+
+#include "NumberPrototype.lut.h"
+
+namespace JSC {
 
-static JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*, JSObject*, JSValue, const ArgList&);
+const ClassInfo NumberPrototype::s_info = { "Number", &NumberObject::s_info, 0, ExecState::numberPrototypeTable };
 
-// ECMA 15.7.4
+/* Source for NumberPrototype.lut.h
+@begin numberPrototypeTable
+  toString          numberProtoFuncToString         DontEnum|Function 1
+  toLocaleString    numberProtoFuncToLocaleString   DontEnum|Function 0
+  valueOf           numberProtoFuncValueOf          DontEnum|Function 0
+  toFixed           numberProtoFuncToFixed          DontEnum|Function 1
+  toExponential     numberProtoFuncToExponential    DontEnum|Function 1
+  toPrecision       numberProtoFuncToPrecision      DontEnum|Function 1
+@end
+*/
 
-NumberPrototype::NumberPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
-    : NumberObject(structure)
+ASSERT_CLASS_FITS_IN_CELL(NumberPrototype);
+
+NumberPrototype::NumberPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
+    : NumberObject(exec->globalData(), structure)
 {
-    setInternalValue(jsNumber(exec, 0));
+    setInternalValue(exec->globalData(), jsNumber(0));
 
-    // The constructor will be added later, after NumberConstructor has been constructed
+    ASSERT(inherits(&s_info));
+    putAnonymousValue(globalObject->globalData(), 0, globalObject);
+}
+
+bool NumberPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<NumberObject>(exec, ExecState::numberPrototypeTable(exec), this, propertyName, slot);
+}
 
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toString, numberProtoFuncToString), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, numberProtoFuncToLocaleString), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, numberProtoFuncValueOf), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toFixed, numberProtoFuncToFixed), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toExponential, numberProtoFuncToExponential), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().toPrecision, numberProtoFuncToPrecision), DontEnum);
+bool NumberPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<NumberObject>(exec, ExecState::numberPrototypeTable(exec), this, propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
 
-// ECMA 15.7.4.2 - 15.7.4.7
+static ALWAYS_INLINE bool toThisNumber(JSValue thisValue, double &x)
+{
+    JSValue v = thisValue.getJSNumber();
+    if (UNLIKELY(!v))
+        return false;
+    x = v.uncheckedGetNumber();
+    return true;
+}
 
-static UString integerPartNoExp(double d)
+static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, int high, int& result, bool& isUndefined)
 {
-    int decimalPoint;
-    int sign;
-    char result[80];
-    WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL);
-    bool resultIsInfOrNan = (decimalPoint == 9999);
-    size_t length = strlen(result);
-
-    StringBuilder builder;
-    builder.append(sign ? "-" : "");
-    if (resultIsInfOrNan)
-        builder.append((const char*)result);
-    else if (decimalPoint <= 0)
-        builder.append("0");
-    else {
-        Vector<char, 1024> buf(decimalPoint + 1);
-
-        // FIXME: Remove use of strncpy()
-        if (static_cast<int>(length) <= decimalPoint) {
-            ASSERT(decimalPoint < 1024);
-            memcpy(buf.data(), result, length);
-            memset(buf.data() + length, '0', decimalPoint - length);
-        } else
-            strncpy(buf.data(), result, decimalPoint);
-        buf[decimalPoint] = '\0';
-
-        builder.append((const char*)(buf.data()));
+    result = 0;
+    isUndefined = false;
+
+    JSValue argument0 = exec->argument(0);
+    if (argument0.isUndefined()) {
+        isUndefined = true;
+        return true;
     }
 
-    return builder.build();
+    double asDouble = argument0.toInteger(exec);
+    if (asDouble < low || asDouble > high)
+        return false;
+
+    result = static_cast<int>(asDouble);
+    return true;
 }
 
-static UString charSequence(char c, int count)
+// toExponential converts a number to a string, always formatting as an expoential.
+// This method takes an optional argument specifying a number of *decimal places*
+// to round the significand to (or, put another way, this method optionally rounds
+// to argument-plus-one significant figures).
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec)
 {
-    Vector<char, 2048> buf(count + 1, c);
-    buf[count] = '\0';
+    // Get x (the double value of this, which should be a Number).
+    double x;
+    if (!toThisNumber(exec->hostThisValue(), x))
+        return throwVMTypeError(exec);
+
+    // Get the argument. 
+    int decimalPlacesInExponent;
+    bool isUndefined;
+    if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlacesInExponent, isUndefined))
+        return throwVMError(exec, createRangeError(exec, "toExponential() argument must be between 0 and 20"));
+
+    // Handle NaN and Infinity.
+    if (isnan(x) || isinf(x))
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // Round if the argument is not undefined, always format as exponential.
+    NumberToStringBuffer buffer;
+    unsigned length = isUndefined
+        ? DecimalNumber(x).toStringExponential(buffer, WTF::NumberToStringBufferLength)
+        : DecimalNumber(x, RoundingSignificantFigures, decimalPlacesInExponent + 1).toStringExponential(buffer, WTF::NumberToStringBufferLength);
 
-    return UString(buf.data());
+    return JSValue::encode(jsString(exec, UString(buffer, length)));
 }
 
-static double intPow10(int e)
+// toFixed converts a number to a string, always formatting as an a decimal fraction.
+// This method takes an argument specifying a number of decimal places to round the
+// significand to. However when converting large values (1e+21 and above) this
+// method will instead fallback to calling ToString. 
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec)
 {
-    // This function uses the "exponentiation by squaring" algorithm and
-    // long double to quickly and precisely calculate integer powers of 10.0.
-
-    // This is a handy workaround for <rdar://problem/4494756>
-
-    if (e == 0)
-        return 1.0;
-
-    bool negative = e < 0;
-    unsigned exp = negative ? -e : e;
-
-    long double result = 10.0;
-    bool foundOne = false;
-    for (int bit = 31; bit >= 0; bit--) {
-        if (!foundOne) {
-            if ((exp >> bit) & 1)
-                foundOne = true;
-        } else {
-            result = result * result;
-            if ((exp >> bit) & 1)
-                result = result * 10.0;
-        }
-    }
+    // Get x (the double value of this, which should be a Number).
+    JSValue thisValue = exec->hostThisValue();
+    JSValue v = thisValue.getJSNumber();
+    if (!v)
+        return throwVMTypeError(exec);
+    double x = v.uncheckedGetNumber();
+
+    // Get the argument. 
+    int decimalPlaces;
+    bool isUndefined; // This is ignored; undefined treated as 0.
+    if (!getIntegerArgumentInRange(exec, 0, 20, decimalPlaces, isUndefined))
+        return throwVMError(exec, createRangeError(exec, "toFixed() argument must be between 0 and 20"));
+
+    // 15.7.4.5.7 states "If x >= 10^21, then let m = ToString(x)"
+    // This also covers Ininity, and structure the check so that NaN
+    // values are also handled by numberToString
+    if (!(fabs(x) < 1e+21))
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // The check above will return false for NaN or Infinity, these will be
+    // handled by numberToString.
+    ASSERT(!isnan(x) && !isinf(x));
+
+    // Convert to decimal with rounding, and format as decimal.
+    NumberToStringBuffer buffer;
+    unsigned length = DecimalNumber(x, RoundingDecimalPlaces, decimalPlaces).toStringDecimal(buffer, WTF::NumberToStringBufferLength);
+    return JSValue::encode(jsString(exec, UString(buffer, length)));
+}
+
+// toPrecision converts a number to a string, takeing an argument specifying a
+// number of significant figures to round the significand to. For positive
+// exponent, all values that can be represented using a decimal fraction will
+// be, e.g. when rounding to 3 s.f. any value up to 999 will be formated as a
+// decimal, whilst 1000 is converted to the exponential representation 1.00e+3.
+// For negative exponents values >= 1e-6 are formated as decimal fractions,
+// with smaller values converted to exponential representation.
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec)
+{
+    // Get x (the double value of this, which should be a Number).
+    JSValue thisValue = exec->hostThisValue();
+    JSValue v = thisValue.getJSNumber();
+    if (!v)
+        return throwVMTypeError(exec);
+    double x = v.uncheckedGetNumber();
+
+    // Get the argument. 
+    int significantFigures;
+    bool isUndefined;
+    if (!getIntegerArgumentInRange(exec, 1, 21, significantFigures, isUndefined))
+        return throwVMError(exec, createRangeError(exec, "toPrecision() argument must be between 1 and 21"));
 
-    if (negative)
-        return static_cast<double>(1.0 / result);
-    return static_cast<double>(result);
+    // To precision called with no argument is treated as ToString.
+    if (isUndefined)
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // Handle NaN and Infinity.
+    if (isnan(x) || isinf(x))
+        return JSValue::encode(jsString(exec, UString::number(x)));
+
+    // Convert to decimal with rounding.
+    DecimalNumber number(x, RoundingSignificantFigures, significantFigures);
+    // If number is in the range 1e-6 <= x < pow(10, significantFigures) then format
+    // as decimal. Otherwise, format the number as an exponential.  Decimal format
+    // demands a minimum of (exponent + 1) digits to represent a number, for example
+    // 1234 (1.234e+3) requires 4 digits. (See ECMA-262 15.7.4.7.10.c)
+    NumberToStringBuffer buffer;
+    unsigned length = number.exponent() >= -6 && number.exponent() < significantFigures
+        ? number.toStringDecimal(buffer, WTF::NumberToStringBufferLength)
+        : number.toStringExponential(buffer, WTF::NumberToStringBufferLength);
+    return JSValue::encode(jsString(exec, UString(buffer, length)));
 }
 
-JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     JSValue v = thisValue.getJSNumber();
     if (!v)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    JSValue radixValue = args.at(0);
+    JSValue radixValue = exec->argument(0);
     int radix;
     if (radixValue.isInt32())
         radix = radixValue.asInt32();
@@ -154,7 +236,7 @@ JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValu
         radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0
 
     if (radix == 10)
-        return jsString(exec, v.toString(exec));
+        return JSValue::encode(jsString(exec, v.toString(exec)));
 
     static const char* const digits = "0123456789abcdefghijklmnopqrstuvwxyz";
 
@@ -164,13 +246,13 @@ JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValu
             int x = v.asInt32();
             if (static_cast<unsigned>(x) < 36) { // Exclude negatives
                 JSGlobalData* globalData = &exec->globalData();
-                return globalData->smallStrings.singleCharacterString(globalData, digits[x]);
+                return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, digits[x]));
             }
         }
     }
 
     if (radix < 2 || radix > 36)
-        return throwError(exec, RangeError, "toString() radix argument must be between 2 and 36");
+        return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36"));
 
     // INT_MAX results in 1024 characters left of the dot with radix 2
     // give the same space on the right side. safety checks are in place
@@ -179,7 +261,7 @@ JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValu
     const char* lastCharInString = s + sizeof(s) - 1;
     double x = v.uncheckedGetNumber();
     if (isnan(x) || isinf(x))
-        return jsString(exec, UString::from(x));
+        return JSValue::encode(jsString(exec, UString::number(x)));
 
     bool isNegative = x < 0.0;
     if (isNegative)
@@ -218,257 +300,29 @@ JSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec, JSObject*, JSValu
     *p = '\0';
     ASSERT(p < s + sizeof(s));
 
-    return jsString(exec, startOfResultString);
+    return JSValue::encode(jsString(exec, startOfResultString));
 }
 
-JSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     // FIXME: Not implemented yet.
 
     JSValue v = thisValue.getJSNumber();
     if (!v)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
-    return jsString(exec, v.toString(exec));
+    return JSValue::encode(jsString(exec, v.toString(exec)));
 }
 
-JSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     JSValue v = thisValue.getJSNumber();
     if (!v)
-        return throwError(exec, TypeError);
-
-    return v;
-}
-
-JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
-{
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwError(exec, TypeError);
-
-    JSValue fractionDigits = args.at(0);
-    double df = fractionDigits.toInteger(exec);
-    if (!(df >= 0 && df <= 20))
-        return throwError(exec, RangeError, "toFixed() digits argument must be between 0 and 20");
-    int f = static_cast<int>(df);
-
-    double x = v.uncheckedGetNumber();
-    if (isnan(x))
-        return jsNontrivialString(exec, "NaN");
+        return throwVMTypeError(exec);
 
-    UString s;
-    if (x < 0) {
-        s = "-";
-        x = -x;
-    } else {
-        s = "";
-        if (x == -0.0)
-            x = 0;
-    }
-
-    if (x >= pow(10.0, 21.0))
-        return jsString(exec, makeString(s, UString::from(x)));
-
-    const double tenToTheF = pow(10.0, f);
-    double n = floor(x * tenToTheF);
-    if (fabs(n / tenToTheF - x) >= fabs((n + 1) / tenToTheF - x))
-        n++;
-
-    UString m = integerPartNoExp(n);
-
-    int k = m.size();
-    if (k <= f) {
-        StringBuilder z;
-        for (int i = 0; i < f + 1 - k; i++)
-            z.append('0');
-        z.append(m);
-        m = z.build();
-        k = f + 1;
-        ASSERT(k == static_cast<int>(m.size()));
-    }
-    int kMinusf = k - f;
-
-    if (kMinusf < static_cast<int>(m.size()))
-        return jsString(exec, makeString(s, m.substr(0, kMinusf), ".", m.substr(kMinusf)));
-    return jsString(exec, makeString(s, m.substr(0, kMinusf)));
-}
-
-static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits)
-{
-    if (fractionalDigits <= 0)
-        return;
-
-    int fDigitsInResult = static_cast<int>(resultLength) - 1;
-    buf[i++] = '.';
-    if (fDigitsInResult > 0) {
-        if (fractionalDigits < fDigitsInResult) {
-            strncpy(buf + i, result + 1, fractionalDigits);
-            i += fractionalDigits;
-        } else {
-            ASSERT(i + resultLength - 1 < 80);
-            memcpy(buf + i, result + 1, resultLength - 1);
-            i += static_cast<int>(resultLength) - 1;
-        }
-    }
-
-    for (int j = 0; j < fractionalDigits - fDigitsInResult; j++)
-        buf[i++] = '0';
-}
-
-static void exponentialPartToString(char* buf, int& i, int decimalPoint)
-{
-    buf[i++] = 'e';
-    // decimalPoint can't be more than 3 digits decimal given the
-    // nature of float representation
-    int exponential = decimalPoint - 1;
-    buf[i++] = (exponential >= 0) ? '+' : '-';
-    if (exponential < 0)
-        exponential *= -1;
-    if (exponential >= 100)
-        buf[i++] = static_cast<char>('0' + exponential / 100);
-    if (exponential >= 10)
-        buf[i++] = static_cast<char>('0' + (exponential % 100) / 10);
-    buf[i++] = static_cast<char>('0' + exponential % 10);
-}
-
-JSValue JSC_HOST_CALL numberProtoFuncToExponential(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
-{
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwError(exec, TypeError);
-
-    double x = v.uncheckedGetNumber();
-
-    if (isnan(x) || isinf(x))
-        return jsString(exec, UString::from(x));
-
-    JSValue fractionalDigitsValue = args.at(0);
-    double df = fractionalDigitsValue.toInteger(exec);
-    if (!(df >= 0 && df <= 20))
-        return throwError(exec, RangeError, "toExponential() argument must between 0 and 20");
-    int fractionalDigits = static_cast<int>(df);
-    bool includeAllDigits = fractionalDigitsValue.isUndefined();
-
-    int decimalAdjust = 0;
-    if (x && !includeAllDigits) {
-        double logx = floor(log10(fabs(x)));
-        x /= pow(10.0, logx);
-        const double tenToTheF = pow(10.0, fractionalDigits);
-        double fx = floor(x * tenToTheF) / tenToTheF;
-        double cx = ceil(x * tenToTheF) / tenToTheF;
-
-        if (fabs(fx - x) < fabs(cx - x))
-            x = fx;
-        else
-            x = cx;
-
-        decimalAdjust = static_cast<int>(logx);
-    }
-
-    if (isnan(x))
-        return jsNontrivialString(exec, "NaN");
-
-    if (x == -0.0) // (-0.0).toExponential() should print as 0 instead of -0
-        x = 0;
-
-    int decimalPoint;
-    int sign;
-    char result[80];
-    WTF::dtoa(result, x, 0, &decimalPoint, &sign, NULL);
-    size_t resultLength = strlen(result);
-    decimalPoint += decimalAdjust;
-
-    int i = 0;
-    char buf[80]; // digit + '.' + fractionDigits (max 20) + 'e' + sign + exponent (max?)
-    if (sign)
-        buf[i++] = '-';
-
-    // ? 9999 is the magical "result is Inf or NaN" value.  what's 999??
-    if (decimalPoint == 999) {
-        ASSERT(i + resultLength < 80);
-        memcpy(buf + i, result, resultLength);
-        buf[i + resultLength] = '\0';
-    } else {
-        buf[i++] = result[0];
-
-        if (includeAllDigits)
-            fractionalDigits = static_cast<int>(resultLength) - 1;
-
-        fractionalPartToString(buf, i, result, resultLength, fractionalDigits);
-        exponentialPartToString(buf, i, decimalPoint);
-        buf[i++] = '\0';
-    }
-    ASSERT(i <= 80);
-
-    return jsString(exec, buf);
-}
-
-JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
-{
-    JSValue v = thisValue.getJSNumber();
-    if (!v)
-        return throwError(exec, TypeError);
-
-    double doublePrecision = args.at(0).toIntegerPreserveNaN(exec);
-    double x = v.uncheckedGetNumber();
-    if (args.at(0).isUndefined() || isnan(x) || isinf(x))
-        return jsString(exec, v.toString(exec));
-
-    UString s;
-    if (x < 0) {
-        s = "-";
-        x = -x;
-    } else
-        s = "";
-
-    if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN
-        return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21");
-    int precision = static_cast<int>(doublePrecision);
-
-    int e = 0;
-    UString m;
-    if (x) {
-        e = static_cast<int>(log10(x));
-        double tens = intPow10(e - precision + 1);
-        double n = floor(x / tens);
-        if (n < intPow10(precision - 1)) {
-            e = e - 1;
-            tens = intPow10(e - precision + 1);
-            n = floor(x / tens);
-        }
-
-        if (fabs((n + 1.0) * tens - x) <= fabs(n * tens - x))
-            ++n;
-        // maintain n < 10^(precision)
-        if (n >= intPow10(precision)) {
-            n /= 10.0;
-            e += 1;
-        }
-        ASSERT(intPow10(precision - 1) <= n);
-        ASSERT(n < intPow10(precision));
-
-        m = integerPartNoExp(n);
-        if (e < -6 || e >= precision) {
-            if (m.size() > 1)
-                m = makeString(m.substr(0, 1), ".", m.substr(1));
-            if (e >= 0)
-                return jsMakeNontrivialString(exec, s, m, "e+", UString::from(e));
-            return jsMakeNontrivialString(exec, s, m, "e-", UString::from(-e));
-        }
-    } else {
-        m = charSequence('0', precision);
-        e = 0;
-    }
-
-    if (e == precision - 1)
-        return jsString(exec, makeString(s, m));
-    if (e >= 0) {
-        if (e + 1 < static_cast<int>(m.size()))
-            return jsString(exec, makeString(s, m.substr(0, e + 1), ".", m.substr(e + 1)));
-        return jsString(exec, makeString(s, m));
-    }
-    return jsMakeNontrivialString(exec, s, "0.", charSequence('0', -(e + 1)), m);
+    return JSValue::encode(v);
 }
 
 } // namespace JSC
index 1fb20771e022126a66dcc244e2438001eae76b37..1f1323b687ee7abe47618f107539f271d5b1cd3e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,22 @@ namespace JSC {
 
     class NumberPrototype : public NumberObject {
     public:
-        NumberPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        NumberPrototype(ExecState*, JSGlobalObject*, Structure*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NumberObject::StructureFlags;
+        static const unsigned AnonymousSlotCount = NumberObject::AnonymousSlotCount + 1;
+
+    private:
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
index 89235af7766eb40b12f46913460f8988b039d8c3..d65f14265cdf63fb7449fa49e6f4ef8cdf00af1e 100644 (file)
@@ -27,6 +27,7 @@
 #define NumericStrings_h
 
 #include "UString.h"
+#include <wtf/FixedArray.h>
 #include <wtf/HashFunctions.h>
 
 namespace JSC {
@@ -39,7 +40,7 @@ namespace JSC {
             if (d == entry.key && !entry.value.isNull())
                 return entry.value;
             entry.key = d;
-            entry.value = UString::from(d);
+            entry.value = UString::number(d);
             return entry.value;
         }
 
@@ -51,7 +52,7 @@ namespace JSC {
             if (i == entry.key && !entry.value.isNull())
                 return entry.value;
             entry.key = i;
-            entry.value = UString::from(i);
+            entry.value = UString::number(i);
             return entry.value;
         }
 
@@ -63,7 +64,7 @@ namespace JSC {
             if (i == entry.key && !entry.value.isNull())
                 return entry.value;
             entry.key = i;
-            entry.value = UString::from(i);
+            entry.value = UString::number(i);
             return entry.value;
         }
     private:
@@ -82,14 +83,14 @@ namespace JSC {
         {
             ASSERT(i < cacheSize);
             if (smallIntCache[i].isNull())
-                smallIntCache[i] = UString::from(i);
+                smallIntCache[i] = UString::number(i);
             return smallIntCache[i];
         }
 
-        CacheEntry<double> doubleCache[cacheSize];
-        CacheEntry<int> intCache[cacheSize];
-        CacheEntry<unsigned> unsignedCache[cacheSize];
-        UString smallIntCache[cacheSize];
+        FixedArray<CacheEntry<double>, cacheSize> doubleCache;
+        FixedArray<CacheEntry<int>, cacheSize> intCache;
+        FixedArray<CacheEntry<unsigned>, cacheSize> unsignedCache;
+        FixedArray<UString, cacheSize> smallIntCache;
     };
 
 } // namespace JSC
index 0838eb43755004b579d6347b09b476a0a0ba93cf..c325fa070b1f7bb9460c218b20b62e78bbd4b8a5 100644 (file)
 #include "ObjectConstructor.h"
 
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSFunction.h"
 #include "JSArray.h"
 #include "JSGlobalObject.h"
+#include "Lookup.h"
 #include "ObjectPrototype.h"
 #include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
 
-static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectConstructorCreate(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState*);
 
-ObjectConstructor::ObjectConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
-: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
+}
+
+#include "ObjectConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::objectConstructorTable };
+
+/* Source for ObjectConstructor.lut.h
+@begin objectConstructorTable
+  getPrototypeOf            objectConstructorGetPrototypeOf             DontEnum|Function 1
+  getOwnPropertyDescriptor  objectConstructorGetOwnPropertyDescriptor   DontEnum|Function 2
+  getOwnPropertyNames       objectConstructorGetOwnPropertyNames        DontEnum|Function 1
+  keys                      objectConstructorKeys                       DontEnum|Function 1
+  defineProperty            objectConstructorDefineProperty             DontEnum|Function 3
+  defineProperties          objectConstructorDefineProperties           DontEnum|Function 2
+  create                    objectConstructorCreate                     DontEnum|Function 2
+  seal                      objectConstructorSeal                       DontEnum|Function 1
+  freeze                    objectConstructorFreeze                     DontEnum|Function 1
+  preventExtensions         objectConstructorPreventExtensions          DontEnum|Function 1
+  isSealed                  objectConstructorIsSealed                   DontEnum|Function 1
+  isFrozen                  objectConstructorIsFrozen                   DontEnum|Function 1
+  isExtensible              objectConstructorIsExtensible               DontEnum|Function 1
+@end
+*/
+
+ObjectConstructor::ObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, ObjectPrototype* objectPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "Object"))
 {
     // ECMA 15.2.3.1
-    putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
-    
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
     // no. of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
-    
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getOwnPropertyNames, objectConstructorGetOwnPropertyNames), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().create, objectConstructorCreate), DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
+}
+
+bool ObjectConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<JSObject>(exec, ExecState::objectConstructorTable(exec), this, propertyName, slot);
+}
+
+bool ObjectConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::objectConstructorTable(exec), this, propertyName, descriptor);
 }
 
 // ECMA 15.2.2
-static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args)
+static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
     JSValue arg = args.at(0);
     if (arg.isUndefinedOrNull())
-        return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
-    return arg.toObject(exec);
+        return constructEmptyObject(exec, globalObject);
+    return arg.toObject(exec, globalObject);
 }
 
-static JSObject* constructWithObjectConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithObjectConstructor(ExecState* exec)
 {
-    return constructObject(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
@@ -80,9 +115,10 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
-static JSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callObjectConstructor(ExecState* exec)
 {
-    return constructObject(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructObject(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 CallType ObjectConstructor::getCallData(CallData& callData)
@@ -91,75 +127,75 @@ CallType ObjectConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
-JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec)
 {
-    if (!args.at(0).isObject())
-        return throwError(exec, TypeError, "Requested prototype of a value that is not an object.");
-    return asObject(args.at(0))->prototype();
+    if (!exec->argument(0).isObject())
+        return throwVMError(exec, createTypeError(exec, "Requested prototype of a value that is not an object."));
+    return JSValue::encode(asObject(exec->argument(0))->prototype());
 }
 
-JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec)
 {
-    if (!args.at(0).isObject())
-        return throwError(exec, TypeError, "Requested property descriptor of a value that is not an object.");
-    UString propertyName = args.at(1).toString(exec);
+    if (!exec->argument(0).isObject())
+        return throwVMError(exec, createTypeError(exec, "Requested property descriptor of a value that is not an object."));
+    UString propertyName = exec->argument(1).toString(exec);
     if (exec->hadException())
-        return jsNull();
-    JSObject* object = asObject(args.at(0));
+        return JSValue::encode(jsNull());
+    JSObject* object = asObject(exec->argument(0));
     PropertyDescriptor descriptor;
     if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
-        return jsUndefined();
+        return JSValue::encode(jsUndefined());
     if (exec->hadException())
-        return jsUndefined();
+        return JSValue::encode(jsUndefined());
 
     JSObject* description = constructEmptyObject(exec);
     if (!descriptor.isAccessorDescriptor()) {
-        description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
-        description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
+        description->putDirect(exec->globalData(), exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
+        description->putDirect(exec->globalData(), exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
     } else {
-        description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
-        description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
+        description->putDirect(exec->globalData(), exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
+        description->putDirect(exec->globalData(), exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
     }
     
-    description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
-    description->putDirect(exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
+    description->putDirect(exec->globalData(), exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
+    description->putDirect(exec->globalData(), exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
 
-    return description;
+    return JSValue::encode(description);
 }
 
 // FIXME: Use the enumeration cache.
-JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exec)
 {
-    if (!args.at(0).isObject())
-        return throwError(exec, TypeError, "Requested property names of a value that is not an object.");
+    if (!exec->argument(0).isObject())
+        return throwVMError(exec, createTypeError(exec, "Requested property names of a value that is not an object."));
     PropertyNameArray properties(exec);
-    asObject(args.at(0))->getOwnPropertyNames(exec, properties, IncludeDontEnumProperties);
+    asObject(exec->argument(0))->getOwnPropertyNames(exec, properties, IncludeDontEnumProperties);
     JSArray* names = constructEmptyArray(exec);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++)
         names->push(exec, jsOwnedString(exec, properties[i].ustring()));
-    return names;
+    return JSValue::encode(names);
 }
 
 // FIXME: Use the enumeration cache.
-JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec)
 {
-    if (!args.at(0).isObject())
-        return throwError(exec, TypeError, "Requested keys of a value that is not an object.");
+    if (!exec->argument(0).isObject())
+        return throwVMError(exec, createTypeError(exec, "Requested keys of a value that is not an object."));
     PropertyNameArray properties(exec);
-    asObject(args.at(0))->getOwnPropertyNames(exec, properties);
+    asObject(exec->argument(0))->getOwnPropertyNames(exec, properties);
     JSArray* keys = constructEmptyArray(exec);
     size_t numProperties = properties.size();
     for (size_t i = 0; i < numProperties; i++)
         keys->push(exec, jsOwnedString(exec, properties[i].ustring()));
-    return keys;
+    return JSValue::encode(keys);
 }
 
 // ES5 8.10.5 ToPropertyDescriptor
 static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
 {
     if (!in.isObject()) {
-        throwError(exec, TypeError, "Property description must be an object.");
+        throwError(exec, createTypeError(exec, "Property description must be an object."));
         return false;
     }
     JSObject* description = asObject(in);
@@ -200,8 +236,8 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
             return false;
         if (!get.isUndefined()) {
             CallData callData;
-            if (get.getCallData(callData) == CallTypeNone) {
-                throwError(exec, TypeError, "Getter must be a function.");
+            if (getCallData(get, callData) == CallTypeNone) {
+                throwError(exec, createTypeError(exec, "Getter must be a function."));
                 return false;
             }
         } else
@@ -216,8 +252,8 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
             return false;
         if (!set.isUndefined()) {
             CallData callData;
-            if (set.getCallData(callData) == CallTypeNone) {
-                throwError(exec, TypeError, "Setter must be a function.");
+            if (getCallData(set, callData) == CallTypeNone) {
+                throwError(exec, createTypeError(exec, "Setter must be a function."));
                 return false;
             }
         } else
@@ -230,32 +266,32 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
         return true;
 
     if (desc.value()) {
-        throwError(exec, TypeError, "Invalid property.  'value' present on property with getter or setter.");
+        throwError(exec, createTypeError(exec, "Invalid property.  'value' present on property with getter or setter."));
         return false;
     }
 
     if (desc.writablePresent()) {
-        throwError(exec, TypeError, "Invalid property.  'writable' present on property with getter or setter.");
+        throwError(exec, createTypeError(exec, "Invalid property.  'writable' present on property with getter or setter."));
         return false;
     }
     return true;
 }
 
-JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
 {
-    if (!args.at(0).isObject())
-        return throwError(exec, TypeError, "Properties can only be defined on Objects.");
-    JSObject* O = asObject(args.at(0));
-    UString propertyName = args.at(1).toString(exec);
+    if (!exec->argument(0).isObject())
+        return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects."));
+    JSObject* O = asObject(exec->argument(0));
+    UString propertyName = exec->argument(1).toString(exec);
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
     PropertyDescriptor descriptor;
-    if (!toPropertyDescriptor(exec, args.at(2), descriptor))
-        return jsNull();
+    if (!toPropertyDescriptor(exec, exec->argument(2), descriptor))
+        return JSValue::encode(jsNull());
     ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
     ASSERT(!exec->hadException());
     O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true);
-    return O;
+    return JSValue::encode(O);
 }
 
 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
@@ -292,26 +328,77 @@ static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* pro
     return object;
 }
 
-JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec)
+{
+    if (!exec->argument(0).isObject())
+        return throwVMError(exec, createTypeError(exec, "Properties can only be defined on Objects."));
+    if (!exec->argument(1).isObject())
+        return throwVMError(exec, createTypeError(exec, "Property descriptor list must be an Object."));
+    return JSValue::encode(defineProperties(exec, asObject(exec->argument(0)), asObject(exec->argument(1))));
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec)
+{
+    if (!exec->argument(0).isObject() && !exec->argument(0).isNull())
+        return throwVMError(exec, createTypeError(exec, "Object prototype may only be an Object or null."));
+    JSValue proto = exec->argument(0);
+    JSObject* newObject = proto.isObject() ? constructEmptyObject(exec, asObject(proto)->inheritorID(exec->globalData())) : constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
+    if (exec->argument(1).isUndefined())
+        return JSValue::encode(newObject);
+    if (!exec->argument(1).isObject())
+        return throwVMError(exec, createTypeError(exec, "Property descriptor list must be an Object."));
+    return JSValue::encode(defineProperties(exec, newObject, asObject(exec->argument(1))));
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorSeal(ExecState* exec)
+{
+    JSValue obj = exec->argument(0);
+    if (!obj.isObject())
+        return throwVMError(exec, createTypeError(exec, "Object.seal can only be called on Objects."));
+    asObject(obj)->seal(exec->globalData());
+    return JSValue::encode(obj);
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorFreeze(ExecState* exec)
+{
+    JSValue obj = exec->argument(0);
+    if (!obj.isObject())
+        return throwVMError(exec, createTypeError(exec, "Object.freeze can only be called on Objects."));
+    asObject(obj)->freeze(exec->globalData());
+    return JSValue::encode(obj);
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorPreventExtensions(ExecState* exec)
+{
+    JSValue obj = exec->argument(0);
+    if (!obj.isObject())
+        return throwVMError(exec, createTypeError(exec, "Object.preventExtensions can only be called on Objects."));
+    asObject(obj)->preventExtensions(exec->globalData());
+    return JSValue::encode(obj);
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorIsSealed(ExecState* exec)
+{
+    JSValue obj = exec->argument(0);
+    if (!obj.isObject())
+        return throwVMError(exec, createTypeError(exec, "Object.isSealed can only be called on Objects."));
+    return JSValue::encode(jsBoolean(asObject(obj)->isSealed(exec->globalData())));
+}
+
+EncodedJSValue JSC_HOST_CALL objectConstructorIsFrozen(ExecState* exec)
 {
-    if (!args.at(0).isObject())
-        return throwError(exec, TypeError, "Properties can only be defined on Objects.");
-    if (!args.at(1).isObject())
-        return throwError(exec, TypeError, "Property descriptor list must be an Object.");
-    return defineProperties(exec, asObject(args.at(0)), asObject(args.at(1)));
+    JSValue obj = exec->argument(0);
+    if (!obj.isObject())
+        return throwVMError(exec, createTypeError(exec, "Object.isFrozen can only be called on Objects."));
+    return JSValue::encode(jsBoolean(asObject(obj)->isFrozen(exec->globalData())));
 }
 
-JSValue JSC_HOST_CALL objectConstructorCreate(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectConstructorIsExtensible(ExecState* exec)
 {
-    if (!args.at(0).isObject() && !args.at(0).isNull())
-        return throwError(exec, TypeError, "Object prototype may only be an Object or null.");
-    JSObject* newObject = constructEmptyObject(exec);
-    newObject->setPrototype(args.at(0));
-    if (args.at(1).isUndefined())
-        return newObject;
-    if (!args.at(1).isObject())
-        return throwError(exec, TypeError, "Property descriptor list must be an Object.");
-    return defineProperties(exec, newObject, asObject(args.at(1)));
+    JSValue obj = exec->argument(0);
+    if (!obj.isObject())
+        return throwVMError(exec, createTypeError(exec, "Object.isExtensible can only be called on Objects."));
+    return JSValue::encode(jsBoolean(asObject(obj)->isExtensible()));
 }
 
 } // namespace JSC
index 1d2cddeacca5cee733d363aea6b26fd2a81457fa..6ebafcdadfaa8c568414a206dfa0242eb36441f9 100644 (file)
@@ -29,7 +29,20 @@ namespace JSC {
 
     class ObjectConstructor : public InternalFunction {
     public:
-        ObjectConstructor(ExecState*, NonNullPassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure);
+        ObjectConstructor(ExecState*, JSGlobalObject*, Structure*, ObjectPrototype*);
+
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
index c32a00734acc82800d4cdb6141dc16ba03324ce5..2c1f96388a0fbcb8da09f524674d2d4dcd36c0fa 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*);
+static EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*);
+
+}
+
+#include "ObjectPrototype.lut.h"
+
+namespace JSC {
+
+const ClassInfo ObjectPrototype::s_info = { "Object", &JSNonFinalObject::s_info, 0, ExecState::objectPrototypeTable };
+
+/* Source for ObjectPrototype.lut.h
+@begin objectPrototypeTable
+  toString              objectProtoFuncToString                 DontEnum|Function 0
+  toLocaleString        objectProtoFuncToLocaleString           DontEnum|Function 0
+  valueOf               objectProtoFuncValueOf                  DontEnum|Function 0
+  hasOwnProperty        objectProtoFuncHasOwnProperty           DontEnum|Function 1
+  propertyIsEnumerable  objectProtoFuncPropertyIsEnumerable     DontEnum|Function 1
+  isPrototypeOf         objectProtoFuncIsPrototypeOf            DontEnum|Function 1
+  __defineGetter__      objectProtoFuncDefineGetter             DontEnum|Function 2
+  __defineSetter__      objectProtoFuncDefineSetter             DontEnum|Function 2
+  __lookupGetter__      objectProtoFuncLookupGetter             DontEnum|Function 1
+  __lookupSetter__      objectProtoFuncLookupSetter             DontEnum|Function 1
+@end
+*/
+
 ASSERT_CLASS_FITS_IN_CELL(ObjectPrototype);
 
-static JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&);
-
-ObjectPrototype::ObjectPrototype(ExecState* exec, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure)
-    : JSObject(stucture)
+ObjectPrototype::ObjectPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* stucture)
+    : JSNonFinalObject(exec->globalData(), stucture)
     , m_hasNoPropertiesWithUInt32Names(true)
 {
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, objectProtoFuncToString), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toLocaleString, objectProtoFuncToLocaleString), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().valueOf, objectProtoFuncValueOf), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().hasOwnProperty, objectProtoFuncHasOwnProperty), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().propertyIsEnumerable, objectProtoFuncPropertyIsEnumerable), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isPrototypeOf, objectProtoFuncIsPrototypeOf), DontEnum);
-
-    // Mozilla extensions
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineGetter__, objectProtoFuncDefineGetter), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().__defineSetter__, objectProtoFuncDefineSetter), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupGetter__, objectProtoFuncLookupGetter), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().__lookupSetter__, objectProtoFuncLookupSetter), DontEnum);
+    ASSERT(inherits(&s_info));
+    putAnonymousValue(globalObject->globalData(), 0, globalObject);
 }
 
 void ObjectPrototype::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
 {
-    JSObject::put(exec, propertyName, value, slot);
+    JSNonFinalObject::put(exec, propertyName, value, slot);
 
     if (m_hasNoPropertiesWithUInt32Names) {
         bool isUInt32;
-        propertyName.toStrictUInt32(&isUInt32);
+        propertyName.toUInt32(isUInt32);
         m_hasNoPropertiesWithUInt32Names = !isUInt32;
     }
 }
@@ -74,82 +86,100 @@ bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName,
 {
     if (m_hasNoPropertiesWithUInt32Names)
         return false;
-    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
+    return JSNonFinalObject::getOwnPropertySlot(exec, propertyName, slot);
 }
 
-// ------------------------------ Functions --------------------------------
+bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), this, propertyName, slot);
+}
 
-// ECMA 15.2.4.2, 15.2.4.4, 15.2.4.5, 15.2.4.7
+bool ObjectPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<JSNonFinalObject>(exec, ExecState::objectPrototypeTable(exec), this, propertyName, descriptor);
+}
+
+// ------------------------------ Functions --------------------------------
 
-JSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncValueOf(ExecState* exec)
 {
-    return thisValue.toThisObject(exec);
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(thisValue.toThisObject(exec));
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
 {
-    return jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, args.at(0).toString(exec))));
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(jsBoolean(thisValue.toThisObject(exec)->hasOwnProperty(exec, Identifier(exec, exec->argument(0).toString(exec)))));
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     JSObject* thisObj = thisValue.toThisObject(exec);
 
-    if (!args.at(0).isObject())
-        return jsBoolean(false);
+    if (!exec->argument(0).isObject())
+        return JSValue::encode(jsBoolean(false));
 
-    JSValue v = asObject(args.at(0))->prototype();
+    JSValue v = asObject(exec->argument(0))->prototype();
 
     while (true) {
         if (!v.isObject())
-            return jsBoolean(false);
-        if (v == thisObj)\v
-            return jsBoolean(true);
+            return JSValue::encode(jsBoolean(false));
+        if (v == thisObj)
+            return JSValue::encode(jsBoolean(true));
         v = asObject(v)->prototype();
     }
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineGetter(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     CallData callData;
-    if (args.at(1).getCallData(callData) == CallTypeNone)
-        return throwError(exec, SyntaxError, "invalid getter usage");
-    thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1)));
-    return jsUndefined();
+    if (getCallData(exec->argument(1), callData) == CallTypeNone)
+        return throwVMError(exec, createSyntaxError(exec, "invalid getter usage"));
+    thisValue.toThisObject(exec)->defineGetter(exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)));
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncDefineSetter(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     CallData callData;
-    if (args.at(1).getCallData(callData) == CallTypeNone)
-        return throwError(exec, SyntaxError, "invalid setter usage");
-    thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, args.at(0).toString(exec)), asObject(args.at(1)));
-    return jsUndefined();
+    if (getCallData(exec->argument(1), callData) == CallTypeNone)
+        return throwVMError(exec, createSyntaxError(exec, "invalid setter usage"));
+    thisValue.toThisObject(exec)->defineSetter(exec, Identifier(exec, exec->argument(0).toString(exec)), asObject(exec->argument(1)));
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec)
 {
-    return thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, args.at(0).toString(exec)));
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(thisValue.toThisObject(exec)->lookupGetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
 {
-    return thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, args.at(0).toString(exec)));
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(thisValue.toThisObject(exec)->lookupSetter(exec, Identifier(exec, exec->argument(0).toString(exec))));
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState* exec)
 {
-    return jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, args.at(0).toString(exec))));
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(jsBoolean(thisValue.toThisObject(exec)->propertyIsEnumerable(exec, Identifier(exec, exec->argument(0).toString(exec)))));
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec)
 {
-    return thisValue.toThisJSString(exec);
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(thisValue.toThisJSString(exec));
 }
 
-JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec)
 {
-    return jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]");
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisValue.toThisObject(exec)->className(), "]"));
 }
 
 } // namespace JSC
index 489d962441b02efba2dc2b6a7839a6d87796d4d2..ec30b9c1feb80916e08ee707682f09dd3d03aaf4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 
 namespace JSC {
 
-    class ObjectPrototype : public JSObject {
+    class ObjectPrototype : public JSNonFinalObject {
     public:
-        ObjectPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        ObjectPrototype(ExecState*, JSGlobalObject*, Structure*);
+
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSNonFinalObject::StructureFlags;
+        static const unsigned AnonymousSlotCount = JSNonFinalObject::AnonymousSlotCount + 1;
 
     private:
         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         bool m_hasNoPropertiesWithUInt32Names;
     };
 
-    JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+    EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
 
 } // namespace JSC
 
index cf236bf5e3f5df963f5d3c0465ffafcdee3286c4..f129a805580b0600711aeac6006cefbc2b311a20 100644 (file)
@@ -55,7 +55,7 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2)
     if (p2.isString())
         return jsString(callFrame, p1.toString(callFrame), asString(p2));
 
-    return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame));
+    return jsNumber(p1.toNumber(callFrame) + p2.toNumber(callFrame));
 }
 
 JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
@@ -85,7 +85,7 @@ bool jsIsObjectType(JSValue v)
     if (!v.isCell())
         return v.isNull();
 
-    JSType type = asCell(v)->structure()->typeInfo().type();
+    JSType type = v.asCell()->structure()->typeInfo().type();
     if (type == NumberType || type == StringType)
         return false;
     if (type == ObjectType) {
index 122890247e1c3042dad8487290fd56a09de0af2e..c102eebed3aa663699ffc519f5964797d4a1f1e6 100644 (file)
@@ -24,9 +24,8 @@
 
 #include "ExceptionHelpers.h"
 #include "Interpreter.h"
-#include "JSImmediate.h"
-#include "JSNumberCell.h"
 #include "JSString.h"
+#include "JSValueInlineMethods.h"
 
 namespace JSC {
 
@@ -46,7 +45,7 @@ namespace JSC {
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
-        unsigned fiberCount = s1->size() + s2->size();
+        unsigned fiberCount = s1->fiberCount() + s2->fiberCount();
         JSGlobalData* globalData = &exec->globalData();
 
         if (fiberCount <= JSString::s_maxInternalRopeLength)
@@ -62,7 +61,7 @@ namespace JSC {
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2)
     {
-        unsigned length1 = u1.size();
+        unsigned length1 = u1.length();
         if (!length1)
             return s2;
         unsigned length2 = s2->length();
@@ -71,7 +70,7 @@ namespace JSC {
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
-        unsigned fiberCount = 1 + s2->size();
+        unsigned fiberCount = 1 + s2->fiberCount();
         JSGlobalData* globalData = &exec->globalData();
 
         if (fiberCount <= JSString::s_maxInternalRopeLength)
@@ -90,13 +89,13 @@ namespace JSC {
         unsigned length1 = s1->length();
         if (!length1)
             return jsString(exec, u2);
-        unsigned length2 = u2.size();
+        unsigned length2 = u2.length();
         if (!length2)
             return s1;
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
-        unsigned fiberCount = s1->size() + 1;
+        unsigned fiberCount = s1->fiberCount() + 1;
         JSGlobalData* globalData = &exec->globalData();
 
         if (fiberCount <= JSString::s_maxInternalRopeLength)
@@ -112,10 +111,10 @@ namespace JSC {
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2)
     {
-        unsigned length1 = u1.size();
+        unsigned length1 = u1.length();
         if (!length1)
             return jsString(exec, u2);
-        unsigned length2 = u2.size();
+        unsigned length2 = u2.length();
         if (!length2)
             return jsString(exec, u1);
         if ((length1 + length2) < length1)
@@ -127,9 +126,9 @@ namespace JSC {
 
     ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3)
     {
-        unsigned length1 = u1.size();
-        unsigned length2 = u2.size();
-        unsigned length3 = u3.size();
+        unsigned length1 = u1.length();
+        unsigned length2 = u2.length();
+        unsigned length3 = u3.length();
         if (!length1)
             return jsString(exec, u2, u3);
         if (!length2)
@@ -154,7 +153,7 @@ namespace JSC {
         for (unsigned i = 0; i < count; ++i) {
             JSValue v = strings[i].jsValue();
             if (LIKELY(v.isString()))
-                fiberCount += asString(v)->size();
+                fiberCount += asString(v)->fiberCount();
             else
                 ++fiberCount;
         }
@@ -189,17 +188,17 @@ namespace JSC {
         return new (globalData) JSString(globalData, ropeBuilder.release());
     }
 
-    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args)
+    ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue)
     {
         unsigned fiberCount = 0;
         if (LIKELY(thisValue.isString()))
-            fiberCount += asString(thisValue)->size();
+            fiberCount += asString(thisValue)->fiberCount();
         else
             ++fiberCount;
-        for (unsigned i = 0; i < args.size(); ++i) {
-            JSValue v = args.at(i);
+        for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+            JSValue v = exec->argument(i);
             if (LIKELY(v.isString()))
-                fiberCount += asString(v)->size();
+                fiberCount += asString(v)->fiberCount();
             else
                 ++fiberCount;
         }
@@ -216,8 +215,8 @@ namespace JSC {
         unsigned length = 0;
         bool overflow = false;
 
-        for (unsigned i = 0; i < args.size(); ++i) {
-            JSValue v = args.at(i);
+        for (unsigned i = 0; i < exec->argumentCount(); ++i) {
+            JSValue v = exec->argument(i);
             if (LIKELY(v.isString()))
                 ropeBuilder.append(asString(v));
             else
@@ -398,7 +397,7 @@ namespace JSC {
     {
         double left = 0.0, right;
         if (v1.getNumber(left) && v2.getNumber(right))
-            return jsNumber(callFrame, left + right);
+            return jsNumber(left + right);
         
         if (v1.isString()) {
             return v2.isString()
@@ -412,7 +411,7 @@ namespace JSC {
 
     inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, size_t& slotOffset)
     {
-        JSCell* cell = asCell(base);
+        JSCell* cell = base.asCell();
         size_t count = 0;
 
         while (slotBase != cell) {
@@ -424,14 +423,14 @@ namespace JSC {
             if (v.isNull())
                 return 0;
 
-            cell = asCell(v);
+            cell = v.asCell();
 
             // Since we're accessing a prototype in a loop, it's a good bet that it
             // should not be treated as a dictionary.
             if (cell->structure()->isDictionary()) {
-                asObject(cell)->flattenDictionaryObject();
+                asObject(cell)->flattenDictionaryObject(callFrame->globalData());
                 if (slotBase == cell)
-                    slotOffset = cell->structure()->get(propertyName); 
+                    slotOffset = cell->structure()->get(callFrame->globalData(), propertyName); 
             }
 
             ++count;
@@ -449,18 +448,18 @@ namespace JSC {
             if (v.isNull())
                 return count;
 
-            base = asCell(v);
+            base = v.asCell();
 
             // Since we're accessing a prototype in a loop, it's a good bet that it
             // should not be treated as a dictionary.
             if (base->structure()->isDictionary())
-                asObject(base)->flattenDictionaryObject();
+                asObject(base)->flattenDictionaryObject(callFrame->globalData());
 
             ++count;
         }
     }
 
-    ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain)
+    ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain, bool isStrictPut)
     {
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator next = iter;
@@ -471,8 +470,13 @@ namespace JSC {
         PropertySlot slot;
         JSObject* base;
         while (true) {
-            base = *iter;
-            if (next == end || base->getPropertySlot(callFrame, property, slot))
+            base = iter->get();
+            if (next == end) {
+                if (isStrictPut && !base->getPropertySlot(callFrame, property, slot))
+                    return JSValue();
+                return base;
+            }
+            if (base->getPropertySlot(callFrame, property, slot))
                 return base;
 
             iter = next;
index 44dc2b84ffd40cb8866cc0ddb27527ede48457e1..28a9364948dda664804fadc54794566001f9a251 100644 (file)
 #define PropertyMapHashTable_h
 
 #include "UString.h"
+#include "WriteBarrier.h"
+#include <wtf/HashTable.h>
+#include <wtf/PassOwnPtr.h>
 #include <wtf/Vector.h>
 
+
+#ifndef NDEBUG
+#define DUMP_PROPERTYMAP_STATS 0
+#else
+#define DUMP_PROPERTYMAP_STATS 0
+#endif
+
+#if DUMP_PROPERTYMAP_STATS
+
+extern int numProbes;
+extern int numCollisions;
+extern int numRehashes;
+extern int numRemoves;
+
+#endif
+
+#define PROPERTY_MAP_DELETED_ENTRY_KEY ((StringImpl*)1) 
+
 namespace JSC {
 
-    struct PropertyMapEntry {
-        UString::Rep* key;
-        unsigned offset;
-        unsigned attributes;
-        JSCell* specificValue;
-        unsigned index;
-
-        PropertyMapEntry(UString::Rep* key, unsigned attributes, JSCell* specificValue)
-            : key(key)
-            , offset(0)
-            , attributes(attributes)
-            , specificValue(specificValue)
-            , index(0)
+inline bool isPowerOf2(unsigned v)
+{
+    // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
+    
+    return !(v & (v - 1)) && v;
+}
+
+inline unsigned nextPowerOf2(unsigned v)
+{
+    // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
+    // Devised by Sean Anderson, Sepember 14, 2001
+
+    v--;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    v++;
+
+    return v;
+}
+
+struct PropertyMapEntry {
+    StringImpl* key;
+    unsigned offset;
+    unsigned attributes;
+    WriteBarrier<JSCell> specificValue;
+
+    PropertyMapEntry(JSGlobalData& globalData, JSCell* owner, StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue)
+        : key(key)
+        , offset(offset)
+        , attributes(attributes)
+        , specificValue(globalData, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)
+    {
+    }
+};
+
+class PropertyTable {
+    WTF_MAKE_FAST_ALLOCATED;
+
+    // This is the implementation for 'iterator' and 'const_iterator',
+    // used for iterating over the table in insertion order.
+    template<typename T>
+    class ordered_iterator {
+    public:
+        ordered_iterator<T>& operator++()
         {
+            m_valuePtr = skipDeletedEntries(m_valuePtr + 1);
+            return *this;
         }
 
-        PropertyMapEntry(UString::Rep* key, unsigned offset, unsigned attributes, JSCell* specificValue, unsigned index)
-            : key(key)
-            , offset(offset)
-            , attributes(attributes)
-            , specificValue(specificValue)
-            , index(index)
+        bool operator==(const ordered_iterator<T>& other)
         {
+            return m_valuePtr == other.m_valuePtr;
+        }
+
+        bool operator!=(const ordered_iterator<T>& other)
+        {
+            return m_valuePtr != other.m_valuePtr;
+        }
+
+        T& operator*()
+        {
+            return *m_valuePtr;
         }
-    };
 
-    // lastIndexUsed is an ever-increasing index used to identify the order items
-    // were inserted into the property map. It's required that getEnumerablePropertyNames
-    // return the properties in the order they were added for compatibility with other
-    // browsers' JavaScript implementations.
-    struct PropertyMapHashTable {
-        unsigned sizeMask;
-        unsigned size;
-        unsigned keyCount;
-        unsigned deletedSentinelCount;
-        unsigned lastIndexUsed;
-        Vector<unsigned>* deletedOffsets;
-        unsigned entryIndices[1];
-
-        PropertyMapEntry* entries()
+        T* operator->()
         {
-            // The entries vector comes after the indices vector.
-            // The 0th item in the entries vector is not really used; it has to
-            // have a 0 in its key to allow the hash table lookup to handle deleted
-            // sentinels without any special-case code, but the other fields are unused.
-            return reinterpret_cast<PropertyMapEntry*>(&entryIndices[size]);
+            return m_valuePtr;
         }
 
-        static size_t allocationSize(unsigned size)
+        ordered_iterator(T* valuePtr)
+            : m_valuePtr(valuePtr)
         {
-            // We never let a hash table get more than half full,
-            // So the number of indices we need is the size of the hash table.
-            // But the number of entries is half that (plus one for the deleted sentinel).
-            return sizeof(PropertyMapHashTable)
-                + (size - 1) * sizeof(unsigned)
-                + (1 + size / 2) * sizeof(PropertyMapEntry);
         }
+
+    private:
+        T* m_valuePtr;
     };
 
+public:
+    typedef StringImpl* KeyType;
+    typedef PropertyMapEntry ValueType;
+
+    // The in order iterator provides overloaded * and -> to access the Value at the current position.
+    typedef ordered_iterator<ValueType> iterator;
+    typedef ordered_iterator<const ValueType> const_iterator;
+
+    // The find_iterator is a pair of a pointer to a Value* an the entry in the index.
+    // If 'find' does not find an entry then iter.first will be 0, and iter.second will
+    // give the point in m_index where an entry should be inserted.
+    typedef std::pair<ValueType*, unsigned> find_iterator;
+
+    // Constructor is passed an initial capacity, a PropertyTable to copy, or both.
+    explicit PropertyTable(unsigned initialCapacity);
+    PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&);
+    PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&);
+    ~PropertyTable();
+
+    // Ordered iteration methods.
+    iterator begin();
+    iterator end();
+    const_iterator begin() const;
+    const_iterator end() const;
+
+    // Find a value in the table.
+    find_iterator find(const KeyType& key);
+    // Add a value to the table
+    std::pair<find_iterator, bool> add(const ValueType& entry);
+    // Remove a value from the table.
+    void remove(const find_iterator& iter);
+    void remove(const KeyType& key);
+
+    // Returns the number of values in the hashtable.
+    unsigned size() const;
+
+    // Checks if there are any values in the hashtable.
+    bool isEmpty() const;
+
+    // Number of slots in the property storage array in use, included deletedOffsets.
+    unsigned propertyStorageSize() const;
+
+    // Used to maintain a list of unused entries in the property storage.
+    void clearDeletedOffsets();
+    bool hasDeletedOffset();
+    unsigned getDeletedOffset();
+    void addDeletedOffset(unsigned offset);
+
+    // Copy this PropertyTable, ensuring the copy has at least the capacity provided.
+    PassOwnPtr<PropertyTable> copy(JSGlobalData&, JSCell* owner, unsigned newCapacity);
+
+#ifndef NDEBUG
+    size_t sizeInMemory();
+    void checkConsistency();
+#endif
+
+private:
+    PropertyTable(const PropertyTable&);
+    // Used to insert a value known not to be in the table, and where we know capacity to be available.
+    void reinsert(const ValueType& entry);
+
+    // Rehash the table.  Used to grow, or to recover deleted slots.
+    void rehash(unsigned newCapacity);
+
+    // The capacity of the table of values is half of the size of the index.
+    unsigned tableCapacity() const;
+
+    // We keep an extra deleted slot after the array to make iteration work,
+    // and to use for deleted values. Index values into the array are 1-based,
+    // so this is tableCapacity() + 1.
+    // For example, if m_tableSize is 16, then tableCapacity() is 8 - but the
+    // values array is actually 9 long (the 9th used for the deleted value/
+    // iteration guard).  The 8 valid entries are numbered 1..8, so the
+    // deleted index is 9 (0 being reserved for empty).
+    unsigned deletedEntryIndex() const;
+
+    // Used in iterator creation/progression.
+    template<typename T>
+    static T* skipDeletedEntries(T* valuePtr);
+
+    // The table of values lies after the hash index.
+    ValueType* table();
+    const ValueType* table() const;
+
+    // total number of  used entries in the values array - by either valid entries, or deleted ones.
+    unsigned usedCount() const;
+
+    // The size in bytes of data needed for by the table.
+    size_t dataSize();
+
+    // Calculates the appropriate table size (rounds up to a power of two).
+    static unsigned sizeForCapacity(unsigned capacity);
+
+    // Check if capacity is available.
+    bool canInsert();
+
+    unsigned m_indexSize;
+    unsigned m_indexMask;
+    unsigned* m_index;
+    unsigned m_keyCount;
+    unsigned m_deletedCount;
+    OwnPtr< Vector<unsigned> > m_deletedOffsets;
+
+    static const unsigned MinimumTableSize = 16;
+    static const unsigned EmptyEntryIndex = 0;
+};
+
+inline PropertyTable::PropertyTable(unsigned initialCapacity)
+    : m_indexSize(sizeForCapacity(initialCapacity))
+    , m_indexMask(m_indexSize - 1)
+    , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
+    , m_keyCount(0)
+    , m_deletedCount(0)
+{
+    ASSERT(isPowerOf2(m_indexSize));
+}
+
+inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, const PropertyTable& other)
+    : m_indexSize(other.m_indexSize)
+    , m_indexMask(other.m_indexMask)
+    , m_index(static_cast<unsigned*>(fastMalloc(dataSize())))
+    , m_keyCount(other.m_keyCount)
+    , m_deletedCount(other.m_deletedCount)
+{
+    ASSERT(isPowerOf2(m_indexSize));
+
+    memcpy(m_index, other.m_index, dataSize());
+
+    iterator end = this->end();
+    for (iterator iter = begin(); iter != end; ++iter) {
+        iter->key->ref();
+        Heap::writeBarrier(owner, iter->specificValue.get());
+    }
+
+    // Copy the m_deletedOffsets vector.
+    Vector<unsigned>* otherDeletedOffsets = other.m_deletedOffsets.get();
+    if (otherDeletedOffsets)
+        m_deletedOffsets = adoptPtr(new Vector<unsigned>(*otherDeletedOffsets));
+}
+
+inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable& other)
+    : m_indexSize(sizeForCapacity(initialCapacity))
+    , m_indexMask(m_indexSize - 1)
+    , m_index(static_cast<unsigned*>(fastZeroedMalloc(dataSize())))
+    , m_keyCount(0)
+    , m_deletedCount(0)
+{
+    ASSERT(isPowerOf2(m_indexSize));
+    ASSERT(initialCapacity >= other.m_keyCount);
+
+    const_iterator end = other.end();
+    for (const_iterator iter = other.begin(); iter != end; ++iter) {
+        ASSERT(canInsert());
+        reinsert(*iter);
+        iter->key->ref();
+        Heap::writeBarrier(owner, iter->specificValue.get());
+    }
+
+    // Copy the m_deletedOffsets vector.
+    Vector<unsigned>* otherDeletedOffsets = other.m_deletedOffsets.get();
+    if (otherDeletedOffsets)
+        m_deletedOffsets = adoptPtr(new Vector<unsigned>(*otherDeletedOffsets));
+}
+
+inline PropertyTable::~PropertyTable()
+{
+    iterator end = this->end();
+    for (iterator iter = begin(); iter != end; ++iter)
+        iter->key->deref();
+
+    fastFree(m_index);
+}
+
+inline PropertyTable::iterator PropertyTable::begin()
+{
+    return iterator(skipDeletedEntries(table()));
+}
+
+inline PropertyTable::iterator PropertyTable::end()
+{
+    return iterator(table() + usedCount());
+}
+
+inline PropertyTable::const_iterator PropertyTable::begin() const
+{
+    return const_iterator(skipDeletedEntries(table()));
+}
+
+inline PropertyTable::const_iterator PropertyTable::end() const
+{
+    return const_iterator(table() + usedCount());
+}
+
+inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key)
+{
+    ASSERT(key);
+    unsigned hash = key->existingHash();
+    unsigned step = 0;
+
+#if DUMP_PROPERTYMAP_STATS
+    ++numProbes;
+#endif
+
+    while (true) {
+        unsigned entryIndex = m_index[hash & m_indexMask];
+        if (entryIndex == EmptyEntryIndex)
+            return std::make_pair((ValueType*)0, hash & m_indexMask);
+        if (key == table()[entryIndex - 1].key)
+            return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask);
+
+#if DUMP_PROPERTYMAP_STATS
+        ++numCollisions;
+#endif
+
+        if (!step)
+            step =WTF::doubleHash(key->existingHash()) | 1;
+        hash += step;
+
+#if DUMP_PROPERTYMAP_STATS
+        ++numRehashes;
+#endif
+    }
+}
+
+inline std::pair<PropertyTable::find_iterator, bool> PropertyTable::add(const ValueType& entry)
+{
+    // Look for a value with a matching key already in the array.
+    find_iterator iter = find(entry.key);
+    if (iter.first)
+        return std::make_pair(iter, false);
+
+    // Ref the key
+    entry.key->ref();
+
+    // ensure capacity is available.
+    if (!canInsert()) {
+        rehash(m_keyCount + 1);
+        iter = find(entry.key);
+        ASSERT(!iter.first);
+    }
+
+    // Allocate a slot in the hashtable, and set the index to reference this.
+    unsigned entryIndex = usedCount() + 1;
+    m_index[iter.second] = entryIndex;
+    iter.first = &table()[entryIndex - 1];
+    *iter.first = entry;
+
+    ++m_keyCount;
+    return std::make_pair(iter, true);
+}
+
+inline void PropertyTable::remove(const find_iterator& iter)
+{
+    // Removing a key that doesn't exist does nothing!
+    if (!iter.first)
+        return;
+
+#if DUMP_PROPERTYMAP_STATS
+    ++numRemoves;
+#endif
+
+    // Replace this one element with the deleted sentinel. Also clear out
+    // the entry so we can iterate all the entries as needed.
+    m_index[iter.second] = deletedEntryIndex();
+    iter.first->key->deref();
+    iter.first->key = PROPERTY_MAP_DELETED_ENTRY_KEY;
+
+    ASSERT(m_keyCount >= 1);
+    --m_keyCount;
+    ++m_deletedCount;
+
+    if (m_deletedCount * 4 >= m_indexSize)
+        rehash(m_keyCount);
+}
+
+inline void PropertyTable::remove(const KeyType& key)
+{
+    remove(find(key));
+}
+
+// returns the number of values in the hashtable.
+inline unsigned PropertyTable::size() const
+{
+    return m_keyCount;
+}
+
+inline bool PropertyTable::isEmpty() const
+{
+    return !m_keyCount;
+}
+
+inline unsigned PropertyTable::propertyStorageSize() const
+{
+    return size() + (m_deletedOffsets ? m_deletedOffsets->size() : 0);
+}
+
+inline void PropertyTable::clearDeletedOffsets()
+{
+    m_deletedOffsets.clear();
+}
+
+inline bool PropertyTable::hasDeletedOffset()
+{
+    return m_deletedOffsets && !m_deletedOffsets->isEmpty();
+}
+
+inline unsigned PropertyTable::getDeletedOffset()
+{
+    unsigned offset = m_deletedOffsets->last();
+    m_deletedOffsets->removeLast();
+    return offset;
+}
+
+inline void PropertyTable::addDeletedOffset(unsigned offset)
+{
+    if (!m_deletedOffsets)
+        m_deletedOffsets = adoptPtr(new Vector<unsigned>);
+    m_deletedOffsets->append(offset);
+}
+
+inline PassOwnPtr<PropertyTable> PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity)
+{
+    ASSERT(newCapacity >= m_keyCount);
+
+    // Fast case; if the new table will be the same m_indexSize as this one, we can memcpy it,
+    // save rehashing all keys.
+    if (sizeForCapacity(newCapacity) == m_indexSize)
+        return adoptPtr(new PropertyTable(globalData, owner, *this));
+    return adoptPtr(new PropertyTable(globalData, owner, newCapacity, *this));
+}
+
+#ifndef NDEBUG
+inline size_t PropertyTable::sizeInMemory()
+{
+    size_t result = sizeof(PropertyTable) + dataSize();
+    if (m_deletedOffsets)
+        result += (m_deletedOffsets->capacity() * sizeof(unsigned));
+    return result;
+}
+#endif
+
+inline void PropertyTable::reinsert(const ValueType& entry)
+{
+    // Used to insert a value known not to be in the table, and where
+    // we know capacity to be available.
+    ASSERT(canInsert());
+    find_iterator iter = find(entry.key);
+    ASSERT(!iter.first);
+
+    unsigned entryIndex = usedCount() + 1;
+    m_index[iter.second] = entryIndex;
+    table()[entryIndex - 1] = entry;
+
+    ++m_keyCount;
+}
+
+inline void PropertyTable::rehash(unsigned newCapacity)
+{
+    unsigned* oldEntryIndices = m_index;
+    iterator iter = this->begin();
+    iterator end = this->end();
+
+    m_indexSize = sizeForCapacity(newCapacity);
+    m_indexMask = m_indexSize - 1;
+    m_keyCount = 0;
+    m_deletedCount = 0;
+    m_index = static_cast<unsigned*>(fastZeroedMalloc(dataSize()));
+
+    for (; iter != end; ++iter) {
+        ASSERT(canInsert());
+        reinsert(*iter);
+    }
+
+    fastFree(oldEntryIndices);
+}
+
+inline unsigned PropertyTable::tableCapacity() const { return m_indexSize >> 1; }
+
+inline unsigned PropertyTable::deletedEntryIndex() const { return tableCapacity() + 1; }
+
+template<typename T>
+inline T* PropertyTable::skipDeletedEntries(T* valuePtr)
+{
+    while (valuePtr->key == PROPERTY_MAP_DELETED_ENTRY_KEY)
+        ++valuePtr;
+    return valuePtr;
+}
+
+inline PropertyTable::ValueType* PropertyTable::table()
+{
+    // The table of values lies after the hash index.
+    return reinterpret_cast<ValueType*>(m_index + m_indexSize);
+}
+
+inline const PropertyTable::ValueType* PropertyTable::table() const
+{
+    // The table of values lies after the hash index.
+    return reinterpret_cast<const ValueType*>(m_index + m_indexSize);
+}
+
+inline unsigned PropertyTable::usedCount() const
+{
+    // Total number of  used entries in the values array - by either valid entries, or deleted ones.
+    return m_keyCount + m_deletedCount;
+}
+
+inline size_t PropertyTable::dataSize()
+{
+    // The size in bytes of data needed for by the table.
+    return m_indexSize * sizeof(unsigned) + ((tableCapacity()) + 1) * sizeof(ValueType);
+}
+
+inline unsigned PropertyTable::sizeForCapacity(unsigned capacity)
+{
+    if (capacity < 8)
+        return MinimumTableSize;
+    return nextPowerOf2(capacity + 1) * 2;
+}
+
+inline bool PropertyTable::canInsert()
+{
+    return usedCount() < tableCapacity();
+}
+
 } // namespace JSC
 
 #endif // PropertyMapHashTable_h
index 6b246691ba24af4b596cdbd2e719a271d480998f..8efb4065e1739cf05d5d9166c75becd80dde30fc 100644 (file)
@@ -21,6 +21,8 @@
 #include "config.h"
 #include "PropertyNameArray.h"
 
+#include "JSObject.h"
+#include "ScopeChain.h"
 #include "Structure.h"
 #include "StructureChain.h"
 
@@ -28,20 +30,20 @@ namespace JSC {
 
 static const size_t setThreshold = 20;
 
-void PropertyNameArray::add(UString::Rep* identifier)
+void PropertyNameArray::add(StringImpl* identifier)
 {
-    ASSERT(identifier == UString::null().rep() || identifier == UString::Rep::empty() || identifier->isIdentifier());
+    ASSERT(!identifier || identifier == StringImpl::empty() || identifier->isIdentifier());
 
     size_t size = m_data->propertyNameVector().size();
     if (size < setThreshold) {
         for (size_t i = 0; i < size; ++i) {
-            if (identifier == m_data->propertyNameVector()[i].ustring().rep())
+            if (identifier == m_data->propertyNameVector()[i].impl())
                 return;
         }
     } else {
         if (m_set.isEmpty()) {
             for (size_t i = 0; i < size; ++i)
-                m_set.add(m_data->propertyNameVector()[i].ustring().rep());
+                m_set.add(m_data->propertyNameVector()[i].impl());
         }
         if (!m_set.add(identifier).second)
             return;
index 3dbcc9df746ffaa1f8e6f760a5dc072ca44d391c..0da930f173f13f4a3e1b8c04d666a8c041a71ad5 100644 (file)
@@ -68,9 +68,9 @@ namespace JSC {
 
         JSGlobalData* globalData() { return m_globalData; }
 
-        void add(const Identifier& identifier) { add(identifier.ustring().rep()); }
-        void add(UString::Rep*);
-        void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
+        void add(const Identifier& identifier) { add(identifier.impl()); }
+        void add(StringImpl*);
+        void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); }
 
         Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
         const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
@@ -86,7 +86,7 @@ namespace JSC {
         const_iterator end() const { return m_data->propertyNameVector().end(); }
 
     private:
-        typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet;
+        typedef HashSet<StringImpl*, PtrHash<StringImpl*> > IdentifierSet;
 
         RefPtr<PropertyNameArrayData> m_data;
         IdentifierSet m_set;
index 2306a11e576fe820501be6e3537c517af7e1474f..fd16c0c092b740e99fd91b3ec34a7527cfc1de48 100644 (file)
@@ -34,11 +34,7 @@ JSValue PropertySlot::functionGetter(ExecState* exec) const
 
     CallData callData;
     CallType callType = m_data.getterFunc->getCallData(callData);
-    if (callType == CallTypeHost)
-        return callData.native.function(exec, m_data.getterFunc, thisValue(), exec->emptyList());
-    ASSERT(callType == CallTypeJS);
-    // FIXME: Can this be done more efficiently using the callData?
-    return asFunction(m_data.getterFunc)->call(exec, thisValue(), exec->emptyList());
+    return call(exec, m_data.getterFunc, callType, callData, thisValue(), exec->emptyList());
 }
 
 } // namespace JSC
index de9ddc99822a633f024e96362188d9d5c4ab6bc0..ce29ac4e6c7bb85553e7abcb79741adba36104f0 100644 (file)
@@ -32,8 +32,7 @@ namespace JSC {
     class ExecState;
     class JSObject;
 
-#define JSC_VALUE_SLOT_MARKER 0
-#define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
+#define JSC_VALUE_MARKER 0
 #define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2)
 #define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3)
 
@@ -67,10 +66,8 @@ namespace JSC {
 
         JSValue getValue(ExecState* exec, const Identifier& propertyName) const
         {
-            if (m_getValue == JSC_VALUE_SLOT_MARKER)
-                return *m_data.valueSlot;
-            if (m_getValue == JSC_REGISTER_SLOT_MARKER)
-                return (*m_data.registerSlot).jsValue();
+            if (m_getValue == JSC_VALUE_MARKER)
+                return m_value;
             if (m_getValue == INDEX_GETTER_MARKER)
                 return m_getIndexValue(exec, slotBase(), index());
             if (m_getValue == GETTER_FUNCTION_MARKER)
@@ -80,10 +77,8 @@ namespace JSC {
 
         JSValue getValue(ExecState* exec, unsigned propertyName) const
         {
-            if (m_getValue == JSC_VALUE_SLOT_MARKER)
-                return *m_data.valueSlot;
-            if (m_getValue == JSC_REGISTER_SLOT_MARKER)
-                return (*m_data.registerSlot).jsValue();
+            if (m_getValue == JSC_VALUE_MARKER)
+                return m_value;
             if (m_getValue == INDEX_GETTER_MARKER)
                 return m_getIndexValue(exec, m_slotBase, m_data.index);
             if (m_getValue == GETTER_FUNCTION_MARKER)
@@ -100,50 +95,32 @@ namespace JSC {
             return m_offset;
         }
 
-        void setValueSlot(JSValue* valueSlot) 
+        void setValue(JSValue slotBase, JSValue value)
         {
-            ASSERT(valueSlot);
-            clearBase();
+            ASSERT(value);
             clearOffset();
-            m_getValue = JSC_VALUE_SLOT_MARKER;
-            m_data.valueSlot = valueSlot;
-        }
-        
-        void setValueSlot(JSValue slotBase, JSValue* valueSlot)
-        {
-            ASSERT(valueSlot);
-            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_getValue = JSC_VALUE_MARKER;
             m_slotBase = slotBase;
-            m_data.valueSlot = valueSlot;
+            m_value = value;
         }
         
-        void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset)
+        void setValue(JSValue slotBase, JSValue value, size_t offset)
         {
-            ASSERT(valueSlot);
-            m_getValue = JSC_VALUE_SLOT_MARKER;
+            ASSERT(value);
+            m_getValue = JSC_VALUE_MARKER;
             m_slotBase = slotBase;
-            m_data.valueSlot = valueSlot;
+            m_value = value;
             m_offset = offset;
             m_cachedPropertyType = Value;
         }
-        
+
         void setValue(JSValue value)
         {
             ASSERT(value);
             clearBase();
             clearOffset();
-            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_getValue = JSC_VALUE_MARKER;
             m_value = value;
-            m_data.valueSlot = &m_value;
-        }
-
-        void setRegisterSlot(Register* registerSlot)
-        {
-            ASSERT(registerSlot);
-            clearBase();
-            clearOffset();
-            m_getValue = JSC_REGISTER_SLOT_MARKER;
-            m_data.registerSlot = registerSlot;
         }
 
         void setCustom(JSValue slotBase, GetValueFunc getValue)
@@ -251,8 +228,6 @@ namespace JSC {
         JSValue m_slotBase;
         union {
             JSObject* getterFunc;
-            JSValue* valueSlot;
-            Register* registerSlot;
             unsigned index;
         } m_data;
 
index a0d5443dce723923e09c0c524a5231dae9b9c709..843c9e11148cc70a67cdb6625447263168bff7a8 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef Protect_h
 #define Protect_h
 
-#include "Collector.h"
+#include "Heap.h"
 #include "JSValue.h"
 
 namespace JSC {
@@ -52,164 +52,15 @@ namespace JSC {
     inline void gcProtect(JSValue value)
     {
         if (value && value.isCell())
-            gcProtect(asCell(value));
+            gcProtect(value.asCell());
     }
 
     inline void gcUnprotect(JSValue value)
     {
         if (value && value.isCell())
-            gcUnprotect(asCell(value));
+            gcUnprotect(value.asCell());
     }
 
-    // FIXME: Share more code with RefPtr template? The only differences are the ref/deref operation
-    // and the implicit conversion to raw pointer
-    template <class T> class ProtectedPtr {
-    public:
-        ProtectedPtr() : m_ptr(0) {}
-        ProtectedPtr(T* ptr);
-        ProtectedPtr(const ProtectedPtr&);
-        ~ProtectedPtr();
-
-        template <class U> ProtectedPtr(const ProtectedPtr<U>&);
-        
-        T* get() const { return m_ptr; }
-        operator T*() const { return m_ptr; }
-        operator JSValue() const { return JSValue(m_ptr); }
-        T* operator->() const { return m_ptr; }
-        
-        operator bool() const { return m_ptr; }
-        bool operator!() const { return !m_ptr; }
-
-        ProtectedPtr& operator=(const ProtectedPtr&);
-        ProtectedPtr& operator=(T*);
-        
-    private:
-        T* m_ptr;
-    };
-
-    class ProtectedJSValue {
-    public:
-        ProtectedJSValue() {}
-        ProtectedJSValue(JSValue value);
-        ProtectedJSValue(const ProtectedJSValue&);
-        ~ProtectedJSValue();
-
-        template <class U> ProtectedJSValue(const ProtectedPtr<U>&);
-        
-        JSValue get() const { return m_value; }
-        operator JSValue() const { return m_value; }
-        JSValue operator->() const { return m_value; }
-        
-        operator bool() const { return m_value; }
-        bool operator!() const { return !m_value; }
-
-        ProtectedJSValue& operator=(const ProtectedJSValue&);
-        ProtectedJSValue& operator=(JSValue);
-        
-    private:
-        JSValue m_value;
-    };
-
-    template <class T> inline ProtectedPtr<T>::ProtectedPtr(T* ptr)
-        : m_ptr(ptr)
-    {
-        gcProtectNullTolerant(m_ptr);
-    }
-
-    template <class T> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr& o)
-        : m_ptr(o.get())
-    {
-        gcProtectNullTolerant(m_ptr);
-    }
-
-    template <class T> inline ProtectedPtr<T>::~ProtectedPtr()
-    {
-        gcUnprotectNullTolerant(m_ptr);
-    }
-
-    template <class T> template <class U> inline ProtectedPtr<T>::ProtectedPtr(const ProtectedPtr<U>& o)
-        : m_ptr(o.get())
-    {
-        gcProtectNullTolerant(m_ptr);
-    }
-
-    template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(const ProtectedPtr<T>& o) 
-    {
-        T* optr = o.m_ptr;
-        gcProtectNullTolerant(optr);
-        gcUnprotectNullTolerant(m_ptr);
-        m_ptr = optr;
-        return *this;
-    }
-
-    template <class T> inline ProtectedPtr<T>& ProtectedPtr<T>::operator=(T* optr)
-    {
-        gcProtectNullTolerant(optr);
-        gcUnprotectNullTolerant(m_ptr);
-        m_ptr = optr;
-        return *this;
-    }
-
-    inline ProtectedJSValue::ProtectedJSValue(JSValue value)
-        : m_value(value)
-    {
-        gcProtect(m_value);
-    }
-
-    inline ProtectedJSValue::ProtectedJSValue(const ProtectedJSValue& o)
-        : m_value(o.get())
-    {
-        gcProtect(m_value);
-    }
-
-    inline ProtectedJSValue::~ProtectedJSValue()
-    {
-        gcUnprotect(m_value);
-    }
-
-    template <class U> ProtectedJSValue::ProtectedJSValue(const ProtectedPtr<U>& o)
-        : m_value(o.get())
-    {
-        gcProtect(m_value);
-    }
-
-    inline ProtectedJSValue& ProtectedJSValue::operator=(const ProtectedJSValue& o) 
-    {
-        JSValue ovalue = o.m_value;
-        gcProtect(ovalue);
-        gcUnprotect(m_value);
-        m_value = ovalue;
-        return *this;
-    }
-
-    inline ProtectedJSValue& ProtectedJSValue::operator=(JSValue ovalue)
-    {
-        gcProtect(ovalue);
-        gcUnprotect(m_value);
-        m_value = ovalue;
-        return *this;
-    }
-
-    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() == b.get(); }
-    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const T* b) { return a.get() == b; }
-    template <class T> inline bool operator==(const T* a, const ProtectedPtr<T>& b) { return a == b.get(); }
-
-    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedPtr<T>& b) { return a.get() != b.get(); }
-    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const T* b) { return a.get() != b; }
-    template <class T> inline bool operator!=(const T* a, const ProtectedPtr<T>& b) { return a != b.get(); }
-
-    inline bool operator==(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() == b.get(); }
-    inline bool operator==(const ProtectedJSValue& a, const JSValue b) { return a.get() == b; }
-    template <class T> inline bool operator==(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() == JSValue(b.get()); }
-    inline bool operator==(const JSValue a, const ProtectedJSValue& b) { return a == b.get(); }
-    template <class T> inline bool operator==(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) == b.get(); }
-
-    inline bool operator!=(const ProtectedJSValue& a, const ProtectedJSValue& b) { return a.get() != b.get(); }
-    inline bool operator!=(const ProtectedJSValue& a, const JSValue b) { return a.get() != b; }
-    template <class T> inline bool operator!=(const ProtectedJSValue& a, const ProtectedPtr<T>& b) { return a.get() != JSValue(b.get()); }
-    inline bool operator!=(const JSValue a, const ProtectedJSValue& b) { return a != b.get(); }
-    template <class T> inline bool operator!=(const ProtectedPtr<T>& a, const ProtectedJSValue& b) { return JSValue(a.get()) != b.get(); }
 } // namespace JSC
 
 #endif // Protect_h
diff --git a/runtime/PrototypeFunction.cpp b/runtime/PrototypeFunction.cpp
deleted file mode 100644 (file)
index 38f8adb..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
- *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *  Copyright (C) 2007 Maks Orlovich
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-#include "PrototypeFunction.h"
-
-#include "JSGlobalObject.h"
-#include <wtf/Assertions.h>
-
-namespace JSC {
-
-ASSERT_CLASS_FITS_IN_CELL(PrototypeFunction);
-
-PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifier& name, NativeFunction function)
-    : InternalFunction(&exec->globalData(), exec->lexicalGlobalObject()->prototypeFunctionStructure(), name)
-    , m_function(function)
-{
-    ASSERT_ARG(function, function);
-    putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
-}
-
-PrototypeFunction::PrototypeFunction(ExecState* exec, NonNullPassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function)
-    : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name)
-    , m_function(function)
-{
-    ASSERT_ARG(function, function);
-    putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
-}
-    
-CallType PrototypeFunction::getCallData(CallData& callData)
-{
-    callData.native.function = m_function;
-    return CallTypeHost;
-}
-
-} // namespace JSC
diff --git a/runtime/PrototypeFunction.h b/runtime/PrototypeFunction.h
deleted file mode 100644 (file)
index 70ee034..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
- *  Copyright (C) 2007 Maks Orlovich
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef PrototypeFunction_h
-#define PrototypeFunction_h
-
-#include "InternalFunction.h"
-#include "CallData.h"
-
-namespace JSC {
-
-    class PrototypeFunction : public InternalFunction {
-    public:
-        PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction);
-        PrototypeFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction);
-
-    private:
-        virtual CallType getCallData(CallData&);
-
-        const NativeFunction m_function;
-    };
-
-} // namespace JSC
-
-#endif // PrototypeFunction_h
index eb8ea8a9942f7aaf1cb8003c92ced76bb4dd3cbf..69d1f8bd29df6f7b3951615dd4cac0e26963adf4 100644 (file)
@@ -38,9 +38,10 @@ namespace JSC {
     public:
         enum Type { Uncachable, ExistingProperty, NewProperty };
 
-        PutPropertySlot()
+        PutPropertySlot(bool isStrictMode = false)
             : m_type(Uncachable)
             , m_base(0)
+            , m_isStrictMode(isStrictMode)
         {
         }
 
@@ -61,15 +62,18 @@ namespace JSC {
         Type type() const { return m_type; }
         JSObject* base() const { return m_base; }
 
+        bool isStrictMode() const { return m_isStrictMode; }
         bool isCacheable() const { return m_type != Uncachable; }
         size_t cachedOffset() const {
             ASSERT(isCacheable());
             return m_offset;
         }
+
     private:
         Type m_type;
         JSObject* m_base;
         size_t m_offset;
+        bool m_isStrictMode;
     };
 
 } // namespace JSC
index 59f1f87f7747570ef4b2e1842d6bda3bedd4d5ac..9211a90ede39214b4f2ce4cd91d44d071696ac81 100644 (file)
@@ -2,6 +2,7 @@
  *  Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
  *  Copyright (c) 2007, 2008 Apple Inc. All rights reserved.
  *  Copyright (C) 2009 Torch Mobile, Inc.
+ *  Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 
 #include "config.h"
 #include "RegExp.h"
+
 #include "Lexer.h"
+#include "RegExpCache.h"
+#include "yarr/Yarr.h"
+#include "yarr/YarrJIT.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wtf/Assertions.h>
 #include <wtf/OwnArrayPtr.h>
 
-
-#if ENABLE(YARR)
-
-#include "yarr/RegexCompiler.h"
-#if ENABLE(YARR_JIT)
-#include "yarr/RegexJIT.h"
-#else
-#include "yarr/RegexInterpreter.h"
-#endif
-
-#else
-
-#include <pcre/pcre.h>
-
-#endif
-
 namespace JSC {
 
-inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern)
-    : m_pattern(pattern)
-    , m_flagBits(0)
-    , m_constructionError(0)
-    , m_numSubpatterns(0)
-    , m_lastMatchStart(-1)
+const ClassInfo RegExp::s_info = { "RegExp", 0, 0, 0 };
+
+RegExpFlags regExpFlags(const UString& string)
 {
-    compile(globalData);
-}
+    RegExpFlags flags = NoFlags;
+
+    for (unsigned i = 0; i < string.length(); ++i) {
+        switch (string.characters()[i]) {
+        case 'g':
+            if (flags & FlagGlobal)
+                return InvalidFlags;
+            flags = static_cast<RegExpFlags>(flags | FlagGlobal);
+            break;
+
+        case 'i':
+            if (flags & FlagIgnoreCase)
+                return InvalidFlags;
+            flags = static_cast<RegExpFlags>(flags | FlagIgnoreCase);
+            break;
+
+        case 'm':
+            if (flags & FlagMultiline)
+                return InvalidFlags;
+            flags = static_cast<RegExpFlags>(flags | FlagMultiline);
+            break;
+
+        default:
+            return InvalidFlags;
+        }
+    }
 
-inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags)
-    : m_pattern(pattern)
-    , m_flagBits(0)
+    return flags;
+}
+  
+struct RegExpRepresentation {
+#if ENABLE(YARR_JIT)
+    Yarr::YarrCodeBlock m_regExpJITCode;
+#endif
+    OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
+};
+
+RegExp::RegExp(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
+    : JSCell(*globalData, globalData->regExpStructure.get())
+    , m_state(NotCompiled)
+    , m_patternString(patternString)
+    , m_flags(flags)
     , m_constructionError(0)
     , m_numSubpatterns(0)
-    , m_lastMatchStart(-1)
+#if ENABLE(REGEXP_TRACING)
+    , m_rtMatchCallCount(0)
+    , m_rtMatchFoundCount(0)
+#endif
 {
-    // NOTE: The global flag is handled on a case-by-case basis by functions like
-    // String::match and RegExpObject::match.
-    if (flags.find('g') != UString::NotFound)
-        m_flagBits |= Global;
-    if (flags.find('i') != UString::NotFound)
-        m_flagBits |= IgnoreCase;
-    if (flags.find('m') != UString::NotFound)
-        m_flagBits |= Multiline;
-
-    compile(globalData);
+    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
+    if (m_constructionError)
+        m_state = ParseError;
+    else
+        m_numSubpatterns = pattern.m_numSubpatterns;
 }
 
-#if !ENABLE(YARR)
 RegExp::~RegExp()
 {
-    jsRegExpFree(m_regExp);
 }
-#endif
 
-PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern)
+RegExp* RegExp::create(JSGlobalData* globalData, const UString& patternString, RegExpFlags flags)
 {
-    return adoptRef(new RegExp(globalData, pattern));
+    return globalData->regExpCache()->lookupOrCreate(patternString, flags);
 }
 
-PassRefPtr<RegExp> RegExp::create(JSGlobalData* globalData, const UString& pattern, const UString& flags)
+void RegExp::compile(JSGlobalData* globalData)
 {
-    return adoptRef(new RegExp(globalData, pattern, flags));
-}
+    ASSERT(m_state == NotCompiled);
+    m_representation = adoptPtr(new RegExpRepresentation);
+    m_state = Compiling;
+    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError);
+    if (m_constructionError) {
+        ASSERT_NOT_REACHED();
+        m_state = ParseError;
+        return;
+    }
 
-#if ENABLE(YARR)
+    globalData->regExpCache()->addToStrongCache(this);
+
+    ASSERT(m_numSubpatterns == pattern.m_numSubpatterns);
 
-void RegExp::compile(JSGlobalData* globalData)
-{
 #if ENABLE(YARR_JIT)
-    Yarr::jitCompileRegex(globalData, m_regExpJITCode, m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline());
+    if (!pattern.m_containsBackreferences && globalData->canUseJIT()) {
+        Yarr::jitCompile(pattern, globalData, m_representation->m_regExpJITCode);
+#if ENABLE(YARR_JIT_DEBUG)
+        if (!m_representation->m_regExpJITCode.isFallBack())
+            m_state = JITCode;
+        else
+            m_state = ByteCode;
 #else
-    UNUSED_PARAM(globalData);
-    m_regExpBytecode.set(Yarr::byteCompileRegex(m_pattern, m_numSubpatterns, m_constructionError, ignoreCase(), multiline()));
+        if (!m_representation->m_regExpJITCode.isFallBack()) {
+            m_state = JITCode;
+            return;
+        }
+#endif
+    }
 #endif
+
+    m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator);
+
+    m_state = ByteCode;
 }
 
-int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
+int RegExp::match(JSGlobalData& globalData, const UString& s, int startOffset, Vector<int, 32>* ovector)
 {
     if (startOffset < 0)
         startOffset = 0;
-    if (ovector)
-        ovector->clear();
 
-    if (static_cast<unsigned>(startOffset) > s.size() || s.isNull()) {
-        m_lastMatchString = UString();
-        m_lastMatchStart = -1;
-        m_lastOVector.shrink(0);
+#if ENABLE(REGEXP_TRACING)
+    m_rtMatchCallCount++;
+#endif
+
+    if (static_cast<unsigned>(startOffset) > s.length() || s.isNull())
         return -1;
-    }
-    
-    // Perform check to see if this match call is the same as the last match invocation
-    // and if it is return the prior result.
-    if ((startOffset == m_lastMatchStart) && (s.rep() == m_lastMatchString.rep())) {
-        if (ovector)
-            *ovector = m_lastOVector;
-        
-        if (m_lastOVector.isEmpty())
-            return -1;
-
-        return m_lastOVector.at(0);
-    }
 
-#if ENABLE(YARR_JIT)
-    if (!!m_regExpJITCode) {
-#else
-    if (m_regExpBytecode) {
-#endif
-        int offsetVectorSize = (m_numSubpatterns + 1) * 3; // FIXME: should be 2 - but adding temporary fallback to pcre.
+    if (m_state != ParseError) {
+        compileIfNecessary(globalData);
+
+        int offsetVectorSize = (m_numSubpatterns + 1) * 2;
         int* offsetVector;
         Vector<int, 32> nonReturnedOvector;
         if (ovector) {
@@ -147,97 +169,122 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
         }
 
         ASSERT(offsetVector);
-        for (int j = 0; j < offsetVectorSize; ++j)
+        // Initialize offsetVector with the return value (index 0) and the 
+        // first subpattern start indicies (even index values) set to -1.
+        // No need to init the subpattern end indicies.
+        for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++)            
             offsetVector[j] = -1;
 
-
+        int result;
 #if ENABLE(YARR_JIT)
-        int result = Yarr::executeRegex(m_regExpJITCode, s.data(), startOffset, s.size(), offsetVector, offsetVectorSize);
-#else
-        int result = Yarr::interpretRegex(m_regExpBytecode.get(), s.data(), startOffset, s.size(), offsetVector);
+        if (m_state == JITCode) {
+            result = Yarr::execute(m_representation->m_regExpJITCode, s.characters(), startOffset, s.length(), offsetVector);
+#if ENABLE(YARR_JIT_DEBUG)
+            matchCompareWithInterpreter(s, startOffset, offsetVector, result);
 #endif
-
-        if (result < 0) {
-#ifndef NDEBUG
-            // TODO: define up a symbol, rather than magic -1
-            if (result != -1)
-                fprintf(stderr, "jsRegExpExecute failed with result %d\n", result);
+        } else
 #endif
-            if (ovector)
-                ovector->clear();
-        }
-        
-        m_lastMatchString = s;
-        m_lastMatchStart = startOffset;
+            result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), offsetVector);
+        ASSERT(result >= -1);
 
-        if (ovector)
-            m_lastOVector = *ovector;
-        else
-            m_lastOVector = nonReturnedOvector;
+#if ENABLE(REGEXP_TRACING)
+        if (result != -1)
+            m_rtMatchFoundCount++;
+#endif
 
         return result;
     }
 
-    m_lastMatchString = UString();
-    m_lastMatchStart = -1;
-    m_lastOVector.shrink(0);
-
     return -1;
 }
 
-#else
-
-void RegExp::compile(JSGlobalData*)
+void RegExp::invalidateCode()
 {
-    m_regExp = 0;
-    JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase;
-    JSRegExpMultilineOption multilineOption = multiline() ? JSRegExpMultiline : JSRegExpSingleLine;
-    m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
+    if (!m_representation || m_state == Compiling)
+        return;
+    m_state = NotCompiled;
+    m_representation.clear();
 }
 
-int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector)
+#if ENABLE(YARR_JIT_DEBUG)
+void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int* offsetVector, int jitResult)
 {
-    if (startOffset < 0)
-        startOffset = 0;
-    if (ovector)
-        ovector->clear();
-
-    if (static_cast<unsigned>(startOffset) > s.size() || s.isNull())
-        return -1;
-
-    if (m_regExp) {
-        // Set up the offset vector for the result.
-        // First 2/3 used for result, the last third used by PCRE.
-        int* offsetVector;
-        int offsetVectorSize;
-        int fixedSizeOffsetVector[3];
-        if (!ovector) {
-            offsetVectorSize = 3;
-            offsetVector = fixedSizeOffsetVector;
+    int offsetVectorSize = (m_numSubpatterns + 1) * 2;
+    Vector<int, 32> interpreterOvector;
+    interpreterOvector.resize(offsetVectorSize);
+    int* interpreterOffsetVector = interpreterOvector.data();
+    int interpreterResult = 0;
+    int differences = 0;
+
+    // Initialize interpreterOffsetVector with the return value (index 0) and the 
+    // first subpattern start indicies (even index values) set to -1.
+    // No need to init the subpattern end indicies.
+    for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++)
+        interpreterOffsetVector[j] = -1;
+
+    interpreterResult = Yarr::interpret(m_representation->m_regExpBytecode.get(), s.characters(), startOffset, s.length(), interpreterOffsetVector);
+
+    if (jitResult != interpreterResult)
+        differences++;
+
+    for (unsigned j = 2, i = 0; i < m_numSubpatterns; j +=2, i++)
+        if ((offsetVector[j] != interpreterOffsetVector[j])
+            || ((offsetVector[j] >= 0) && (offsetVector[j+1] != interpreterOffsetVector[j+1])))
+            differences++;
+
+    if (differences) {
+        fprintf(stderr, "RegExp Discrepency for /%s/\n    string input ", pattern().utf8().data());
+        unsigned segmentLen = s.length() - static_cast<unsigned>(startOffset);
+
+        fprintf(stderr, (segmentLen < 150) ? "\"%s\"\n" : "\"%148s...\"\n", s.utf8().data() + startOffset);
+
+        if (jitResult != interpreterResult) {
+            fprintf(stderr, "    JIT result = %d, blah interpreted result = %d\n", jitResult, interpreterResult);
+            differences--;
         } else {
-            offsetVectorSize = (m_numSubpatterns + 1) * 3;
-            ovector->resize(offsetVectorSize);
-            offsetVector = ovector->data();
+            fprintf(stderr, "    Correct result = %d\n", jitResult);
         }
 
-        int numMatches = jsRegExpExecute(m_regExp, reinterpret_cast<const UChar*>(s.data()), s.size(), startOffset, offsetVector, offsetVectorSize);
-    
-        if (numMatches < 0) {
-#ifndef NDEBUG
-            if (numMatches != JSRegExpErrorNoMatch)
-                fprintf(stderr, "jsRegExpExecute failed with result %d\n", numMatches);
-#endif
-            if (ovector)
-                ovector->clear();
-            return -1;
+        if (differences) {
+            for (unsigned j = 2, i = 0; i < m_numSubpatterns; j +=2, i++) {
+                if (offsetVector[j] != interpreterOffsetVector[j])
+                    fprintf(stderr, "    JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j, offsetVector[j], j, interpreterOffsetVector[j]);
+                if ((offsetVector[j] >= 0) && (offsetVector[j+1] != interpreterOffsetVector[j+1]))
+                    fprintf(stderr, "    JIT offset[%d] = %d, interpreted offset[%d] = %d\n", j+1, offsetVector[j+1], j+1, interpreterOffsetVector[j+1]);
+            }
         }
-
-        return offsetVector[0];
     }
-
-    return -1;
 }
+#endif
+
+#if ENABLE(REGEXP_TRACING)
+    void RegExp::printTraceData()
+    {
+        char formattedPattern[41];
+        char rawPattern[41];
+
+        strncpy(rawPattern, pattern().utf8().data(), 40);
+        rawPattern[40]= '\0';
 
+        int pattLen = strlen(rawPattern);
+
+        snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern);
+
+#if ENABLE(YARR_JIT)
+        Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode;
+
+        const size_t jitAddrSize = 20;
+        char jitAddr[jitAddrSize];
+        if (m_state == JITCode)
+            snprintf(jitAddr, jitAddrSize, "fallback");
+        else
+            snprintf(jitAddr, jitAddrSize, "0x%014lx", reinterpret_cast<unsigned long int>(codeBlock.getAddr()));
+#else
+        const char* jitAddr = "JIT Off";
 #endif
 
+        printf("%-40.40s %16.16s %10d %10d\n", formattedPattern, jitAddr, m_rtMatchCallCount, m_rtMatchFoundCount);
+    }
+#endif
+    
 } // namespace JSC
index 04022bc9563850f2a1bb2499e066993523a2c12a..79f4694ee134bfd60ef396a31bdeeb44bc94e3e2 100644 (file)
 
 #include "UString.h"
 #include "ExecutableAllocator.h"
+#include "Structure.h"
+#include "RegExpKey.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
-#include "yarr/RegexJIT.h"
-#include "yarr/RegexInterpreter.h"
-
-struct JSRegExp;
 
 namespace JSC {
 
+    struct RegExpRepresentation;
     class JSGlobalData;
 
-    class RegExp : public RefCounted<RegExp> {
+    RegExpFlags regExpFlags(const UString&);
+
+    class RegExp : public JSCell {
     public:
-        static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern);
-        static PassRefPtr<RegExp> create(JSGlobalData* globalData, const UString& pattern, const UString& flags);
-#if !ENABLE(YARR)
+        static RegExp* create(JSGlobalData*, const UString& pattern, RegExpFlags);
         ~RegExp();
-#endif
 
-        bool global() const { return m_flagBits & Global; }
-        bool ignoreCase() const { return m_flagBits & IgnoreCase; }
-        bool multiline() const { return m_flagBits & Multiline; }
+        bool global() const { return m_flags & FlagGlobal; }
+        bool ignoreCase() const { return m_flags & FlagIgnoreCase; }
+        bool multiline() const { return m_flags & FlagMultiline; }
 
-        const UString& pattern() const { return m_pattern; }
+        const UString& pattern() const { return m_patternString; }
 
-        bool isValid() const { return !m_constructionError; }
+        bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; }
         const char* errorMessage() const { return m_constructionError; }
 
-        int match(const UString&, int startOffset, Vector<int, 32>* ovector = 0);
+        int match(JSGlobalData&, const UString&, int startOffset, Vector<int, 32>* ovector = 0);
         unsigned numSubpatterns() const { return m_numSubpatterns; }
 
+        bool hasCode()
+        {
+            return m_representation;
+        }
+
+        void invalidateCode();
+        
+#if ENABLE(REGEXP_TRACING)
+        void printTraceData();
+#endif
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(LeafType, 0), 0, &s_info);
+        }
+        
+        static JS_EXPORTDATA const ClassInfo s_info;
+
+        RegExpKey key() { return RegExpKey(m_flags, m_patternString); }
+
     private:
-        RegExp(JSGlobalData* globalData, const UString& pattern);
-        RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags);
+        friend class RegExpCache;
+        RegExp(JSGlobalData* globalData, const UString& pattern, RegExpFlags);
 
-        void compile(JSGlobalData*);
+        enum RegExpState {
+            ParseError,
+            JITCode,
+            ByteCode,
+            NotCompiled,
+            Compiling
+        } m_state;
 
-        enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 };
+        void compile(JSGlobalData*);
+        void compileIfNecessary(JSGlobalData& globalData)
+        {
+            if (m_representation)
+                return;
+            compile(&globalData);
+        }
+
+#if ENABLE(YARR_JIT_DEBUG)
+        void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult);
+#endif
 
-        UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
-        int m_flagBits;
+        UString m_patternString;
+        RegExpFlags m_flags;
         const char* m_constructionError;
         unsigned m_numSubpatterns;
-        UString m_lastMatchString;
-        int m_lastMatchStart;
-        Vector<int, 32> m_lastOVector;
-
-#if ENABLE(YARR_JIT)
-        Yarr::RegexCodeBlock m_regExpJITCode;
-#elif ENABLE(YARR)
-        OwnPtr<Yarr::BytecodePattern> m_regExpBytecode;
-#else
-        JSRegExp* m_regExp;
+#if ENABLE(REGEXP_TRACING)
+        unsigned m_rtMatchCallCount;
+        unsigned m_rtMatchFoundCount;
 #endif
+
+        OwnPtr<RegExpRepresentation> m_representation;
     };
 
 } // namespace JSC
index 5e9d610c74bea4c9b93c79127e41a5c8602b0b5c..2dce19797b8e185f130455a4edaf211fa9f35a70 100644 (file)
 #include "config.h"
 
 #include "RegExpCache.h"
+#include "RegExpObject.h"
 
 namespace JSC {
 
-PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags)
+RegExp* RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags flags)
 {
-    if (isCacheable(patternString)) {
-        pair<HashMap<RegExpKey, RefPtr<RegExp> >::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0);
-        if (!result.second)
-            return result.first->second;
-    }
-    return create(patternString, flags);
+    RegExpKey key(flags, patternString);
+    RegExpCacheMap::iterator result = m_weakCache.find(key);
+    if (result != m_weakCache.end())
+        return result->second.get();
+    RegExp* regExp = new (m_globalData) RegExp(m_globalData, patternString, flags);
+#if ENABLE(REGEXP_TRACING)
+    m_globalData->addRegExpToTrace(regExp);
+#endif
+    // We need to do a second lookup to add the RegExp as
+    // allocating it may have caused a gc cycle, which in
+    // turn may have removed items from the cache.
+    m_weakCache.add(key, Weak<RegExp>(*m_globalData, regExp, this));
+    return regExp;
 }
 
-PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UString& flags) 
+RegExpCache::RegExpCache(JSGlobalData* globalData)
+    : m_nextEntryInStrongCache(0)
+    , m_globalData(globalData)
 {
-    RefPtr<RegExp> regExp;
-
-    if (!flags.isNull())
-        regExp = RegExp::create(m_globalData, patternString, flags);
-    else
-        regExp = RegExp::create(m_globalData, patternString);
-
-    if (patternString.size() >= maxCacheablePatternLength)
-        return regExp;
+}
 
-    ++m_nextKeyToEvict;
-    if (m_nextKeyToEvict == maxCacheableEntries) {
-        m_nextKeyToEvict = 0;
-        m_isFull = true;
-    }
-    if (m_isFull)
-        m_cacheMap.remove(RegExpKey(patternKeyArray[m_nextKeyToEvict].flagsValue, patternKeyArray[m_nextKeyToEvict].pattern));
+void RegExpCache::finalize(Handle<Unknown> handle, void*)
+{
+    RegExp* regExp = static_cast<RegExp*>(handle.get().asCell());
+    m_weakCache.remove(regExp->key());
+    regExp->invalidateCode();
+}
 
-    RegExpKey key = RegExpKey(flags, patternString);
-    m_cacheMap.set(key, regExp);
-    patternKeyArray[m_nextKeyToEvict].flagsValue = key.flagsValue;
-    patternKeyArray[m_nextKeyToEvict].pattern = patternString.rep();
-    return regExp;
+void RegExpCache::addToStrongCache(RegExp* regExp)
+{
+    UString pattern = regExp->pattern();
+    if (pattern.length() > maxStrongCacheablePatternLength)
+        return;
+    m_strongCache[m_nextEntryInStrongCache].set(*m_globalData, regExp);
+    m_nextEntryInStrongCache++;
+    if (m_nextEntryInStrongCache == maxStrongCacheableEntries)
+        m_nextEntryInStrongCache = 0;
 }
 
-RegExpCache::RegExpCache(JSGlobalData* globalData)
-    : m_globalData(globalData)
-    , m_nextKeyToEvict(-1)
-    , m_isFull(false)
+void RegExpCache::invalidateCode()
 {
+    for (int i = 0; i < maxStrongCacheableEntries; i++)
+        m_strongCache[i].clear();
+    m_nextEntryInStrongCache = 0;
+    RegExpCacheMap::iterator end = m_weakCache.end();
+    for (RegExpCacheMap::iterator ptr = m_weakCache.begin(); ptr != end; ++ptr)
+        ptr->second->invalidateCode();
 }
 
 }
index 998d80bc0c9a3ff0cc38779a501f8cb18a5e9781..4f3ea1536a4eae10d9dcbeb794ecd7510c2a61f6 100644 (file)
 
 #include "RegExp.h"
 #include "RegExpKey.h"
+#include "Strong.h"
 #include "UString.h"
+#include "Weak.h"
+#include <wtf/FixedArray.h>
+#include <wtf/HashMap.h>
 
 #ifndef RegExpCache_h
 #define RegExpCache_h
 
 namespace JSC {
 
-class RegExpCache {
+class RegExpCache : private WeakHandleOwner {
+friend class RegExp;
+typedef HashMap<RegExpKey, Weak<RegExp> > RegExpCacheMap;
+
 public:
-    PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags);
-    PassRefPtr<RegExp> create(const UString& patternString, const UString& flags);
     RegExpCache(JSGlobalData* globalData);
-    
-    static bool isCacheable(const UString& patternString) { return patternString.size() < maxCacheablePatternLength; }
+    void invalidateCode();
 
 private:
-    static const unsigned maxCacheablePatternLength = 256;
-    static const int maxCacheableEntries = 32;
+    
+    static const unsigned maxStrongCacheablePatternLength = 256;
+
+    static const int maxStrongCacheableEntries = 32;
+
+    virtual void finalize(Handle<Unknown>, void* context);
 
-    typedef HashMap<RegExpKey, RefPtr<RegExp> > RegExpCacheMap;
-    RegExpKey patternKeyArray[maxCacheableEntries];
-    RegExpCacheMap m_cacheMap;
+    RegExp* lookupOrCreate(const UString& patternString, RegExpFlags);
+    void addToStrongCache(RegExp*);
+    RegExpCacheMap m_weakCache; // Holds all regular expressions currently live.
+    int m_nextEntryInStrongCache;
+    WTF::FixedArray<Strong<RegExp>, maxStrongCacheableEntries> m_strongCache; // Holds a select few regular expressions that have compiled and executed
     JSGlobalData* m_globalData;
-    int m_nextKeyToEvict;
-    bool m_isFull;
 };
 
 } // namespace JSC
index 5332a874f74438f1ef162e8aaac794bfcb5b3aa2..3e499bacbec0d22ec9eb684afed89f7cbab0f581 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "ArrayPrototype.h"
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "RegExpPrototype.h"
 #include "RegExp.h"
 #include "RegExpCache.h"
+#include "UStringConcatenate.h"
+#include <wtf/PassOwnPtr.h>
+
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
@@ -64,7 +69,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
 
-const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable };
+const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable };
 
 /* Source for RegExpConstructor.lut.h
 @begin regExpConstructorTable
@@ -92,19 +97,21 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info,
 @end
 */
 
-RegExpConstructor::RegExpConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp"))
-    , d(new RegExpConstructorPrivate)
+RegExpConstructor::RegExpConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, "RegExp"))
+    , d(adoptPtr(new RegExpConstructorPrivate))
 {
+    ASSERT(inherits(&s_info));
+
     // ECMA 15.10.5.1 RegExp.prototype
-    putDirectWithoutTransition(exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
 }
 
 RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
-    : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1)
+    : JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1, CreateInitialized)
 {
     RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
     d->input = data->lastInput;
@@ -139,7 +146,7 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
     }
 
     PutPropertySlot slot;
-    JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector()[0]), slot);
+    JSArray::put(exec, exec->propertyNames().index, jsNumber(d->lastOvector()[0]), slot);
     JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->input), slot);
 
     delete d;
@@ -183,7 +190,7 @@ JSValue RegExpConstructor::getLeftContext(ExecState* exec) const
 JSValue RegExpConstructor::getRightContext(ExecState* exec) const
 {
     if (!d->lastOvector().isEmpty())
-        return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.size() - d->lastOvector()[1]);
+        return jsSubstring(exec, d->lastInput, d->lastOvector()[1], d->lastInput.length() - d->lastOvector()[1]);
     return jsEmptyString(exec);
 }
     
@@ -286,31 +293,42 @@ void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValu
 {
     asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
 }
-  
+
 // ECMA 15.10.4
-JSObject* constructRegExp(ExecState* exec, const ArgList& args)
+JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
 
-    if (arg0.inherits(&RegExpObject::info)) {
+    if (arg0.inherits(&RegExpObject::s_info)) {
         if (!arg1.isUndefined())
-            return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+            return throwError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
         return asObject(arg0);
     }
 
     UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
-    UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
+    if (exec->hadException())
+        return 0;
+
+    RegExpFlags flags = NoFlags;
+    if (!arg1.isUndefined()) {
+        flags = regExpFlags(arg1.toString(exec));
+        if (exec->hadException())
+            return 0;
+        if (flags == InvalidFlags)
+            return throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
+    }
 
-    RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
+    RegExp* regExp = RegExp::create(&exec->globalData(), pattern, flags);
     if (!regExp->isValid())
-        return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage()));
-    return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
+        return throwError(exec, createSyntaxError(exec, regExp->errorMessage()));
+    return new (exec) RegExpObject(exec->lexicalGlobalObject(), globalObject->regExpStructure(), regExp);
 }
 
-static JSObject* constructWithRegExpConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
 {
-    return constructRegExp(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
@@ -320,9 +338,10 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.10.3
-static JSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
 {
-    return constructRegExp(exec, args);
+    ArgList args(exec);
+    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
 }
 
 CallType RegExpConstructor::getCallData(CallData& callData)
index 8f4be71687a0f3177738060bcdbb9bcea02fca65..1d02e6ff7cfc4155457931a11e925d164edb580b 100644 (file)
@@ -31,7 +31,9 @@ namespace JSC {
     class RegExpPrototype;
     struct RegExpConstructorPrivate;
 
-    struct RegExpConstructorPrivate : FastAllocBase {
+    struct RegExpConstructorPrivate {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         // Global search cache / settings
         RegExpConstructorPrivate()
             : lastNumSubPatterns(0)
@@ -55,20 +57,20 @@ namespace JSC {
 
     class RegExpConstructor : public InternalFunction {
     public:
-        RegExpConstructor(ExecState*, NonNullPassRefPtr<Structure>, RegExpPrototype*);
+        RegExpConstructor(ExecState*, JSGlobalObject*, Structure*, RegExpPrototype*);
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        static const ClassInfo info;
+        static const ClassInfo s_info;
 
-        void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
+        void performMatch(JSGlobalData&, RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
         JSObject* arrayOfMatches(ExecState*) const;
 
         void setInput(const UString&);
@@ -89,18 +91,16 @@ namespace JSC {
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-
         OwnPtr<RegExpConstructorPrivate> d;
     };
 
     RegExpConstructor* asRegExpConstructor(JSValue);
 
-    JSObject* constructRegExp(ExecState*, const ArgList&);
+    JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&);
 
     inline RegExpConstructor* asRegExpConstructor(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
+        ASSERT(asObject(value)->inherits(&RegExpConstructor::s_info));
         return static_cast<RegExpConstructor*>(asObject(value));
     }
 
@@ -109,9 +109,9 @@ namespace JSC {
       expression matching through the performMatch function. We use cached results to calculate, 
       e.g., RegExp.lastMatch and RegExp.leftParen.
     */
-    inline void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
+    ALWAYS_INLINE void RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
     {
-        position = r->match(s, startOffset, &d->tempOvector());
+        position = r->match(globalData, s, startOffset, &d->tempOvector());
 
         if (ovector)
             *ovector = d->tempOvector().data();
index e5ab43892d9b41a6adced5fe9429c973192b8bf5..b4847f97114d0039d50e2e25f529209e622edf26 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "UString.h"
-
 #ifndef RegExpKey_h
 #define RegExpKey_h
 
+#include "UString.h"
+#include <wtf/text/StringHash.h>
+
 namespace JSC {
 
+enum RegExpFlags {
+    NoFlags = 0,
+    FlagGlobal = 1,
+    FlagIgnoreCase = 2,
+    FlagMultiline = 4,
+    InvalidFlags = 8,
+    DeletedValueFlags = -1
+};
+
 struct RegExpKey {
-    int flagsValue;
-    RefPtr<UString::Rep> pattern;
+    RegExpFlags flagsValue;
+    RefPtr<StringImpl> pattern;
 
     RegExpKey()
-        : flagsValue(0)
+        : flagsValue(NoFlags)
     {
     }
 
-    RegExpKey(int flags)
+    RegExpKey(RegExpFlags flags)
         : flagsValue(flags)
     {
     }
 
-    RegExpKey(int flags, const UString& pattern)
+    RegExpKey(RegExpFlags flags, const UString& pattern)
         : flagsValue(flags)
-        , pattern(pattern.rep())
+        , pattern(pattern.impl())
     {
     }
 
-    RegExpKey(int flags, const PassRefPtr<UString::Rep> pattern)
+    RegExpKey(RegExpFlags flags, const PassRefPtr<StringImpl> pattern)
         : flagsValue(flags)
         , pattern(pattern)
     {
     }
 
-    RegExpKey(const UString& flags, const UString& pattern)
-        : pattern(pattern.rep())
-    {
-        flagsValue = getFlagsValue(flags);
-    }
-
-    int getFlagsValue(const UString flags) 
+    RegExpKey(RegExpFlags flags, const RefPtr<StringImpl>& pattern)
+        : flagsValue(flags)
+        , pattern(pattern)
     {
-        flagsValue = 0;
-        if (flags.find('g') != UString::NotFound)
-            flagsValue += 4;
-        if (flags.find('i') != UString::NotFound)
-            flagsValue += 2;
-        if (flags.find('m') != UString::NotFound)
-            flagsValue += 1;
-        return flagsValue;
     }
 };
-} // namespace JSC
-
-namespace WTF {
-template<typename T> struct DefaultHash;
-template<typename T> struct RegExpHash;
 
-inline bool operator==(const JSC::RegExpKey& a, const JSC::RegExpKey& b) 
+inline bool operator==(const RegExpKey& a, const RegExpKey& b) 
 {
     if (a.flagsValue != b.flagsValue)
         return false;
@@ -93,6 +86,12 @@ inline bool operator==(const JSC::RegExpKey& a, const JSC::RegExpKey& b)
     return equal(a.pattern.get(), b.pattern.get());
 }
 
+} // namespace JSC
+
+namespace WTF {
+template<typename T> struct DefaultHash;
+template<typename T> struct RegExpHash;
+
 template<> struct RegExpHash<JSC::RegExpKey> {
     static unsigned hash(const JSC::RegExpKey& key) { return key.pattern->hash(); }
     static bool equal(const JSC::RegExpKey& a, const JSC::RegExpKey& b) { return a == b; }
@@ -104,8 +103,8 @@ template<> struct DefaultHash<JSC::RegExpKey> {
 };
 
 template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> {
-    static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = -1; }
-    static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == -1; }
+    static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; }
+    static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; }
 };
 } // namespace WTF
 
index bc74924d0dba433523627b8b463404b75c049441..fc3b2058c48f80de1ad30818cf99ff45484f1dad 100644 (file)
 #include "RegExpObject.h"
 
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "Lookup.h"
 #include "RegExpConstructor.h"
 #include "RegExpPrototype.h"
+#include "UStringConcatenate.h"
+#include <wtf/PassOwnPtr.h>
+
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
@@ -46,7 +51,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
 
-const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
+const ClassInfo RegExpObject::s_info = { "RegExp", &JSObjectWithGlobalObject::s_info, 0, ExecState::regExpTable };
 
 /* Source for RegExpObject.lut.h
 @begin regExpTable
@@ -58,16 +63,29 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
 @end
 */
 
-RegExpObject::RegExpObject(NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp)
-    : JSObject(structure)
-    , d(new RegExpObjectData(regExp, 0))
+RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+    : JSObjectWithGlobalObject(globalObject, structure)
+    , d(adoptPtr(new RegExpObjectData(globalObject->globalData(), this, regExp)))
 {
+    ASSERT(inherits(&s_info));
 }
 
 RegExpObject::~RegExpObject()
 {
 }
 
+void RegExpObject::visitChildren(SlotVisitor& visitor)
+{
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    Base::visitChildren(visitor);
+    if (d->regExp)
+        visitor.append(&d->regExp);
+    if (UNLIKELY(!d->lastIndex.get().isInt32()))
+        visitor.append(&d->lastIndex);
+}
+
 bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
 {
     return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
@@ -98,9 +116,9 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
     return jsString(exec, asRegExpObject(slotBase)->regExp()->pattern());
 }
 
-JSValue regExpObjectLastIndex(ExecState* exec, JSValue slotBase, const Identifier&)
+JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
 {
-    return jsNumber(exec, asRegExpObject(slotBase)->lastIndex());
+    return asRegExpObject(slotBase)->getLastIndex();
 }
 
 void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
@@ -110,64 +128,60 @@ void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue
 
 void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
 {
-    asRegExpObject(baseObject)->setLastIndex(value.toInteger(exec));
+    asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
 }
 
-JSValue RegExpObject::test(ExecState* exec, const ArgList& args)
+JSValue RegExpObject::test(ExecState* exec)
 {
-    return jsBoolean(match(exec, args));
+    return jsBoolean(match(exec));
 }
 
-JSValue RegExpObject::exec(ExecState* exec, const ArgList& args)
+JSValue RegExpObject::exec(ExecState* exec)
 {
-    if (match(exec, args))
+    if (match(exec))
         return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec);
     return jsNull();
 }
 
-static JSValue JSC_HOST_CALL callRegExpObject(ExecState* exec, JSObject* function, JSValue, const ArgList& args)
-{
-    return asRegExpObject(function)->exec(exec, args);
-}
-
-CallType RegExpObject::getCallData(CallData& callData)
-{
-    callData.native.function = callRegExpObject;
-    return CallTypeHost;
-}
-
 // Shared implementation used by test and exec.
-bool RegExpObject::match(ExecState* exec, const ArgList& args)
+bool RegExpObject::match(ExecState* exec)
 {
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
-
-    UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec);
-    if (input.isNull()) {
-        throwError(exec, GeneralError, makeString("No input to ", toString(exec), "."));
-        return false;
-    }
-
+    UString input = exec->argument(0).toString(exec);
+    JSGlobalData* globalData = &exec->globalData();
     if (!regExp()->global()) {
         int position;
         int length;
-        regExpConstructor->performMatch(d->regExp.get(), input, 0, position, length);
+        regExpConstructor->performMatch(*globalData, d->regExp.get(), input, 0, position, length);
         return position >= 0;
     }
 
-    if (d->lastIndex < 0 || d->lastIndex > input.size()) {
-        d->lastIndex = 0;
-        return false;
+    JSValue jsLastIndex = getLastIndex();
+    unsigned lastIndex;
+    if (LIKELY(jsLastIndex.isUInt32())) {
+        lastIndex = jsLastIndex.asUInt32();
+        if (lastIndex > input.length()) {
+            setLastIndex(0);
+            return false;
+        }
+    } else {
+        double doubleLastIndex = jsLastIndex.toInteger(exec);
+        if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
+            setLastIndex(0);
+            return false;
+        }
+        lastIndex = static_cast<unsigned>(doubleLastIndex);
     }
 
     int position;
     int length = 0;
-    regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length);
+    regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length);
     if (position < 0) {
-        d->lastIndex = 0;
+        setLastIndex(0);
         return false;
     }
 
-    d->lastIndex = position + length;
+    setLastIndex(position + length);
     return true;
 }
 
index 4ad11ef7a5907264b281b850fef1a62e3ac6ee12..6fc6cb9a72f298527c3a654ef55b8248e7eb0740 100644 (file)
 #ifndef RegExpObject_h
 #define RegExpObject_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 #include "RegExp.h"
 
 namespace JSC {
-
-    class RegExpObject : public JSObject {
+    
+    class RegExpObject : public JSObjectWithGlobalObject {
     public:
-        RegExpObject(NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>);
+        typedef JSObjectWithGlobalObject Base;
+
+        RegExpObject(JSGlobalObject*, Structure*, RegExp*);
         virtual ~RegExpObject();
 
-        void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; }
+        void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); }
         RegExp* regExp() const { return d->regExp.get(); }
 
-        void setLastIndex(double lastIndex) { d->lastIndex = lastIndex; }
-        double lastIndex() const { return d->lastIndex; }
+        void setLastIndex(size_t lastIndex)
+        {
+            d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
+        }
+        void setLastIndex(JSGlobalData& globalData, JSValue lastIndex)
+        {
+            d->lastIndex.set(globalData, this, lastIndex);
+        }
+        JSValue getLastIndex() const
+        {
+            return d->lastIndex.get();
+        }
 
-        JSValue test(ExecState*, const ArgList&);
-        JSValue exec(ExecState*, const ArgList&);
+        JSValue test(ExecState*);
+        JSValue exec(ExecState*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags;
 
     private:
-        bool match(ExecState*, const ArgList&);
+        virtual void visitChildren(SlotVisitor&);
 
-        virtual CallType getCallData(CallData&);
+        bool match(ExecState*);
 
-        struct RegExpObjectData : FastAllocBase {
-            RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex)
-                : regExp(regExp)
-                , lastIndex(lastIndex)
+        struct RegExpObjectData {
+            WTF_MAKE_FAST_ALLOCATED;
+        public:
+            RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp)
+                : regExp(globalData, owner, regExp)
             {
+                lastIndex.setWithoutWriteBarrier(jsNumber(0));
             }
 
-            RefPtr<RegExp> regExp;
-            double lastIndex;
+            WriteBarrier<RegExp> regExp;
+            WriteBarrier<Unknown> lastIndex;
         };
-
+#if COMPILER(MSVC)
+        friend void WTF::deleteOwnedPtr<RegExpObjectData>(RegExpObjectData*);
+#endif
         OwnPtr<RegExpObjectData> d;
     };
 
@@ -78,7 +93,7 @@ namespace JSC {
 
     inline RegExpObject* asRegExpObject(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&RegExpObject::info));
+        ASSERT(asObject(value)->inherits(&RegExpObject::s_info));
         return static_cast<RegExpObject*>(asObject(value));
     }
 
index 7c34b21a4d8811cafa3f744e2286fc63c53ae5e0..26f62330a0d5ec225e1538769ceb7a25e38870c1 100644 (file)
 #include "JSStringBuilder.h"
 #include "JSValue.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
 #include "RegExpObject.h"
 #include "RegExp.h"
 #include "RegExpCache.h"
+#include "StringRecursionChecker.h"
+#include "UStringConcatenate.h"
 
 namespace JSC {
 
-ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype);
+static EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*);
+static EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*);
+static EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*);
+static EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*);
+
+}
 
-static JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+#include "RegExpPrototype.lut.h"
+
+namespace JSC {
 
-// ECMA 15.10.5
+const ClassInfo RegExpPrototype::s_info = { "RegExp", &RegExpObject::s_info, 0, ExecState::regExpPrototypeTable };
 
-const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
+/* Source for RegExpPrototype.lut.h
+@begin regExpPrototypeTable
+  compile   regExpProtoFuncCompile      DontEnum|Function 2
+  exec      regExpProtoFuncExec         DontEnum|Function 1
+  test      regExpProtoFuncTest         DontEnum|Function 1
+  toString  regExpProtoFuncToString     DontEnum|Function 0
+@end
+*/
 
-RegExpPrototype::RegExpPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure)
-    : JSObject(structure)
+ASSERT_CLASS_FITS_IN_CELL(RegExpPrototype);
+
+RegExpPrototype::RegExpPrototype(ExecState*, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
+    : RegExpObject(globalObject, structure, regExp)
 {
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
+}
+
+bool RegExpPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
+{
+    return getStaticFunctionSlot<RegExpObject>(exec, ExecState::regExpPrototypeTable(exec), this, propertyName, slot);
+}
+
+bool RegExpPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<RegExpObject>(exec, ExecState::regExpPrototypeTable(exec), this, propertyName, descriptor);
 }
 
 // ------------------------------ Functions ---------------------------
-    
-JSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec)
 {
-    if (!thisValue.inherits(&RegExpObject::info))
-        return throwError(exec, TypeError);
-    return asRegExpObject(thisValue)->test(exec, args);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&RegExpObject::s_info))
+        return throwVMTypeError(exec);
+    return JSValue::encode(asRegExpObject(thisValue)->test(exec));
 }
 
-JSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
 {
-    if (!thisValue.inherits(&RegExpObject::info))
-        return throwError(exec, TypeError);
-    return asRegExpObject(thisValue)->exec(exec, args);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&RegExpObject::s_info))
+        return throwVMTypeError(exec);
+    return JSValue::encode(asRegExpObject(thisValue)->exec(exec));
 }
 
-JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
 {
-    if (!thisValue.inherits(&RegExpObject::info))
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&RegExpObject::s_info))
+        return throwVMTypeError(exec);
 
-    RefPtr<RegExp> regExp;
-    JSValue arg0 = args.at(0);
-    JSValue arg1 = args.at(1);
+    RegExp* regExp;
+    JSValue arg0 = exec->argument(0);
+    JSValue arg1 = exec->argument(1);
     
-    if (arg0.inherits(&RegExpObject::info)) {
+    if (arg0.inherits(&RegExpObject::s_info)) {
         if (!arg1.isUndefined())
-            return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
+            return throwVMError(exec, createTypeError(exec, "Cannot supply flags when constructing one RegExp from another."));
         regExp = asRegExpObject(arg0)->regExp();
     } else {
-        UString pattern = args.isEmpty() ? UString("") : arg0.toString(exec);
-        UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
-        regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
+        UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
+        RegExpFlags flags = NoFlags;
+        if (!arg1.isUndefined()) {
+            flags = regExpFlags(arg1.toString(exec));
+            if (exec->hadException())
+                return JSValue::encode(jsUndefined());
+            if (flags == InvalidFlags)
+                return throwVMError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor."));
+        }
+        regExp = RegExp::create(&exec->globalData(), pattern, flags);
     }
 
     if (!regExp->isValid())
-        return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage()));
+        return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage()));
 
-    asRegExpObject(thisValue)->setRegExp(regExp.release());
+    asRegExpObject(thisValue)->setRegExp(exec->globalData(), regExp);
     asRegExpObject(thisValue)->setLastIndex(0);
-    return jsUndefined();
+    return JSValue::encode(jsUndefined());
 }
 
-JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
 {
-    if (!thisValue.inherits(&RegExpObject::info)) {
-        if (thisValue.inherits(&RegExpPrototype::info))
-            return jsNontrivialString(exec, "//");
-        return throwError(exec, TypeError);
+    JSValue thisValue = exec->hostThisValue();
+    if (!thisValue.inherits(&RegExpObject::s_info)) {
+        if (thisValue.inherits(&RegExpPrototype::s_info))
+            return JSValue::encode(jsNontrivialString(exec, "//"));
+        return throwVMTypeError(exec);
     }
 
+    RegExpObject* thisObject = asRegExpObject(thisValue);
+
+    StringRecursionChecker checker(exec, thisObject);
+    if (EncodedJSValue earlyReturnValue = checker.earlyReturnValue())
+        return earlyReturnValue;
+
     char postfix[5] = { '/', 0, 0, 0, 0 };
     int index = 1;
-    if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec))
+    if (thisObject->get(exec, exec->propertyNames().global).toBoolean(exec))
         postfix[index++] = 'g';
-    if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
+    if (thisObject->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec))
         postfix[index++] = 'i';
-    if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec))
+    if (thisObject->get(exec, exec->propertyNames().multiline).toBoolean(exec))
         postfix[index] = 'm';
-    UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec);
+    UString source = thisObject->get(exec, exec->propertyNames().source).toString(exec);
     // If source is empty, use "/(?:)/" to avoid colliding with comment syntax
-    return jsMakeNontrivialString(exec, "/", source.size() ? source : UString("(?:)"), postfix);
+    return JSValue::encode(jsMakeNontrivialString(exec, "/", source.length() ? source : UString("(?:)"), postfix));
 }
 
 } // namespace JSC
index d3979bdd216ed7b8e70f8ab6fc675fc99d3cddb9..83e75be0252912d4d349cffab61492cd8abf5f5a 100644 (file)
 #ifndef RegExpPrototype_h
 #define RegExpPrototype_h
 
+#include "RegExpObject.h"
 #include "JSObject.h"
 
 namespace JSC {
 
-    class RegExpPrototype : public JSObject {
+    class RegExpPrototype : public RegExpObject {
     public:
-        RegExpPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure);
+        RegExpPrototype(ExecState*, JSGlobalObject*, Structure*, RegExp*);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | RegExpObject::StructureFlags;
+
+    private:
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
index 25b9848177ed0c3df7354f76573b59696981caf0..09c24a9dd38e75b923de3a5484b0c958a2eb491a 100644 (file)
@@ -40,7 +40,7 @@ void RopeImpl::derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue)
             else
                 nextRope->deref();
         } else
-            static_cast<UStringImpl*>(fiber)->deref();
+            static_cast<StringImpl*>(fiber)->deref();
     }
 }
 
index ac2b5026dab139106df60ca1cd28ee2a0a9bb809..dfacbf5d32135e05533f00301b8fbfbb2da7919e 100644 (file)
 #ifndef RopeImpl_h
 #define RopeImpl_h
 
-#include "UStringImpl.h"
+#include <wtf/text/StringImpl.h>
 
 namespace JSC {
 
 class RopeImpl : public StringImplBase {
 public:
     // A RopeImpl is composed from a set of smaller strings called Fibers.
-    // Each Fiber in a rope is either UStringImpl or another RopeImpl.
+    // Each Fiber in a rope is either StringImpl or another RopeImpl.
     typedef StringImplBase* Fiber;
 
     // Creates a RopeImpl comprising of 'fiberCount' Fibers.
@@ -56,7 +56,7 @@ public:
         if (isRope(fiber))
             static_cast<RopeImpl*>(fiber)->deref();
         else
-            static_cast<UStringImpl*>(fiber)->deref();
+            static_cast<StringImpl*>(fiber)->deref();
     }
 
     void initializeFiber(unsigned &index, Fiber fiber)
index 981794bee91c7faa2e1dad1558834ea539edf717..df4da41c021394270654c051c6f7c8e52885ec65 100644 (file)
@@ -31,11 +31,11 @@ namespace JSC {
 
 #ifndef NDEBUG
 
-void ScopeChainNode::print() const
+void ScopeChainNode::print()
 {
     ScopeChainIterator scopeEnd = end();
     for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
-        JSObject* o = *scopeIter;
+        JSObject* o = scopeIter->get();
         PropertyNameArray propertyNames(globalObject->globalExec());
         o->getPropertyNames(globalObject->globalExec(), propertyNames);
         PropertyNameArray::const_iterator propEnd = propertyNames.end();
@@ -43,7 +43,7 @@ void ScopeChainNode::print() const
         fprintf(stderr, "----- [scope %p] -----\n", o);
         for (PropertyNameArray::const_iterator propIter = propertyNames.begin(); propIter != propEnd; propIter++) {
             Identifier name = *propIter;
-            fprintf(stderr, "%s, ", name.ascii());
+            fprintf(stderr, "%s, ", name.ustring().utf8().data());
         }
         fprintf(stderr, "\n");
     }
@@ -51,12 +51,14 @@ void ScopeChainNode::print() const
 
 #endif
 
-int ScopeChain::localDepth() const
+const ClassInfo ScopeChainNode::s_info = { "ScopeChainNode", 0, 0, 0 };
+
+int ScopeChainNode::localDepth()
 {
     int scopeDepth = 0;
     ScopeChainIterator iter = this->begin();
     ScopeChainIterator end = this->end();
-    while (!(*iter)->inherits(&JSActivation::info)) {
+    while (!(*iter)->inherits(&JSActivation::s_info)) {
         ++iter;
         if (iter == end)
             break;
@@ -65,4 +67,16 @@ int ScopeChain::localDepth() const
     return scopeDepth;
 }
 
+void ScopeChainNode::visitChildren(SlotVisitor& visitor)
+{
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    if (next)
+        visitor.append(&next);
+    visitor.append(&object);
+    visitor.append(&globalObject);
+    visitor.append(&globalThis);
+}
+
 } // namespace JSC
index 0b15b67b39a0381b2f27a53422bd2fc75461bcfd..7fbb888e3b4ae62114f9b9271e1e2cf2071167e3 100644 (file)
@@ -21,7 +21,9 @@
 #ifndef ScopeChain_h
 #define ScopeChain_h
 
-#include "FastAllocBase.h"
+#include "JSCell.h"
+#include "Structure.h"
+#include <wtf/FastAllocBase.h>
 
 namespace JSC {
 
@@ -30,110 +32,71 @@ namespace JSC {
     class JSObject;
     class MarkStack;
     class ScopeChainIterator;
+    typedef MarkStack SlotVisitor;
     
-    class ScopeChainNode : public FastAllocBase {
+    class ScopeChainNode : public JSCell {
     public:
         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
-            : next(next)
-            , object(object)
+            : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
             , globalData(globalData)
-            , globalObject(globalObject)
-            , globalThis(globalThis)
-            , refCount(1)
+            , next(*globalData, this, next, WriteBarrier<ScopeChainNode>::MayBeNull)
+            , object(*globalData, this, object)
+            , globalObject(*globalData, this, globalObject)
+            , globalThis(*globalData, this, globalThis)
         {
             ASSERT(globalData);
             ASSERT(globalObject);
         }
-#ifndef NDEBUG
-        // Due to the number of subtle and timing dependent bugs that have occurred due
-        // to deleted but still "valid" ScopeChainNodes we now deliberately clobber the
-        // contents in debug builds.
-        ~ScopeChainNode()
-        {
-            next = 0;
-            object = 0;
-            globalData = 0;
-            globalObject = 0;
-            globalThis = 0;
-        }
-#endif
 
-        ScopeChainNode* next;
-        JSObject* object;
         JSGlobalData* globalData;
-        JSGlobalObject* globalObject;
-        JSObject* globalThis;
-        int refCount;
-
-        void deref() { ASSERT(refCount); if (--refCount == 0) { release();} }
-        void ref() { ASSERT(refCount); ++refCount; }
-        void release();
-
-        // Before calling "push" on a bare ScopeChainNode, a client should
-        // logically "copy" the node. Later, the client can "deref" the head
-        // of its chain of ScopeChainNodes to reclaim all the nodes it added
-        // after the logical copy, leaving nodes added before the logical copy
-        // (nodes shared with other clients) untouched.
-        ScopeChainNode* copy()
-        {
-            ref();
-            return this;
-        }
+        WriteBarrier<ScopeChainNode> next;
+        WriteBarrier<JSObject> object;
+        WriteBarrier<JSGlobalObject> globalObject;
+        WriteBarrier<JSObject> globalThis;
 
         ScopeChainNode* push(JSObject*);
         ScopeChainNode* pop();
 
-        ScopeChainIterator begin() const;
-        ScopeChainIterator end() const;
+        ScopeChainIterator begin();
+        ScopeChainIterator end();
+
+        int localDepth();
 
 #ifndef NDEBUG        
-        void print() const;
+        void print();
 #endif
+        
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) { return Structure::create(globalData, proto, TypeInfo(CompoundType, StructureFlags), AnonymousSlotCount, &s_info); }
+        virtual void visitChildren(SlotVisitor&);
+        static JS_EXPORTDATA const ClassInfo s_info;
+
+    private:
+        static const unsigned StructureFlags = OverridesVisitChildren;
     };
 
     inline ScopeChainNode* ScopeChainNode::push(JSObject* o)
     {
         ASSERT(o);
-        return new ScopeChainNode(this, o, globalData, globalObject, globalThis);
+        return new (globalData) ScopeChainNode(this, o, globalData, globalObject.get(), globalThis.get());
     }
 
     inline ScopeChainNode* ScopeChainNode::pop()
     {
         ASSERT(next);
-        ScopeChainNode* result = next;
-
-        if (--refCount != 0)
-            ++result->refCount;
-        else
-            delete this;
-
-        return result;
-    }
-
-    inline void ScopeChainNode::release()
-    {
-        // This function is only called by deref(),
-        // Deref ensures these conditions are true.
-        ASSERT(refCount == 0);
-        ScopeChainNode* n = this;
-        do {
-            ScopeChainNode* next = n->next;
-            delete n;
-            n = next;
-        } while (n && --n->refCount == 0);
+        return next.get();
     }
 
     class ScopeChainIterator {
     public:
-        ScopeChainIterator(const ScopeChainNode* node)
+        ScopeChainIterator(ScopeChainNode* node)
             : m_node(node)
         {
         }
 
-        JSObject* const & operator*() const { return m_node->object; }
-        JSObject* const * operator->() const { return &(operator*()); }
+        WriteBarrier<JSObject> const & operator*() const { return m_node->object; }
+        WriteBarrier<JSObject> const * operator->() const { return &(operator*()); }
     
-        ScopeChainIterator& operator++() { m_node = m_node->next; return *this; }
+        ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; }
 
         // postfix ++ intentionally omitted
 
@@ -141,99 +104,43 @@ namespace JSC {
         bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
 
     private:
-        const ScopeChainNode* m_node;
+        ScopeChainNode* m_node;
     };
 
-    inline ScopeChainIterator ScopeChainNode::begin() const
+    inline ScopeChainIterator ScopeChainNode::begin()
     {
         return ScopeChainIterator(this); 
     }
 
-    inline ScopeChainIterator ScopeChainNode::end() const
+    inline ScopeChainIterator ScopeChainNode::end()
     { 
         return ScopeChainIterator(0); 
     }
 
-    class NoScopeChain {};
-
-    class ScopeChain {
-        friend class JIT;
-    public:
-        ScopeChain(NoScopeChain)
-            : m_node(0)
-        {
-        }
-
-        ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
-            : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis))
-        {
-        }
-
-        ScopeChain(const ScopeChain& c)
-            : m_node(c.m_node->copy())
-        {
-        }
-
-        ScopeChain& operator=(const ScopeChain& c);
-
-        explicit ScopeChain(ScopeChainNode* node)
-            : m_node(node->copy())
-        {
-        }
-
-        ~ScopeChain()
-        {
-            if (m_node)
-                m_node->deref();
-#ifndef NDEBUG
-            m_node = 0;
-#endif
-        }
-
-        void swap(ScopeChain&);
-
-        ScopeChainNode* node() const { return m_node; }
-
-        JSObject* top() const { return m_node->object; }
-
-        ScopeChainIterator begin() const { return m_node->begin(); }
-        ScopeChainIterator end() const { return m_node->end(); }
-
-        void push(JSObject* o) { m_node = m_node->push(o); }
-
-        void pop() { m_node = m_node->pop(); }
-        void clear() { m_node->deref(); m_node = 0; }
-        
-        JSGlobalObject* globalObject() const { return m_node->globalObject; }
-
-        void markAggregate(MarkStack&) const;
-
-        // Caution: this should only be used if the codeblock this is being used
-        // with needs a full scope chain, otherwise this returns the depth of
-        // the preceeding call frame
-        //
-        // Returns the depth of the current call frame's scope chain
-        int localDepth() const;
-
-#ifndef NDEBUG        
-        void print() const { m_node->print(); }
-#endif
-
-    private:
-        ScopeChainNode* m_node;
-    };
-
-    inline void ScopeChain::swap(ScopeChain& o)
+    ALWAYS_INLINE JSGlobalData& ExecState::globalData() const
     {
-        ScopeChainNode* tmp = m_node;
-        m_node = o.m_node;
-        o.m_node = tmp;
+        ASSERT(scopeChain()->globalData);
+        return *scopeChain()->globalData;
     }
 
-    inline ScopeChain& ScopeChain::operator=(const ScopeChain& c)
+    ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const
+    {
+        return scopeChain()->globalObject.get();
+    }
+    
+    ALWAYS_INLINE JSObject* ExecState::globalThisValue() const
+    {
+        return scopeChain()->globalThis.get();
+    }
+    
+    ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const
+    {
+        return static_cast<ScopeChainNode*>(jsValue().asCell());
+    }
+    
+    ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain)
     {
-        ScopeChain tmp(c);
-        swap(tmp);
+        *this = JSValue(scopeChain);
         return *this;
     }
 
index 984d101368a9bc9ca078da27accb02f75a1deed6..35701f11d05339ca04a2c1943277c73eef48dde7 100644 (file)
 
 namespace JSC {
 
-    inline void ScopeChain::markAggregate(MarkStack& markStack) const
-    {
-        for (ScopeChainNode* n = m_node; n; n = n->next)
-            markStack.append(n->object);
-    }
-
 } // namespace JSC
 
 #endif // ScopeChainMark_h
index 0f5df4a23884bfe40f651fc335dda7a1f13ecfeb..8741e9bd29a53220d916f9971c20278fb04de1e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #include "JSGlobalObject.h"
 #include "JSString.h"
-
 #include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
-static const unsigned numCharactersToStore = 0x100;
 
-static inline bool isMarked(JSString* string)
+static inline bool isMarked(JSCell* string)
 {
-    return string && Heap::isCellMarked(string);
+    return string && Heap::isMarked(string);
 }
 
-class SmallStringsStorage : public Noncopyable {
+class SmallStringsStorage {
+    WTF_MAKE_NONCOPYABLE(SmallStringsStorage); WTF_MAKE_FAST_ALLOCATED;
 public:
     SmallStringsStorage();
 
-    UString::Rep* rep(unsigned char character) { return m_reps[character].get(); }
+    StringImpl* rep(unsigned char character)
+    {
+        return m_reps[character].get();
+    }
 
 private:
-    RefPtr<UString::Rep> m_reps[numCharactersToStore];
+    static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
+
+    RefPtr<StringImpl> m_reps[singleCharacterStringCount];
 };
 
 SmallStringsStorage::SmallStringsStorage()
 {
     UChar* characterBuffer = 0;
-    RefPtr<UStringImpl> baseString = UStringImpl::createUninitialized(numCharactersToStore, characterBuffer);
-    for (unsigned i = 0; i < numCharactersToStore; ++i) {
+    RefPtr<StringImpl> baseString = StringImpl::createUninitialized(singleCharacterStringCount, characterBuffer);
+    for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
         characterBuffer[i] = i;
-        m_reps[i] = UStringImpl::create(baseString, i, 1);
+        m_reps[i] = StringImpl::create(baseString, i, 1);
     }
 }
 
 SmallStrings::SmallStrings()
 {
-    COMPILE_ASSERT(numCharactersToStore == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
+    COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage);
     clear();
 }
 
@@ -69,7 +74,7 @@ SmallStrings::~SmallStrings()
 {
 }
 
-void SmallStrings::markChildren(MarkStack& markStack)
+void SmallStrings::visitChildren(HeapRootVisitor& heapRootMarker)
 {
     /*
        Our hypothesis is that small strings are very common. So, we cache them
@@ -82,7 +87,7 @@ void SmallStrings::markChildren(MarkStack& markStack)
      */
 
     bool isAnyStringMarked = isMarked(m_emptyString);
-    for (unsigned i = 0; i < numCharactersToStore && !isAnyStringMarked; ++i)
+    for (unsigned i = 0; i < singleCharacterStringCount && !isAnyStringMarked; ++i)
         isAnyStringMarked = isMarked(m_singleCharacterStrings[i]);
     
     if (!isAnyStringMarked) {
@@ -91,17 +96,17 @@ void SmallStrings::markChildren(MarkStack& markStack)
     }
     
     if (m_emptyString)
-        markStack.append(m_emptyString);
-    for (unsigned i = 0; i < numCharactersToStore; ++i) {
+        heapRootMarker.mark(&m_emptyString);
+    for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
         if (m_singleCharacterStrings[i])
-            markStack.append(m_singleCharacterStrings[i]);
+            heapRootMarker.mark(&m_singleCharacterStrings[i]);
     }
 }
 
 void SmallStrings::clear()
 {
     m_emptyString = 0;
-    for (unsigned i = 0; i < numCharactersToStore; ++i)
+    for (unsigned i = 0; i < singleCharacterStringCount; ++i)
         m_singleCharacterStrings[i] = 0;
 }
 
@@ -110,7 +115,7 @@ unsigned SmallStrings::count() const
     unsigned count = 0;
     if (m_emptyString)
         ++count;
-    for (unsigned i = 0; i < numCharactersToStore; ++i) {
+    for (unsigned i = 0; i < singleCharacterStringCount; ++i) {
         if (m_singleCharacterStrings[i])
             ++count;
     }
@@ -126,15 +131,15 @@ void SmallStrings::createEmptyString(JSGlobalData* globalData)
 void SmallStrings::createSingleCharacterString(JSGlobalData* globalData, unsigned char character)
 {
     if (!m_storage)
-        m_storage.set(new SmallStringsStorage);
+        m_storage = adoptPtr(new SmallStringsStorage);
     ASSERT(!m_singleCharacterStrings[character]);
-    m_singleCharacterStrings[character] = new (globalData) JSString(globalData, m_storage->rep(character), JSString::HasOtherOwner);
+    m_singleCharacterStrings[character] = new (globalData) JSString(globalData, PassRefPtr<StringImpl>(m_storage->rep(character)), JSString::HasOtherOwner);
 }
 
-UString::Rep* SmallStrings::singleCharacterStringRep(unsigned char character)
+StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character)
 {
     if (!m_storage)
-        m_storage.set(new SmallStringsStorage);
+        m_storage = adoptPtr(new SmallStringsStorage);
     return m_storage->rep(character);
 }
 
index bc337c995806d35c1af111c5693760de122d3d54..e762e1f365c88c38d02cce2d775bd192e6c996c1 100644 (file)
 #define SmallStrings_h
 
 #include "UString.h"
+#include <wtf/FixedArray.h>
 #include <wtf/OwnPtr.h>
 
 namespace JSC {
 
+    class HeapRootVisitor;
     class JSGlobalData;
     class JSString;
     class MarkStack;
     class SmallStringsStorage;
+    typedef MarkStack SlotVisitor;
 
-    class SmallStrings : public Noncopyable {
+    static const unsigned maxSingleCharacterString = 0xFF;
+
+    class SmallStrings {
+        WTF_MAKE_NONCOPYABLE(SmallStrings);
     public:
         SmallStrings();
         ~SmallStrings();
@@ -47,6 +53,7 @@ namespace JSC {
                 createEmptyString(globalData);
             return m_emptyString;
         }
+
         JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
         {
             if (!m_singleCharacterStrings[character])
@@ -54,21 +61,23 @@ namespace JSC {
             return m_singleCharacterStrings[character];
         }
 
-        UString::Rep* singleCharacterStringRep(unsigned char character);
+        StringImpl* singleCharacterStringRep(unsigned char character);
 
-        void markChildren(MarkStack&);
+        void visitChildren(HeapRootVisitor&);
         void clear();
 
         unsigned count() const;
-#if ENABLE(JIT)
-        JSString** singleCharacterStrings() { return m_singleCharacterStrings; }
-#endif
+
+        JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
+
     private:
+        static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
+
         void createEmptyString(JSGlobalData*);
         void createSingleCharacterString(JSGlobalData*, unsigned char);
 
         JSString* m_emptyString;
-        JSString* m_singleCharacterStrings[0x100];
+        JSString* m_singleCharacterStrings[singleCharacterStringCount];
         OwnPtr<SmallStringsStorage> m_storage;
     };
 
diff --git a/runtime/StrictEvalActivation.cpp b/runtime/StrictEvalActivation.cpp
new file mode 100644 (file)
index 0000000..e666dee
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "StrictEvalActivation.h"
+
+namespace JSC {
+
+StrictEvalActivation::StrictEvalActivation(ExecState* exec)
+    : JSNonFinalObject(exec->globalData(), exec->globalData().strictEvalActivationStructure.get())
+{
+}
+
+bool StrictEvalActivation::deleteProperty(ExecState*, const Identifier&)
+{
+    return false;
+}
+
+JSObject* StrictEvalActivation::toThisObject(ExecState* exec) const
+{
+    return exec->globalThisValue();
+}
+
+JSValue StrictEvalActivation::toStrictThisObject(ExecState*) const
+{
+    return jsNull();
+}
+
+}
diff --git a/runtime/StrictEvalActivation.h b/runtime/StrictEvalActivation.h
new file mode 100644 (file)
index 0000000..e2885cc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 StrictEvalActivation_h
+#define StrictEvalActivation_h
+
+#include "JSObject.h"
+
+namespace JSC {
+
+class StrictEvalActivation : public JSNonFinalObject {
+public:
+    StrictEvalActivation(ExecState*);
+    virtual bool deleteProperty(ExecState*, const Identifier&);
+    virtual JSObject* toThisObject(ExecState*) const;
+    virtual JSValue toStrictThisObject(ExecState*) const;
+};
+
+} // namespace JSC
+
+#endif // StrictEvalActivation_h
diff --git a/runtime/StringBuilder.h b/runtime/StringBuilder.h
deleted file mode 100644 (file)
index f028c08..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2009 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 StringBuilder_h
-#define StringBuilder_h
-
-#include <wtf/Vector.h>
-
-namespace JSC {
-
-class StringBuilder {
-public:
-    void append(const UChar u)
-    {
-        buffer.append(u);
-    }
-
-    void append(const char* str)
-    {
-        append(str, strlen(str));
-    }
-
-    void append(const char* str, size_t len)
-    {
-        reserveCapacity(buffer.size() + len);
-        for (size_t i = 0; i < len; i++)
-            buffer.append(static_cast<unsigned char>(str[i]));
-    }
-
-    void append(const UChar* str, size_t len)
-    {
-        buffer.append(str, len);
-    }
-
-    void append(const UString& str)
-    {
-        buffer.append(str.data(), str.size());
-    }
-
-    bool isEmpty() { return buffer.isEmpty(); }
-    void reserveCapacity(size_t newCapacity)
-    {
-        if (newCapacity < buffer.capacity())
-            return;
-        buffer.reserveCapacity(std::max(newCapacity, buffer.capacity() + buffer.capacity() / 4 + 1));
-    }
-    void resize(size_t size) { buffer.resize(size); }
-    size_t size() const { return buffer.size(); }
-
-    UChar operator[](size_t i) const { return buffer.at(i); }
-
-    UString build()
-    {
-        buffer.shrinkToFit();
-        ASSERT(buffer.data() || !buffer.size());
-        return UString::adopt(buffer);
-    }
-
-protected:
-    Vector<UChar, 64> buffer;
-};
-
-}
-
-#endif
index 94bee4391d1a0996f2a5d4c5aa641d9c29092e7a..ea6e12853e776820cdef9df6fbdb604a50eff564 100644 (file)
 #include "config.h"
 #include "StringConstructor.h"
 
+#include "Executable.h"
+#include "JITCode.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
-#include "PrototypeFunction.h"
 #include "StringPrototype.h"
 
 namespace JSC {
 
-static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL stringFromCharCode(ExecState*);
+
+}
+
+#include "StringConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo StringConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::stringConstructorTable };
+
+/* Source for StringConstructor.lut.h
+@begin stringConstructorTable
+  fromCharCode          stringFromCharCode         DontEnum|Function 1
+@end
+*/
+
+ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+
+StringConstructor::StringConstructor(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, StringPrototype* stringPrototype)
+    : InternalFunction(&exec->globalData(), globalObject, structure, Identifier(exec, stringPrototype->classInfo()->className))
 {
-    unsigned length = args.size();
-    UChar* buf;
-    PassRefPtr<UStringImpl> impl = UStringImpl::createUninitialized(length, buf);
-    for (unsigned i = 0; i < length; ++i)
-        buf[i] = static_cast<UChar>(args.at(i).toUInt32(exec));
-    return jsString(exec, impl);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(1), ReadOnly | DontEnum | DontDelete);
 }
 
-static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+bool StringConstructor::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
-    if (LIKELY(args.size() == 1))
-        return jsSingleCharacterString(exec, args.at(0).toUInt32(exec));
-    return stringFromCharCodeSlowCase(exec, args);
+    return getStaticFunctionSlot<InternalFunction>(exec, ExecState::stringConstructorTable(exec), this, propertyName, slot);
 }
 
-ASSERT_CLASS_FITS_IN_CELL(StringConstructor);
+bool StringConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+    return getStaticFunctionDescriptor<InternalFunction>(exec, ExecState::stringConstructorTable(exec), this, propertyName, descriptor);
+}
+
+// ------------------------------ Functions --------------------------------
+
+static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec)
+{
+    unsigned length = exec->argumentCount();
+    UChar* buf;
+    PassRefPtr<StringImpl> impl = StringImpl::createUninitialized(length, buf);
+    for (unsigned i = 0; i < length; ++i)
+        buf[i] = static_cast<UChar>(exec->argument(i).toUInt32(exec));
+    return jsString(exec, impl);
+}
 
-StringConstructor::StringConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype)
-    : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className))
+static EncodedJSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec)
 {
-    // ECMA 15.5.3.1 String.prototype
-    putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete);
-
-    // ECMA 15.5.3.2 fromCharCode()
-#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, exec->globalData().getThunk(fromCharCodeThunkGenerator), stringFromCharCode), DontEnum);
-#else
-    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum);
-#endif
-    // no. of arguments for constructor
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
+    if (LIKELY(exec->argumentCount() == 1))
+        return JSValue::encode(jsSingleCharacterString(exec, exec->argument(0).toUInt32(exec)));
+    return JSValue::encode(stringFromCharCodeSlowCase(exec));
 }
 
-// ECMA 15.5.2
-static JSObject* constructWithStringConstructor(ExecState* exec, JSObject*, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL constructWithStringConstructor(ExecState* exec)
 {
-    if (args.isEmpty())
-        return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure());
-    return new (exec) StringObject(exec, exec->lexicalGlobalObject()->stringObjectStructure(), args.at(0).toString(exec));
+    JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
+    if (!exec->argumentCount())
+        return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure()));
+    return JSValue::encode(new (exec) StringObject(exec, globalObject->stringObjectStructure(), exec->argument(0).toString(exec)));
 }
 
 ConstructType StringConstructor::getConstructData(ConstructData& constructData)
@@ -77,12 +97,11 @@ ConstructType StringConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
-// ECMA 15.5.1
-static JSValue JSC_HOST_CALL callStringConstructor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
+static EncodedJSValue JSC_HOST_CALL callStringConstructor(ExecState* exec)
 {
-    if (args.isEmpty())
-        return jsEmptyString(exec);
-    return jsString(exec, args.at(0).toString(exec));
+    if (!exec->argumentCount())
+        return JSValue::encode(jsEmptyString(exec));
+    return JSValue::encode(jsString(exec, exec->argument(0).toString(exec)));
 }
 
 CallType StringConstructor::getCallData(CallData& callData)
index e511f7bf2ea0a76ff5082bd30b66b7a2c66e972c..b2e3be60949d7c3d9ad2a662ac53530988f2af2f 100644 (file)
@@ -29,10 +29,24 @@ namespace JSC {
 
     class StringConstructor : public InternalFunction {
     public:
-        StringConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*);
+        StringConstructor(ExecState*, JSGlobalObject*, Structure*, StringPrototype*);
 
+        static const ClassInfo s_info;
+
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InternalFunction::StructureFlags;
+
+    private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
+
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
index f8e0e872b40c549006080e50f3228bedf98b91b3..67dc291b09ecf7d7eba88aaf296fa5348ec22cf9 100644 (file)
@@ -27,24 +27,27 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringObject);
 
-const ClassInfo StringObject::info = { "String", 0, 0, 0 };
+const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 };
 
-StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure)
-    : JSWrapperObject(structure)
+StringObject::StringObject(ExecState* exec, Structure* structure)
+    : JSWrapperObject(exec->globalData(), structure)
 {
-    setInternalValue(jsEmptyString(exec));
+    ASSERT(inherits(&s_info));
+    setInternalValue(exec->globalData(), jsEmptyString(exec));
 }
 
-StringObject::StringObject(NonNullPassRefPtr<Structure> structure, JSString* string)
-    : JSWrapperObject(structure)
+StringObject::StringObject(JSGlobalData& globalData, Structure* structure, JSString* string)
+    : JSWrapperObject(globalData, structure)
 {
-    setInternalValue(string);
+    ASSERT(inherits(&s_info));
+    setInternalValue(globalData, string);
 }
 
-StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
-    : JSWrapperObject(structure)
+StringObject::StringObject(ExecState* exec, Structure* structure, const UString& string)
+    : JSWrapperObject(exec->globalData(), structure)
 {
-    setInternalValue(jsString(exec, string));
+    ASSERT(inherits(&s_info));
+    setInternalValue(exec->globalData(), jsString(exec, string));
 }
 
 bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -80,7 +83,7 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam
     if (propertyName == exec->propertyNames().length)
         return false;
     bool isStrictUInt32;
-    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
+    unsigned i = propertyName.toUInt32(isStrictUInt32);
     if (isStrictUInt32 && internalValue()->canGetIndex(i))
         return false;
     return JSObject::deleteProperty(exec, propertyName);
@@ -90,7 +93,7 @@ void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& prope
 {
     int size = internalValue()->length();
     for (int i = 0; i < size; ++i)
-        propertyNames.add(Identifier(exec, UString::from(i)));
+        propertyNames.add(Identifier(exec, UString::number(i)));
     if (mode == IncludeDontEnumProperties)
         propertyNames.add(exec->propertyNames().length);
     return JSObject::getOwnPropertyNames(exec, propertyNames, mode);
index e3add77b92bbff5843186b46dec4ed5cedc07738..4c16044fba698574ced732a22ccf6fc66d247bf1 100644 (file)
@@ -28,10 +28,10 @@ namespace JSC {
 
     class StringObject : public JSWrapperObject {
     public:
-        StringObject(ExecState*, NonNullPassRefPtr<Structure>);
-        StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&);
+        StringObject(ExecState*, Structure*);
+        StringObject(ExecState*, Structure*, const UString&);
 
-        static StringObject* create(ExecState*, JSString*);
+        static StringObject* create(ExecState*, JSGlobalObject*, JSString*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
@@ -41,26 +41,25 @@ namespace JSC {
         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const JS_EXPORTDATA ClassInfo info;
+        static const JS_EXPORTDATA ClassInfo s_info;
 
         JSString* internalValue() const { return asString(JSWrapperObject::internalValue());}
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
-        StringObject(NonNullPassRefPtr<Structure>, JSString*);
-  };
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags;
+        StringObject(JSGlobalData&, Structure*, JSString*);
+    };
 
     StringObject* asStringObject(JSValue);
 
     inline StringObject* asStringObject(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&StringObject::info));
+        ASSERT(asObject(value)->inherits(&StringObject::s_info));
         return static_cast<StringObject*>(asObject(value));
     }
 
index 43c3e3839a41f09bc01cc40d1e36ecc2566d6bc3..313394458f3d0118412c648880344027237cacd9 100644 (file)
@@ -33,18 +33,18 @@ namespace JSC {
         static StringObjectThatMasqueradesAsUndefined* create(ExecState* exec, const UString& string)
         {
             return new (exec) StringObjectThatMasqueradesAsUndefined(exec,
-                createStructure(exec->lexicalGlobalObject()->stringPrototype()), string);
+                createStructure(exec->globalData(), exec->lexicalGlobalObject()->stringPrototype()), string);
         }
 
     private:
-        StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
+        StringObjectThatMasqueradesAsUndefined(ExecState* exec, Structure* structure, const UString& string)
             : StringObject(exec, structure, string)
         {
         }
 
-        static PassRefPtr<Structure> createStructure(JSValue proto) 
+        static Structure* createStructure(JSGlobalData& globalData, JSValue proto) 
         { 
-            return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); 
+            return Structure::create(globalData, proto, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info); 
         }
 
         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags;
index 1e16513c05a36528ead3fba3a2f676b11dc205fb..ce88a465e5eec752bf2411aa909ca1934c2ec0df 100644 (file)
@@ -46,40 +46,38 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringPrototype);
 
-static JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState*, JSObject*, JSValue, const ArgList&);
-
-static JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&);
-
-static JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*, JSObject*, JSValue, const ArgList&);
-static JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*, JSObject*, JSValue, const ArgList&);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncBold(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSub(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncSup(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*);
+static EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*);
 
 }
 
@@ -87,7 +85,7 @@ static JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*, JSObject*, JSV
 
 namespace JSC {
 
-const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, ExecState::stringTable };
+const ClassInfo StringPrototype::s_info = { "String", &StringObject::s_info, 0, ExecState::stringTable };
 
 /* Source for StringPrototype.lut.h
 @begin stringTable 26
@@ -133,11 +131,14 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec
 */
 
 // ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
     : StringObject(exec, structure)
 {
+    ASSERT(inherits(&s_info));
+
+    putAnonymousValue(exec->globalData(), 0, globalObject);
     // The constructor will be added later, after StringConstructor has been built
-    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
+    putDirectWithoutTransition(exec->globalData(), exec->propertyNames().length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
 }
 
 bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
@@ -152,19 +153,19 @@ bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier
 
 // ------------------------------ Functions --------------------------
 
-static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, unsigned i)
+static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, size_t i)
 {
     Vector<UChar> substitutedReplacement;
     int offset = 0;
     do {
-        if (i + 1 == replacement.size())
+        if (i + 1 == replacement.length())
             break;
 
         UChar ref = replacement[i + 1];
         if (ref == '$') {
             // "$$" -> "$"
             ++i;
-            substitutedReplacement.append(replacement.data() + offset, i - offset);
+            substitutedReplacement.append(replacement.characters() + offset, i - offset);
             offset = i + 1;
             continue;
         }
@@ -180,13 +181,13 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
             backrefLength = ovector[0];
         } else if (ref == '\'') {
             backrefStart = ovector[1];
-            backrefLength = source.size() - backrefStart;
+            backrefLength = source.length() - backrefStart;
         } else if (reg && ref >= '0' && ref <= '9') {
             // 1- and 2-digit back references are allowed
             unsigned backrefIndex = ref - '0';
             if (backrefIndex > reg->numSubpatterns())
                 continue;
-            if (replacement.size() > i + 2) {
+            if (replacement.length() > i + 2) {
                 ref = replacement[i + 2];
                 if (ref >= '0' && ref <= '9') {
                     backrefIndex = 10 * backrefIndex + ref - '0';
@@ -204,14 +205,15 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
             continue;
 
         if (i - offset)
-            substitutedReplacement.append(replacement.data() + offset, i - offset);
+            substitutedReplacement.append(replacement.characters() + offset, i - offset);
         i += 1 + advance;
         offset = i + 1;
-        substitutedReplacement.append(source.data() + backrefStart, backrefLength);
-    } while ((i = replacement.find('$', i + 1)) != UString::NotFound);
+        if (backrefStart >= 0)
+            substitutedReplacement.append(source.characters() + backrefStart, backrefLength);
+    } while ((i = replacement.find('$', i + 1)) != notFound);
 
-    if (replacement.size() - offset)
-        substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset);
+    if (replacement.length() - offset)
+        substitutedReplacement.append(replacement.characters() + offset, replacement.length() - offset);
 
     substitutedReplacement.shrinkToFit();
     return UString::adopt(substitutedReplacement);
@@ -219,15 +221,15 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem
 
 static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg)
 {
-    unsigned i = replacement.find('$', 0);
-    if (UNLIKELY(i != UString::NotFound))
+    size_t i = replacement.find('$', 0);
+    if (UNLIKELY(i != notFound))
         return substituteBackreferencesSlow(replacement, source, ovector, reg, i);
     return replacement;
 }
 
 static inline int localeCompare(const UString& a, const UString& b)
 {
-    return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.data()), a.size(), reinterpret_cast<const ::UChar*>(b.data()), b.size());
+    return Collator::userDefault()->collate(reinterpret_cast<const ::UChar*>(a.characters()), a.length(), reinterpret_cast<const ::UChar*>(b.characters()), b.length());
 }
 
 struct StringRange {
@@ -246,30 +248,29 @@ public:
     int length;
 };
 
-JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount);
-JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount)
+static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount)
 {
     if (rangeCount == 1 && separatorCount == 0) {
-        int sourceSize = source.size();
+        int sourceSize = source.length();
         int position = substringRanges[0].position;
         int length = substringRanges[0].length;
         if (position <= 0 && length >= sourceSize)
             return sourceVal;
         // We could call UString::substr, but this would result in redundant checks
-        return jsString(exec, UStringImpl::create(source.rep(), max(0, position), min(sourceSize, length)));
+        return jsString(exec, StringImpl::create(source.impl(), max(0, position), min(sourceSize, length)));
     }
 
     int totalLength = 0;
     for (int i = 0; i < rangeCount; i++)
         totalLength += substringRanges[i].length;
     for (int i = 0; i < separatorCount; i++)
-        totalLength += separators[i].size();
+        totalLength += separators[i].length();
 
     if (totalLength == 0)
         return jsString(exec, "");
 
     UChar* buffer;
-    PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(totalLength, buffer);
+    PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
     if (!impl)
         return throwOutOfMemoryError(exec);
 
@@ -277,34 +278,41 @@ JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, c
     int bufferPos = 0;
     for (int i = 0; i < maxCount; i++) {
         if (i < rangeCount) {
-            UStringImpl::copyChars(buffer + bufferPos, source.data() + substringRanges[i].position, substringRanges[i].length);
-            bufferPos += substringRanges[i].length;
+            if (int srcLen = substringRanges[i].length) {
+                StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen);
+                bufferPos += srcLen;
+            }
         }
         if (i < separatorCount) {
-            UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size());
-            bufferPos += separators[i].size();
+            if (int sepLen = separators[i].length()) {
+                StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), sepLen);
+                bufferPos += sepLen;
+            }
         }
     }
 
     return jsString(exec, impl);
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     JSString* sourceVal = thisValue.toThisJSString(exec);
-    JSValue pattern = args.at(0);
-    JSValue replacement = args.at(1);
+    JSValue pattern = exec->argument(0);
+    JSValue replacement = exec->argument(1);
+    JSGlobalData* globalData = &exec->globalData();
 
     UString replacementString;
     CallData callData;
-    CallType callType = replacement.getCallData(callData);
+    CallType callType = getCallData(replacement, callData);
     if (callType == CallTypeNone)
         replacementString = replacement.toString(exec);
 
-    if (pattern.inherits(&RegExpObject::info)) {
+    if (pattern.inherits(&RegExpObject::s_info)) {
         const UString& source = sourceVal->value(exec);
+        unsigned sourceLen = source.length();
         if (exec->hadException())
-            return JSValue();
+            return JSValue::encode(JSValue());
         RegExp* reg = asRegExpObject(pattern)->regExp();
         bool global = reg->global();
 
@@ -321,17 +329,17 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
             // reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue
             int argCount = reg->numSubpatterns() + 1 + 2;
             JSFunction* func = asFunction(replacement);
-            CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot());
+            CachedCall cachedCall(exec, func, argCount);
             if (exec->hadException())
-                return jsNull();
+                return JSValue::encode(jsNull());
             while (true) {
                 int matchIndex;
                 int matchLen = 0;
                 int* ovector;
-                regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+                regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
                 if (matchIndex < 0)
                     break;
-                
+
                 sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
 
                 int completeMatchStart = ovector[0];
@@ -346,12 +354,15 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
                         cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen));
                 }
 
-                cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart));
+                cachedCall.setArgument(i++, jsNumber(completeMatchStart));
                 cachedCall.setArgument(i++, sourceVal);
-                
+
                 cachedCall.setThis(exec->globalThisValue());
                 JSValue result = cachedCall.call();
-                replacements.append(result.toString(cachedCall.newCallFrame(exec)));
+                if (LIKELY(result.isString()))
+                    replacements.append(asString(result)->value(exec));
+                else
+                    replacements.append(result.toString(cachedCall.newCallFrame(exec)));
                 if (exec->hadException())
                     break;
 
@@ -361,43 +372,52 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
                 // special case of empty match
                 if (matchLen == 0) {
                     startPosition++;
-                    if (startPosition > source.size())
+                    if (startPosition > sourceLen)
                         break;
                 }
-            }            
+            }
         } else {
             do {
                 int matchIndex;
                 int matchLen = 0;
                 int* ovector;
-                regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
+                regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
                 if (matchIndex < 0)
                     break;
 
-                sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
-
                 if (callType != CallTypeNone) {
+                    sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
+
                     int completeMatchStart = ovector[0];
                     MarkedArgumentBuffer args;
 
                     for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
                         int matchStart = ovector[i * 2];
                         int matchLen = ovector[i * 2 + 1] - matchStart;
-
                         if (matchStart < 0)
                             args.append(jsUndefined());
                         else
                             args.append(jsSubstring(exec, source, matchStart, matchLen));
                     }
 
-                    args.append(jsNumber(exec, completeMatchStart));
+                    args.append(jsNumber(completeMatchStart));
                     args.append(sourceVal);
 
                     replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec));
                     if (exec->hadException())
                         break;
-                } else
-                    replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
+                } else {
+                    int replLen = replacementString.length();
+                    if (lastIndex < matchIndex || replLen) {
+                        sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
+                        if (replLen)
+                            replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
+                        else
+                            replacements.append(UString());
+                    }
+                }
 
                 lastIndex = matchIndex + matchLen;
                 startPosition = lastIndex;
@@ -405,38 +425,39 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
                 // special case of empty match
                 if (matchLen == 0) {
                     startPosition++;
-                    if (startPosition > source.size())
+                    if (startPosition > sourceLen)
                         break;
                 }
             } while (global);
         }
 
         if (!lastIndex && replacements.isEmpty())
-            return sourceVal;
+            return JSValue::encode(sourceVal);
 
-        if (static_cast<unsigned>(lastIndex) < source.size())
-            sourceRanges.append(StringRange(lastIndex, source.size() - lastIndex));
+        if (static_cast<unsigned>(lastIndex) < sourceLen)
+            sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
 
-        return jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size());
+        return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size()));
     }
 
     // Not a regular expression, so treat the pattern as a string.
 
     UString patternString = pattern.toString(exec);
-    if (patternString.size() == 1 && callType == CallTypeNone)
-        return sourceVal->replaceCharacter(exec, patternString[0], replacementString);
-    
+    // Special case for single character patterns without back reference replacement
+    if (patternString.length() == 1 && callType == CallTypeNone && replacementString.find('$', 0) == notFound)
+        return JSValue::encode(sourceVal->replaceCharacter(exec, patternString[0], replacementString));
+
     const UString& source = sourceVal->value(exec);
-    unsigned matchPos = source.find(patternString);
+    size_t matchPos = source.find(patternString);
 
-    if (matchPos == UString::NotFound)
-        return sourceVal;
+    if (matchPos == notFound)
+        return JSValue::encode(sourceVal);
 
-    int matchLen = patternString.size();
+    int matchLen = patternString.length();
     if (callType != CallTypeNone) {
         MarkedArgumentBuffer args;
         args.append(jsSubstring(exec, source, matchPos, matchLen));
-        args.append(jsNumber(exec, matchPos));
+        args.append(jsNumber(matchPos));
         args.append(sourceVal);
 
         replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec);
@@ -444,75 +465,87 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue
     
     size_t matchEnd = matchPos + matchLen;
     int ovector[2] = { matchPos, matchEnd };
-    return jsString(exec, source.substr(0, matchPos), substituteBackreferences(replacementString, source, ovector, 0), source.substr(matchEnd));
+    return JSValue::encode(jsString(exec, source.substringSharingImpl(0, matchPos), substituteBackreferences(replacementString, source, ovector, 0), source.substringSharingImpl(matchEnd)));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     // Also used for valueOf.
 
     if (thisValue.isString())
-        return thisValue;
+        return JSValue::encode(thisValue);
 
-    if (thisValue.inherits(&StringObject::info))
-        return asStringObject(thisValue)->internalValue();
+    if (thisValue.inherits(&StringObject::s_info))
+        return JSValue::encode(asStringObject(thisValue)->internalValue());
 
-    return throwError(exec, TypeError);
+    return throwVMTypeError(exec);
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
-    unsigned len = s.size();
-    JSValue a0 = args.at(0);
+    unsigned len = s.length();
+    JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
         uint32_t i = a0.asUInt32();
         if (i < len)
-            return jsSingleCharacterSubstring(exec, s, i);
-        return jsEmptyString(exec);
+            return JSValue::encode(jsSingleCharacterSubstring(exec, s, i));
+        return JSValue::encode(jsEmptyString(exec));
     }
     double dpos = a0.toInteger(exec);
     if (dpos >= 0 && dpos < len)
-        return jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos));
-    return jsEmptyString(exec);
+        return JSValue::encode(jsSingleCharacterSubstring(exec, s, static_cast<unsigned>(dpos)));
+    return JSValue::encode(jsEmptyString(exec));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
-    unsigned len = s.size();
-    JSValue a0 = args.at(0);
+    unsigned len = s.length();
+    JSValue a0 = exec->argument(0);
     if (a0.isUInt32()) {
         uint32_t i = a0.asUInt32();
         if (i < len)
-            return jsNumber(exec, s.data()[i]);
-        return jsNaN(exec);
+            return JSValue::encode(jsNumber(s.characters()[i]));
+        return JSValue::encode(jsNaN());
     }
     double dpos = a0.toInteger(exec);
     if (dpos >= 0 && dpos < len)
-        return jsNumber(exec, s[static_cast<int>(dpos)]);
-    return jsNaN(exec);
+        return JSValue::encode(jsNumber(s[static_cast<int>(dpos)]));
+    return JSValue::encode(jsNaN());
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
 {
-    if (thisValue.isString() && (args.size() == 1)) {
-        JSValue v = args.at(0);
-        return v.isString()
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isString() && (exec->argumentCount() == 1)) {
+        JSValue v = exec->argument(0);
+        return JSValue::encode(v.isString()
             ? jsString(exec, asString(thisValue), asString(v))
-            : jsString(exec, asString(thisValue), v.toString(exec));
+            : jsString(exec, asString(thisValue), v.toString(exec)));
     }
-
-    return jsString(exec, thisValue, args);
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    return JSValue::encode(jsString(exec, thisValue));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
-    int len = s.size();
+    int len = s.length();
 
-    JSValue a0 = args.at(0);
-    JSValue a1 = args.at(1);
+    JSValue a0 = exec->argument(0);
+    JSValue a1 = exec->argument(1);
     UString u2 = a0.toString(exec);
     int pos;
     if (a1.isUndefined())
@@ -528,19 +561,22 @@ JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue
         pos = static_cast<int>(dpos);
     }
 
-    unsigned result = s.find(u2, pos);
-    if (result == UString::NotFound)
-        return jsNumber(exec, -1);
-    return jsNumber(exec, result);
+    size_t result = s.find(u2, pos);
+    if (result == notFound)
+        return JSValue::encode(jsNumber(-1));
+    return JSValue::encode(jsNumber(result));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
-    int len = s.size();
+    int len = s.length();
 
-    JSValue a0 = args.at(0);
-    JSValue a1 = args.at(1);
+    JSValue a0 = exec->argument(0);
+    JSValue a1 = exec->argument(1);
 
     UString u2 = a0.toString(exec);
     double dpos = a1.toIntegerPreserveNaN(exec);
@@ -554,22 +590,24 @@ JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSV
         dpos = len;
 #endif
 
-    unsigned result = s.rfind(u2, static_cast<unsigned>(dpos));
-    if (result == UString::NotFound)
-        return jsNumber(exec, -1);
-    return jsNumber(exec, result);
+    size_t result = s.reverseFind(u2, static_cast<unsigned>(dpos));
+    if (result == notFound)
+        return JSValue::encode(jsNumber(-1));
+    return JSValue::encode(jsNumber(result));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
+    JSGlobalData* globalData = &exec->globalData();
 
-    JSValue a0 = args.at(0);
+    JSValue a0 = exec->argument(0);
 
-    UString u = s;
-    RefPtr<RegExp> reg;
-    RegExpObject* imp = 0;
-    if (a0.inherits(&RegExpObject::info))
+    RegExp* reg;
+    if (a0.inherits(&RegExpObject::s_info))
         reg = asRegExpObject(a0)->regExp();
     else {
         /*
@@ -577,49 +615,48 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
          */
-        reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null());
+        reg = RegExp::create(&exec->globalData(), a0.toString(exec), NoFlags);
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
     int matchLength = 0;
-    regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
+    regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength);
     if (!(reg->global())) {
         // case without 'g' flag is handled like RegExp.prototype.exec
         if (pos < 0)
-            return jsNull();
-        return regExpConstructor->arrayOfMatches(exec);
+            return JSValue::encode(jsNull());
+        return JSValue::encode(regExpConstructor->arrayOfMatches(exec));
     }
 
     // return array of matches
     MarkedArgumentBuffer list;
-    int lastIndex = 0;
     while (pos >= 0) {
-        list.append(jsSubstring(exec, u, pos, matchLength));
-        lastIndex = pos;
+        list.append(jsSubstring(exec, s, pos, matchLength));
         pos += matchLength == 0 ? 1 : matchLength;
-        regExpConstructor->performMatch(reg.get(), u, pos, pos, matchLength);
+        regExpConstructor->performMatch(*globalData, reg, s, pos, pos, matchLength);
     }
-    if (imp)
-        imp->setLastIndex(lastIndex);
     if (list.isEmpty()) {
         // if there are no matches at all, it's important to return
         // Null instead of an empty array, because this matches
         // other browsers and because Null is a false value.
-        return jsNull();
+        return JSValue::encode(jsNull());
     }
 
-    return constructArray(exec, list);
+    return JSValue::encode(constructArray(exec, list));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
+    JSGlobalData* globalData = &exec->globalData();
 
-    JSValue a0 = args.at(0);
+    JSValue a0 = exec->argument(0);
 
-    UString u = s;
-    RefPtr<RegExp> reg;
-    if (a0.inherits(&RegExpObject::info))
+    RegExp* reg;
+    if (a0.inherits(&RegExpObject::s_info))
         reg = asRegExpObject(a0)->regExp();
     else { 
         /*
@@ -627,22 +664,25 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue
          *  If regexp is not an object whose [[Class]] property is "RegExp", it is
          *  replaced with the result of the expression new RegExp(regexp).
          */
-        reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null());
+        reg = RegExp::create(&exec->globalData(), a0.toString(exec), NoFlags);
     }
     RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     int pos;
     int matchLength = 0;
-    regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength);
-    return jsNumber(exec, pos);
+    regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength);
+    return JSValue::encode(jsNumber(pos));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
-    int len = s.size();
+    int len = s.length();
 
-    JSValue a0 = args.at(0);
-    JSValue a1 = args.at(1);
+    JSValue a0 = exec->argument(0);
+    JSValue a1 = exec->argument(1);
 
     // The arg processing is very much like ArrayProtoFunc::Slice
     double start = a0.toInteger(exec);
@@ -654,33 +694,37 @@ JSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec, JSObject*, JSValue t
             from = 0;
         if (to > len)
             to = len;
-        return jsSubstring(exec, s, static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from));
+        return JSValue::encode(jsSubstring(exec, s, static_cast<unsigned>(from), static_cast<unsigned>(to) - static_cast<unsigned>(from)));
     }
 
-    return jsEmptyString(exec);
+    return JSValue::encode(jsEmptyString(exec));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     UString s = thisValue.toThisString(exec);
+    JSGlobalData* globalData = &exec->globalData();
 
-    JSValue a0 = args.at(0);
-    JSValue a1 = args.at(1);
+    JSValue a0 = exec->argument(0);
+    JSValue a1 = exec->argument(1);
 
     JSArray* result = constructEmptyArray(exec);
     unsigned i = 0;
     unsigned p0 = 0;
     unsigned limit = a1.isUndefined() ? 0xFFFFFFFFU : a1.toUInt32(exec);
-    if (a0.inherits(&RegExpObject::info)) {
+    if (a0.inherits(&RegExpObject::s_info)) {
         RegExp* reg = asRegExpObject(a0)->regExp();
-        if (s.isEmpty() && reg->match(s, 0) >= 0) {
+        if (s.isEmpty() && reg->match(*globalData, s, 0) >= 0) {
             // empty string matched by regexp -> empty array
-            return result;
+            return JSValue::encode(result);
         }
         unsigned pos = 0;
-        while (i != limit && pos < s.size()) {
+        while (i != limit && pos < s.length()) {
             Vector<int, 32> ovector;
-            int mpos = reg->match(s, pos, &ovector);
+            int mpos = reg->match(*globalData, s, pos, &ovector);
             if (mpos < 0)
                 break;
             int mlen = ovector[1] - ovector[0];
@@ -702,30 +746,32 @@ JSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec, JSObject*, JSValue t
         if (u2.isEmpty()) {
             if (s.isEmpty()) {
                 // empty separator matches empty string -> empty array
-                return result;
+                return JSValue::encode(result);
             }
-            while (i != limit && p0 < s.size() - 1)
+            while (i != limit && p0 < s.length() - 1)
                 result->put(exec, i++, jsSingleCharacterSubstring(exec, s, p0++));
         } else {
-            unsigned pos;
-            
-            while (i != limit && (pos = s.find(u2, p0)) != UString::NotFound) {
+            size_t pos;
+            while (i != limit && (pos = s.find(u2, p0)) != notFound) {
                 result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0));
-                p0 = pos + u2.size();
+                p0 = pos + u2.length();
             }
         }
     }
 
     // add remaining string
     if (i != limit)
-        result->put(exec, i++, jsSubstring(exec, s, p0, s.size() - p0));
+        result->put(exec, i++, jsSubstring(exec, s, p0, s.length() - p0));
 
-    return result;
+    return JSValue::encode(result);
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
-{    
-    int len;
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec)
+{
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
+    unsigned len;
     JSString* jsString = 0;
     UString uString;
     if (thisValue.isString()) {
@@ -733,16 +779,16 @@ JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue
         len = jsString->length();
     } else {
         uString = thisValue.toThisObject(exec)->toString(exec);
-        len = uString.size();
+        len = uString.length();
     }
 
-    JSValue a0 = args.at(0);
-    JSValue a1 = args.at(1);
+    JSValue a0 = exec->argument(0);
+    JSValue a1 = exec->argument(1);
 
     double start = a0.toInteger(exec);
     double length = a1.isUndefined() ? len : a1.toInteger(exec);
     if (start >= len || length <= 0)
-        return jsEmptyString(exec);
+        return JSValue::encode(jsEmptyString(exec));
     if (start < 0) {
         start += len;
         if (start < 0)
@@ -750,16 +796,18 @@ JSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec, JSObject*, JSValue
     }
     if (start + length > len)
         length = len - start;
-    
     unsigned substringStart = static_cast<unsigned>(start);
     unsigned substringLength = static_cast<unsigned>(length);
     if (jsString)
-        return jsSubstring(exec, jsString, substringStart, substringLength);
-    return jsSubstring(exec, uString, substringStart, substringLength);
+        return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
+    return JSValue::encode(jsSubstring(exec, uString, substringStart, substringLength));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     int len;
     JSString* jsString = 0;
     UString uString;
@@ -768,28 +816,27 @@ JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSVal
         len = jsString->length();
     } else {
         uString = thisValue.toThisObject(exec)->toString(exec);
-        len = uString.size();
+        len = uString.length();
     }
 
-    JSValue a0 = args.at(0);
-    JSValue a1 = args.at(1);
+    JSValue a0 = exec->argument(0);
+    JSValue a1 = exec->argument(1);
 
     double start = a0.toNumber(exec);
-    double end = a1.toNumber(exec);
-    if (isnan(start))
-        start = 0;
-    if (isnan(end))
-        end = 0;
-    if (start < 0)
+    double end;
+    if (!(start >= 0)) // check for negative values or NaN
         start = 0;
-    if (end < 0)
-        end = 0;
-    if (start > len)
+    else if (start > len)
         start = len;
-    if (end > len)
-        end = len;
     if (a1.isUndefined())
         end = len;
+    else { 
+        end = a1.toNumber(exec);
+        if (!(end >= 0)) // check for negative values or NaN
+            end = 0;
+        else if (end > len)
+            end = len;
+    }
     if (start > end) {
         double temp = end;
         end = start;
@@ -798,20 +845,23 @@ JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSVal
     unsigned substringStart = static_cast<unsigned>(start);
     unsigned substringLength = static_cast<unsigned>(end) - substringStart;
     if (jsString)
-        return jsSubstring(exec, jsString, substringStart, substringLength);
-    return jsSubstring(exec, uString, substringStart, substringLength);
+        return JSValue::encode(jsSubstring(exec, jsString, substringStart, substringLength));
+    return JSValue::encode(jsSubstring(exec, uString, substringStart, substringLength));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     JSString* sVal = thisValue.toThisJSString(exec);
     const UString& s = sVal->value(exec);
 
-    int sSize = s.size();
+    int sSize = s.length();
     if (!sSize)
-        return sVal;
+        return JSValue::encode(sVal);
 
-    const UChar* sData = s.data();
+    const UChar* sData = s.characters();
     Vector<UChar> buffer(sSize);
 
     UChar ored = 0;
@@ -821,7 +871,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSV
         buffer[i] = toASCIILower(c);
     }
     if (!(ored & ~0x7f))
-        return jsString(exec, UString::adopt(buffer));
+        return JSValue::encode(jsString(exec, UString::adopt(buffer)));
 
     bool error;
     int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error);
@@ -829,26 +879,29 @@ JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSV
         buffer.resize(length);
         length = Unicode::toLower(buffer.data(), length, sData, sSize, &error);
         if (error)
-            return sVal;
+            return JSValue::encode(sVal);
     }
     if (length == sSize) {
         if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-            return sVal;
+            return JSValue::encode(sVal);
     } else
         buffer.resize(length);
-    return jsString(exec, UString::adopt(buffer));
+    return JSValue::encode(jsString(exec, UString::adopt(buffer)));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
     JSString* sVal = thisValue.toThisJSString(exec);
     const UString& s = sVal->value(exec);
 
-    int sSize = s.size();
+    int sSize = s.length();
     if (!sSize)
-        return sVal;
+        return JSValue::encode(sVal);
 
-    const UChar* sData = s.data();
+    const UChar* sData = s.characters();
     Vector<UChar> buffer(sSize);
 
     UChar ored = 0;
@@ -858,7 +911,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSV
         buffer[i] = toASCIIUpper(c);
     }
     if (!(ored & ~0x7f))
-        return jsString(exec, UString::adopt(buffer));
+        return JSValue::encode(jsString(exec, UString::adopt(buffer)));
 
     bool error;
     int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error);
@@ -866,100 +919,115 @@ JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSV
         buffer.resize(length);
         length = Unicode::toUpper(buffer.data(), length, sData, sSize, &error);
         if (error)
-            return sVal;
+            return JSValue::encode(sVal);
     }
     if (length == sSize) {
         if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-            return sVal;
+            return JSValue::encode(sVal);
     } else
         buffer.resize(length);
-    return jsString(exec, UString::adopt(buffer));
+    return JSValue::encode(jsString(exec, UString::adopt(buffer)));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec)
 {
-    if (args.size() < 1)
-      return jsNumber(exec, 0);
+    if (exec->argumentCount() < 1)
+      return JSValue::encode(jsNumber(0));
+
+    JSValue thisValue = exec->hostThisValue();
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwVMTypeError(exec);
 
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
-    return jsNumber(exec, localeCompare(s, a0.toString(exec)));
+    JSValue a0 = exec->argument(0);
+    return JSValue::encode(jsNumber(localeCompare(s, a0.toString(exec))));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<big>", s, "</big>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<big>", s, "</big>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<small>", s, "</small>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<small>", s, "</small>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<blink>", s, "</blink>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<blink>", s, "</blink>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<b>", s, "</b>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<b>", s, "</b>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<tt>", s, "</tt>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<tt>", s, "</tt>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<i>", s, "</i>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<i>", s, "</i>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<strike>", s, "</strike>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<strike>", s, "</strike>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<sub>", s, "</sub>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<sub>", s, "</sub>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    return jsMakeNontrivialString(exec, "<sup>", s, "</sup>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<sup>", s, "</sup>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
-    return jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>");
+    JSValue a0 = exec->argument(0);
+    return JSValue::encode(jsMakeNontrivialString(exec, "<font color=\"", a0.toString(exec), "\">", s, "</font>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
+    JSValue a0 = exec->argument(0);
 
     uint32_t smallInteger;
     if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
-        unsigned stringSize = s.size();
+        unsigned stringSize = s.length();
         unsigned bufferSize = 22 + stringSize;
         UChar* buffer;
-        PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer);
+        PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(bufferSize, buffer);
         if (!impl)
-            return jsUndefined();
+            return JSValue::encode(jsUndefined());
         buffer[0] = '<';
         buffer[1] = 'f';
         buffer[2] = 'o';
@@ -975,7 +1043,7 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu
         buffer[12] = '0' + smallInteger;
         buffer[13] = '"';
         buffer[14] = '>';
-        memcpy(&buffer[15], s.data(), stringSize * sizeof(UChar));
+        memcpy(&buffer[15], s.characters(), stringSize * sizeof(UChar));
         buffer[15 + stringSize] = '<';
         buffer[16 + stringSize] = '/';
         buffer[17 + stringSize] = 'f';
@@ -983,32 +1051,34 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu
         buffer[19 + stringSize] = 'n';
         buffer[20 + stringSize] = 't';
         buffer[21 + stringSize] = '>';
-        return jsNontrivialString(exec, impl);
+        return JSValue::encode(jsNontrivialString(exec, impl));
     }
 
-    return jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>");
+    return JSValue::encode(jsMakeNontrivialString(exec, "<font size=\"", a0.toString(exec), "\">", s, "</font>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
-    return jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>");
+    JSValue a0 = exec->argument(0);
+    return JSValue::encode(jsMakeNontrivialString(exec, "<a name=\"", a0.toString(exec), "\">", s, "</a>"));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec)
 {
+    JSValue thisValue = exec->hostThisValue();
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
+    JSValue a0 = exec->argument(0);
     UString linkText = a0.toString(exec);
 
-    unsigned linkTextSize = linkText.size();
-    unsigned stringSize = s.size();
+    unsigned linkTextSize = linkText.length();
+    unsigned stringSize = s.length();
     unsigned bufferSize = 15 + linkTextSize + stringSize;
     UChar* buffer;
-    PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer);
+    PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(bufferSize, buffer);
     if (!impl)
-        return jsUndefined();
+        return JSValue::encode(jsUndefined());
     buffer[0] = '<';
     buffer[1] = 'a';
     buffer[2] = ' ';
@@ -1018,15 +1088,15 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th
     buffer[6] = 'f';
     buffer[7] = '=';
     buffer[8] = '"';
-    memcpy(&buffer[9], linkText.data(), linkTextSize * sizeof(UChar));
+    memcpy(&buffer[9], linkText.characters(), linkTextSize * sizeof(UChar));
     buffer[9 + linkTextSize] = '"';
     buffer[10 + linkTextSize] = '>';
-    memcpy(&buffer[11 + linkTextSize], s.data(), stringSize * sizeof(UChar));
+    memcpy(&buffer[11 + linkTextSize], s.characters(), stringSize * sizeof(UChar));
     buffer[11 + linkTextSize + stringSize] = '<';
     buffer[12 + linkTextSize + stringSize] = '/';
     buffer[13 + linkTextSize + stringSize] = 'a';
     buffer[14 + linkTextSize + stringSize] = '>';
-    return jsNontrivialString(exec, impl);
+    return JSValue::encode(jsNontrivialString(exec, impl));
 }
 
 enum {
@@ -1041,38 +1111,43 @@ static inline bool isTrimWhitespace(UChar c)
 
 static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKind)
 {
+    if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible
+        return throwTypeError(exec);
     UString str = thisValue.toThisString(exec);
     unsigned left = 0;
     if (trimKind & TrimLeft) {
-        while (left < str.size() && isTrimWhitespace(str[left]))
+        while (left < str.length() && isTrimWhitespace(str[left]))
             left++;
     }
-    unsigned right = str.size();
+    unsigned right = str.length();
     if (trimKind & TrimRight) {
         while (right > left && isTrimWhitespace(str[right - 1]))
             right--;
     }
 
     // Don't gc allocate a new string if we don't have to.
-    if (left == 0 && right == str.size() && thisValue.isString())
+    if (left == 0 && right == str.length() && thisValue.isString())
         return thisValue;
 
-    return jsString(exec, str.substr(left, right - left));
+    return jsString(exec, str.substringSharingImpl(left, right - left));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState* exec)
 {
-    return trimString(exec, thisValue, TrimLeft | TrimRight);
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(trimString(exec, thisValue, TrimLeft | TrimRight));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState* exec)
 {
-    return trimString(exec, thisValue, TrimLeft);
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(trimString(exec, thisValue, TrimLeft));
 }
 
-JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&)
+EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState* exec)
 {
-    return trimString(exec, thisValue, TrimRight);
+    JSValue thisValue = exec->hostThisValue();
+    return JSValue::encode(trimString(exec, thisValue, TrimRight));
 }
     
     
index 3a6a2a39076b9fc24d094a5b8ce3dd0aca230a56..6c4b4756413ac270f9f7ea3248013a87e8e1f2a0 100644 (file)
@@ -29,13 +29,23 @@ namespace JSC {
 
     class StringPrototype : public StringObject {
     public:
-        StringPrototype(ExecState*, NonNullPassRefPtr<Structure>);
+        StringPrototype(ExecState*, JSGlobalObject*, Structure*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-        static const ClassInfo info;
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
+        static const ClassInfo s_info;
+        
+    protected:
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags;
+
+        COMPILE_ASSERT(!StringObject::AnonymousSlotCount, StringPrototype_stomps_on_your_anonymous_slot);
+        static const unsigned AnonymousSlotCount = 1;
     };
 
 } // namespace JSC
diff --git a/runtime/StringRecursionChecker.cpp b/runtime/StringRecursionChecker.cpp
new file mode 100644 (file)
index 0000000..4e74735
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "StringRecursionChecker.h"
+
+#include "Error.h"
+#include "ExceptionHelpers.h"
+
+namespace JSC {
+
+EncodedJSValue StringRecursionChecker::throwStackOverflowError()
+{
+    return throwVMError(m_exec, createStackOverflowError(m_exec));
+}
+
+EncodedJSValue StringRecursionChecker::emptyString()
+{
+    return JSValue::encode(jsEmptyString(m_exec));
+}
+
+}
diff --git a/runtime/StringRecursionChecker.h b/runtime/StringRecursionChecker.h
new file mode 100644 (file)
index 0000000..314f14e
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef StringRecursionChecker_h
+#define StringRecursionChecker_h
+
+#include "Interpreter.h"
+
+namespace JSC {
+
+class StringRecursionChecker {
+    WTF_MAKE_NONCOPYABLE(StringRecursionChecker);
+
+public:
+    StringRecursionChecker(ExecState*, JSObject* thisObject);
+    ~StringRecursionChecker();
+
+    EncodedJSValue earlyReturnValue() const; // 0 if everything is OK, value to return for failure cases
+
+private:
+    EncodedJSValue throwStackOverflowError();
+    EncodedJSValue emptyString();
+    EncodedJSValue performCheck();
+
+    ExecState* m_exec;
+    JSObject* m_thisObject;
+    EncodedJSValue m_earlyReturnValue;
+};
+
+inline EncodedJSValue StringRecursionChecker::performCheck()
+{
+    int size = m_exec->globalData().stringRecursionCheckVisitedObjects.size();
+    if (size >= MaxSmallThreadReentryDepth && size >= m_exec->globalData().maxReentryDepth)
+        return throwStackOverflowError();
+    bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).second;
+    if (alreadyVisited)
+        return emptyString(); // Return empty string to avoid infinite recursion.
+    return 0; // Indicate success.
+}
+
+inline StringRecursionChecker::StringRecursionChecker(ExecState* exec, JSObject* thisObject)
+    : m_exec(exec)
+    , m_thisObject(thisObject)
+    , m_earlyReturnValue(performCheck())
+{
+}
+
+inline EncodedJSValue StringRecursionChecker::earlyReturnValue() const
+{
+    return m_earlyReturnValue;
+}
+
+inline StringRecursionChecker::~StringRecursionChecker()
+{
+    if (m_earlyReturnValue)
+        return;
+    ASSERT(m_exec->globalData().stringRecursionCheckVisitedObjects.contains(m_thisObject));
+    m_exec->globalData().stringRecursionCheckVisitedObjects.remove(m_thisObject);
+}
+
+}
+
+#endif
index 6d13f4b98af3d42ae06c24e28633c066085e6427..a3fda547fddb7f850929b2a1229fe6071b3637d0 100644 (file)
 using namespace std;
 using namespace WTF;
 
-namespace JSC {
-
-// Choose a number for the following so that most property maps are smaller,
-// but it's not going to blow out the stack to allocate this number of pointers.
-static const int smallMapThreshold = 1024;
-
-// The point at which the function call overhead of the qsort implementation
-// becomes small compared to the inefficiency of insertion sort.
-static const unsigned tinyMapThreshold = 20;
-
-static const unsigned newTableSize = 16;
+#if DUMP_PROPERTYMAP_STATS
 
-#ifndef NDEBUG
-static WTF::RefCountedLeakCounter structureCounter("Structure");
+int numProbes;
+int numCollisions;
+int numRehashes;
+int numRemoves;
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-static Mutex& ignoreSetMutex = *(new Mutex);
 #endif
 
-static bool shouldIgnoreLeaks;
-static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>);
-#endif
+namespace JSC {
 
 #if DUMP_STRUCTURE_ID_STATISTICS
 static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>);
 #endif
 
-static int comparePropertyMapEntryIndices(const void* a, const void* b);
-
-inline void Structure::setTransitionTable(TransitionTable* table)
-{
-    ASSERT(m_isUsingSingleSlot);
-#ifndef NDEBUG
-    setSingleTransition(0);
-#endif
-    m_isUsingSingleSlot = false;
-    m_transitions.m_table = table;
-    // This implicitly clears the flag that indicates we're using a single transition
-    ASSERT(!m_isUsingSingleSlot);
-}
-
-// The contains and get methods accept imprecise matches, so if an unspecialised transition exists
-// for the given key they will consider that transition to be a match.  If a specialised transition
-// exists and it matches the provided specificValue, get will return the specific transition.
-inline bool Structure::transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
-{
-    if (m_isUsingSingleSlot) {
-        Structure* existingTransition = singleTransition();
-        return existingTransition && existingTransition->m_nameInPrevious.get() == key.first
-               && existingTransition->m_attributesInPrevious == key.second
-               && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0);
-    }
-    TransitionTable::iterator find = transitionTable()->find(key);
-    if (find == transitionTable()->end())
-        return false;
-
-    return find->second.first || find->second.second->transitionedFor(specificValue);
-}
-
-inline Structure* Structure::transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const
+bool StructureTransitionTable::contains(StringImpl* rep, unsigned attributes) const
 {
-    if (m_isUsingSingleSlot) {
-        Structure* existingTransition = singleTransition();
-        if (existingTransition && existingTransition->m_nameInPrevious.get() == key.first
-            && existingTransition->m_attributesInPrevious == key.second
-            && (existingTransition->m_specificValueInPrevious == specificValue || existingTransition->m_specificValueInPrevious == 0))
-            return existingTransition;
-        return 0;
+    if (isUsingSingleSlot()) {
+        Structure* transition = singleTransition();
+        return transition && transition->m_nameInPrevious == rep && transition->m_attributesInPrevious == attributes;
     }
-
-    Transition transition = transitionTable()->get(key);
-    if (transition.second && transition.second->transitionedFor(specificValue))
-        return transition.second;
-    return transition.first;
+    return map()->contains(make_pair(rep, attributes));
 }
 
-inline bool Structure::transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const
+inline Structure* StructureTransitionTable::get(StringImpl* rep, unsigned attributes) const
 {
-    if (m_isUsingSingleSlot) {
+    if (isUsingSingleSlot()) {
         Structure* transition = singleTransition();
-        return transition && transition->m_nameInPrevious == key.first
-        && transition->m_attributesInPrevious == key.second;
+        return (transition && transition->m_nameInPrevious == rep && transition->m_attributesInPrevious == attributes) ? transition : 0;
     }
-    return transitionTable()->contains(key);
+    return map()->get(make_pair(rep, attributes));
 }
 
-inline void Structure::transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue)
+inline void StructureTransitionTable::remove(Structure* structure)
 {
-    if (m_isUsingSingleSlot) {
-        ASSERT(transitionTableContains(key, specificValue));
-        setSingleTransition(0);
-        return;
+    if (isUsingSingleSlot()) {
+        // If more than one transition had been added, then we wouldn't be in
+        // single slot mode (even despecifying a from a specific value triggers
+        // map mode).
+        // As such, the passed structure *must* be the existing transition.
+        ASSERT(singleTransition() == structure);
+        clearSingleTransition();
+    } else {
+        // Check whether a mapping exists for structure's key, and whether the
+        // entry is structure (the latter check may fail if we initially had a
+        // transition with a specific value, and this has been despecified).
+
+        // Newer versions of the STL have an std::make_pair function that takes rvalue references.
+        // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
+        // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details
+        TransitionMap::iterator entry = map()->find(make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious));
+        if (entry != map()->end() && structure == entry.get().second)
+            map()->remove(entry);
     }
-    TransitionTable::iterator find = transitionTable()->find(key);
-    if (!specificValue)
-        find->second.first = 0;
-    else
-        find->second.second = 0;
-    if (!find->second.first && !find->second.second)
-        transitionTable()->remove(find);
 }
 
-inline void Structure::transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue)
+inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* structure)
 {
-    if (m_isUsingSingleSlot) {
-        if (!singleTransition()) {
-            setSingleTransition(structure);
+    if (isUsingSingleSlot()) {
+        Structure* existingTransition = singleTransition();
+
+        // This handles the first transition being added.
+        if (!existingTransition) {
+            setSingleTransition(globalData, structure);
             return;
         }
-        Structure* existingTransition = singleTransition();
-        TransitionTable* transitionTable = new TransitionTable;
-        setTransitionTable(transitionTable);
-        if (existingTransition)
-            transitionTableAdd(std::make_pair(existingTransition->m_nameInPrevious.get(), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious);
+
+        // This handles the second transition being added
+        // (or the first transition being despecified!)
+        setMap(new TransitionMap());
+        add(globalData, existingTransition);
     }
-    if (!specificValue) {
-        TransitionTable::iterator find = transitionTable()->find(key);
-        if (find == transitionTable()->end())
-            transitionTable()->add(key, Transition(structure, static_cast<Structure*>(0)));
-        else
-            find->second.first = structure;
-    } else {
-        // If we're adding a transition to a specific value, then there cannot be
-        // an existing transition
-        ASSERT(!transitionTable()->contains(key));
-        transitionTable()->add(key, Transition(static_cast<Structure*>(0), structure));
+
+    // Add the structure to the map.
+
+    // Newer versions of the STL have an std::make_pair function that takes rvalue references.
+    // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
+    // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details
+    std::pair<TransitionMap::iterator, bool> result = map()->add(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure);
+    if (!result.second) {
+        // There already is an entry! - we should only hit this when despecifying.
+        ASSERT(result.first.get().second->m_specificValueInPrevious);
+        ASSERT(!structure->m_specificValueInPrevious);
+        map()->set(result.first, structure);
     }
 }
 
@@ -191,21 +149,22 @@ void Structure::dumpStatistics()
     HashSet<Structure*>::const_iterator end = liveStructureSet.end();
     for (HashSet<Structure*>::const_iterator it = liveStructureSet.begin(); it != end; ++it) {
         Structure* structure = *it;
-        if (structure->m_usingSingleTransitionSlot) {
-            if (!structure->m_transitions.singleTransition)
+
+        switch (structure->m_transitionTable.size()) {
+            case 0:
                 ++numberLeaf;
-            else
-                ++numberUsingSingleSlot;
+               if (!structure->m_previous)
+                    ++numberSingletons;
+                break;
 
-           if (!structure->m_previous && !structure->m_transitions.singleTransition)
-                ++numberSingletons;
+            case 1:
+                ++numberUsingSingleSlot;
+                break;
         }
 
         if (structure->m_propertyTable) {
             ++numberWithPropertyMaps;
-            totalPropertyMapsSize += PropertyMapHashTable::allocationSize(structure->m_propertyTable->size);
-            if (structure->m_propertyTable->deletedOffsets)
-                totalPropertyMapsSize += (structure->m_propertyTable->deletedOffsets->capacity() * sizeof(unsigned)); 
+            totalPropertyMapsSize += structure->m_propertyTable->sizeInMemory();
         }
     }
 
@@ -223,133 +182,79 @@ void Structure::dumpStatistics()
 #endif
 }
 
-Structure::Structure(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
-    : m_typeInfo(typeInfo)
-    , m_prototype(prototype)
-    , m_specificValueInPrevious(0)
-    , m_propertyTable(0)
-    , m_propertyStorageCapacity(JSObject::inlineStorageCapacity)
+Structure::Structure(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
+    : JSCell(globalData, globalData.structureStructure.get())
+    , m_typeInfo(typeInfo)
+    , m_prototype(globalData, this, prototype)
+    , m_classInfo(classInfo)
+    , m_propertyStorageCapacity(typeInfo.isFinal() ? JSFinalObject_inlineStorageCapacity : JSNonFinalObject_inlineStorageCapacity)
     , m_offset(noOffset)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(false)
+    , m_hasNonEnumerableProperties(false)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(0)
     , m_anonymousSlotCount(anonymousSlotCount)
-    , m_isUsingSingleSlot(true)
+    , m_preventExtensions(false)
+    , m_didTransition(false)
 {
-    m_transitions.m_singleTransition = 0;
-
     ASSERT(m_prototype);
     ASSERT(m_prototype.isObject() || m_prototype.isNull());
-
-#ifndef NDEBUG
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    MutexLocker protect(ignoreSetMutex);
-#endif
-    if (shouldIgnoreLeaks)
-        ignoreSet.add(this);
-    else
-        structureCounter.increment();
-#endif
-
-#if DUMP_STRUCTURE_ID_STATISTICS
-    liveStructureSet.add(this);
-#endif
-}
-
-Structure::~Structure()
-{
-    if (m_previous) {
-        ASSERT(m_nameInPrevious);
-        m_previous->transitionTableRemove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious);
-
-    }
-    ASSERT(!m_enumerationCache.hasDeadObject());
-
-    if (m_propertyTable) {
-        unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
-        for (unsigned i = 1; i <= entryCount; i++) {
-            if (UString::Rep* key = m_propertyTable->entries()[i].key)
-                key->deref();
-        }
-
-        delete m_propertyTable->deletedOffsets;
-        fastFree(m_propertyTable);
-    }
-
-    if (!m_isUsingSingleSlot)
-        delete transitionTable();
-
-#ifndef NDEBUG
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    MutexLocker protect(ignoreSetMutex);
-#endif
-    HashSet<Structure*>::iterator it = ignoreSet.find(this);
-    if (it != ignoreSet.end())
-        ignoreSet.remove(it);
-    else
-        structureCounter.decrement();
-#endif
-
-#if DUMP_STRUCTURE_ID_STATISTICS
-    liveStructureSet.remove(this);
-#endif
-}
-
-void Structure::startIgnoringLeaks()
-{
-#ifndef NDEBUG
-    shouldIgnoreLeaks = true;
-#endif
 }
 
-void Structure::stopIgnoringLeaks()
-{
-#ifndef NDEBUG
-    shouldIgnoreLeaks = false;
-#endif
-}
+const ClassInfo Structure::s_info = { "Structure", 0, 0, 0 };
 
-static bool isPowerOf2(unsigned v)
+Structure::Structure(JSGlobalData& globalData)
+    : JSCell(globalData, this, CreatingEarlyCell)
+    , m_typeInfo(CompoundType, OverridesVisitChildren)
+    , m_prototype(globalData, this, jsNull())
+    , m_classInfo(&s_info)
+    , m_propertyStorageCapacity(0)
+    , m_offset(noOffset)
+    , m_dictionaryKind(NoneDictionaryKind)
+    , m_isPinnedPropertyTable(false)
+    , m_hasGetterSetterProperties(false)
+    , m_hasNonEnumerableProperties(false)
+    , m_attributesInPrevious(0)
+    , m_specificFunctionThrashCount(0)
+    , m_anonymousSlotCount(0)
+    , m_preventExtensions(false)
+    , m_didTransition(false)
 {
-    // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
-    
-    return !(v & (v - 1)) && v;
+    ASSERT(m_prototype);
+    ASSERT(m_prototype.isNull());
+    ASSERT(!globalData.structureStructure);
 }
 
-static unsigned nextPowerOf2(unsigned v)
+Structure::Structure(JSGlobalData& globalData, const Structure* previous)
+    : JSCell(globalData, globalData.structureStructure.get())
+    , m_typeInfo(previous->typeInfo())
+    , m_prototype(globalData, this, previous->storedPrototype())
+    , m_classInfo(previous->m_classInfo)
+    , m_propertyStorageCapacity(previous->m_propertyStorageCapacity)
+    , m_offset(noOffset)
+    , m_dictionaryKind(NoneDictionaryKind)
+    , m_isPinnedPropertyTable(false)
+    , m_hasGetterSetterProperties(previous->m_hasGetterSetterProperties)
+    , m_hasNonEnumerableProperties(previous->m_hasNonEnumerableProperties)
+    , m_attributesInPrevious(0)
+    , m_specificFunctionThrashCount(previous->m_specificFunctionThrashCount)
+    , m_anonymousSlotCount(previous->anonymousSlotCount())
+    , m_preventExtensions(previous->m_preventExtensions)
+    , m_didTransition(true)
 {
-    // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html
-    // Devised by Sean Anderson, Sepember 14, 2001
-
-    v--;
-    v |= v >> 1;
-    v |= v >> 2;
-    v |= v >> 4;
-    v |= v >> 8;
-    v |= v >> 16;
-    v++;
-
-    return v;
+    ASSERT(m_prototype);
+    ASSERT(m_prototype.isObject() || m_prototype.isNull());
 }
 
-static unsigned sizeForKeyCount(size_t keyCount)
+Structure::~Structure()
 {
-    if (keyCount == notFound)
-        return newTableSize;
-
-    if (keyCount < 8)
-        return newTableSize;
-
-    if (isPowerOf2(keyCount))
-        return keyCount * 4;
-
-    return nextPowerOf2(keyCount) * 2;
 }
 
-void Structure::materializePropertyMap()
+void Structure::materializePropertyMap(JSGlobalData& globalData)
 {
+    ASSERT(structure()->classInfo() == &s_info);
     ASSERT(!m_propertyTable);
 
     Vector<Structure*, 8> structures;
@@ -357,13 +262,13 @@ void Structure::materializePropertyMap()
 
     Structure* structure = this;
 
-    // Search for the last Structure with a property table. 
+    // Search for the last Structure with a property table.
     while ((structure = structure->previousID())) {
         if (structure->m_isPinnedPropertyTable) {
             ASSERT(structure->m_propertyTable);
             ASSERT(!structure->m_previous);
 
-            m_propertyTable = structure->copyPropertyTable();
+            m_propertyTable = structure->m_propertyTable->copy(globalData, 0, m_offset + 1);
             break;
         }
 
@@ -371,80 +276,46 @@ void Structure::materializePropertyMap()
     }
 
     if (!m_propertyTable)
-        createPropertyMapHashTable(sizeForKeyCount(m_offset + 1));
-    else {
-        if (sizeForKeyCount(m_offset + 1) > m_propertyTable->size)
-            rehashPropertyMapHashTable(sizeForKeyCount(m_offset + 1)); // This could be made more efficient by combining with the copy above. 
-    }
+        createPropertyMap(m_offset + 1);
 
     for (ptrdiff_t i = structures.size() - 2; i >= 0; --i) {
         structure = structures[i];
-        structure->m_nameInPrevious->ref();
-        PropertyMapEntry entry(structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious, ++m_propertyTable->lastIndexUsed);
-        insertIntoPropertyMapHashTable(entry);
+        PropertyMapEntry entry(globalData, this, structure->m_nameInPrevious.get(), m_anonymousSlotCount + structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
+        m_propertyTable->add(entry);
     }
 }
 
 void Structure::growPropertyStorageCapacity()
 {
-    if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
-        m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
+    if (isUsingInlineStorage())
+        m_propertyStorageCapacity = JSObject::baseExternalStorageCapacity;
     else
         m_propertyStorageCapacity *= 2;
 }
 
-void Structure::despecifyDictionaryFunction(const Identifier& propertyName)
+void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName)
 {
-    const UString::Rep* rep = propertyName._ustring.rep();
+    StringImpl* rep = propertyName.impl();
 
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
 
     ASSERT(isDictionary());
     ASSERT(m_propertyTable);
 
-    unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numProbes;
-#endif
-
-    unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-    ASSERT(entryIndex != emptyEntryIndex);
-
-    if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
-        m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
-        return;
-    }
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numCollisions;
-#endif
-
-    unsigned k = 1 | doubleHash(rep->existingHash());
-
-    while (1) {
-        i += k;
-
-#if DUMP_PROPERTYMAP_STATS
-        ++numRehashes;
-#endif
-
-        entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        ASSERT(entryIndex != emptyEntryIndex);
-
-        if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
-            m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
-            return;
-        }
-    }
+    PropertyMapEntry* entry = m_propertyTable->find(rep).first;
+    ASSERT(entry);
+    entry->specificValue.clear();
 }
 
-PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
+Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
 {
     ASSERT(!structure->isDictionary());
     ASSERT(structure->typeInfo().type() == ObjectType);
 
-    if (Structure* existingTransition = structure->transitionTableGet(make_pair(propertyName.ustring().rep(), attributes), specificValue)) {
+    if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.impl(), attributes)) {
+        JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get();
+        if (specificValueInPrevious && specificValueInPrevious != specificValue)
+            return 0;
         ASSERT(existingTransition->m_offset != noOffset);
         offset = existingTransition->m_offset + existingTransition->m_anonymousSlotCount;
         ASSERT(offset >= structure->m_anonymousSlotCount);
@@ -455,8 +326,18 @@ PassRefPtr<Structure> Structure::addPropertyTransitionToExistingStructure(Struct
     return 0;
 }
 
-PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
+Structure* Structure::addPropertyTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset)
 {
+    // If we have a specific function, we may have got to this point if there is
+    // already a transition with the correct property name and attributes, but
+    // specialized to a different function.  In this case we just want to give up
+    // and despecialize the transition.
+    // In this case we clear the value of specificFunction which will result
+    // in us adding a non-specific transition, and any subsequent lookup in
+    // Structure::addPropertyTransitionToExistingStructure will just use that.
+    if (specificValue && structure->m_transitionTable.contains(propertyName.impl(), attributes))
+        specificValue = 0;
+
     ASSERT(!structure->isDictionary());
     ASSERT(structure->typeInfo().type() == ObjectType);
     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
@@ -465,43 +346,37 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
         specificValue = 0;
 
     if (structure->transitionCount() > s_maxTransitionLength) {
-        RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
+        Structure* transition = toCacheableDictionaryTransition(globalData, structure);
         ASSERT(structure != transition);
-        offset = transition->put(propertyName, attributes, specificValue);
+        offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
         ASSERT(offset >= structure->m_anonymousSlotCount);
         ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
         if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
             transition->growPropertyStorageCapacity();
-        return transition.release();
+        return transition;
     }
 
-    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
+    Structure* transition = create(globalData, structure);
 
-    transition->m_cachedPrototypeChain = structure->m_cachedPrototypeChain;
-    transition->m_previous = structure;
-    transition->m_nameInPrevious = propertyName.ustring().rep();
+    transition->m_cachedPrototypeChain.setMayBeNull(globalData, transition, structure->m_cachedPrototypeChain.get());
+    transition->m_previous.set(globalData, transition, structure);
+    transition->m_nameInPrevious = propertyName.impl();
     transition->m_attributesInPrevious = attributes;
-    transition->m_specificValueInPrevious = specificValue;
-    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
-    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
-    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
-    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
+    transition->m_specificValueInPrevious.setMayBeNull(globalData, transition, specificValue);
 
     if (structure->m_propertyTable) {
         if (structure->m_isPinnedPropertyTable)
-            transition->m_propertyTable = structure->copyPropertyTable();
-        else {
-            transition->m_propertyTable = structure->m_propertyTable;
-            structure->m_propertyTable = 0;
-        }
+            transition->m_propertyTable = structure->m_propertyTable->copy(globalData, 0, structure->m_propertyTable->size() + 1);
+        else
+            transition->m_propertyTable = structure->m_propertyTable.release();
     } else {
         if (structure->m_previous)
-            transition->materializePropertyMap();
+            transition->materializePropertyMap(globalData);
         else
-            transition->createPropertyMapHashTable();
+            transition->createPropertyMap();
     }
 
-    offset = transition->put(propertyName, attributes, specificValue);
+    offset = transition->putSpecificValue(globalData, propertyName, attributes, specificValue);
     ASSERT(offset >= structure->m_anonymousSlotCount);
     ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
     if (transition->propertyStorageSize() > transition->propertyStorageCapacity())
@@ -509,183 +384,235 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con
 
     transition->m_offset = offset - structure->m_anonymousSlotCount;
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
-    structure->transitionTableAdd(make_pair(propertyName.ustring().rep(), attributes), transition.get(), specificValue);
-    return transition.release();
+    structure->m_transitionTable.add(globalData, transition);
+    return transition;
 }
 
-PassRefPtr<Structure> Structure::removePropertyTransition(Structure* structure, const Identifier& propertyName, size_t& offset)
+Structure* Structure::removePropertyTransition(JSGlobalData& globalData, Structure* structure, const Identifier& propertyName, size_t& offset)
 {
     ASSERT(!structure->isUncacheableDictionary());
 
-    RefPtr<Structure> transition = toUncacheableDictionaryTransition(structure);
+    Structure* transition = toUncacheableDictionaryTransition(globalData, structure);
 
     offset = transition->remove(propertyName);
     ASSERT(offset >= structure->m_anonymousSlotCount);
     ASSERT(structure->m_anonymousSlotCount == transition->m_anonymousSlotCount);
 
-    return transition.release();
+    return transition;
 }
 
-PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, JSValue prototype)
+Structure* Structure::changePrototypeTransition(JSGlobalData& globalData, Structure* structure, JSValue prototype)
 {
-    RefPtr<Structure> transition = create(prototype, structure->typeInfo(), structure->anonymousSlotCount());
+    Structure* transition = create(globalData, structure);
 
-    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
-    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
-    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
-    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
+    transition->m_prototype.set(globalData, transition, prototype);
 
     // Don't set m_offset, as one can not transition to this.
 
-    structure->materializePropertyMapIfNecessary();
-    transition->m_propertyTable = structure->copyPropertyTable();
+    structure->materializePropertyMapIfNecessary(globalData);
+    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
     transition->m_isPinnedPropertyTable = true;
     
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
-    return transition.release();
+    return transition;
 }
 
-PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction)
+Structure* Structure::despecifyFunctionTransition(JSGlobalData& globalData, Structure* structure, const Identifier& replaceFunction)
 {
     ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount);
-    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
+    Structure* transition = create(globalData, structure);
 
-    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
-    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
-    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
-    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount + 1;
+    ++transition->m_specificFunctionThrashCount;
 
     // Don't set m_offset, as one can not transition to this.
 
-    structure->materializePropertyMapIfNecessary();
-    transition->m_propertyTable = structure->copyPropertyTable();
+    structure->materializePropertyMapIfNecessary(globalData);
+    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
     transition->m_isPinnedPropertyTable = true;
 
     if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
-        transition->despecifyAllFunctions();
+        transition->despecifyAllFunctions(globalData);
     else {
-        bool removed = transition->despecifyFunction(replaceFunction);
+        bool removed = transition->despecifyFunction(globalData, replaceFunction);
         ASSERT_UNUSED(removed, removed);
     }
     
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
-    return transition.release();
+    return transition;
 }
 
-PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure)
+Structure* Structure::getterSetterTransition(JSGlobalData& globalData, Structure* structure)
 {
-    RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo(), structure->anonymousSlotCount());
-    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
-    transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties;
-    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
-    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
+    Structure* transition = create(globalData, structure);
 
     // Don't set m_offset, as one can not transition to this.
 
-    structure->materializePropertyMapIfNecessary();
-    transition->m_propertyTable = structure->copyPropertyTable();
+    structure->materializePropertyMapIfNecessary(globalData);
+    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
     transition->m_isPinnedPropertyTable = true;
     
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
-    return transition.release();
+    return transition;
 }
 
-PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, DictionaryKind kind)
+Structure* Structure::toDictionaryTransition(JSGlobalData& globalData, Structure* structure, DictionaryKind kind)
 {
     ASSERT(!structure->isUncacheableDictionary());
     
-    RefPtr<Structure> transition = create(structure->m_prototype, structure->typeInfo(), structure->anonymousSlotCount());
+    Structure* transition = create(globalData, structure);
+
+    structure->materializePropertyMapIfNecessary(globalData);
+    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
+    transition->m_isPinnedPropertyTable = true;
     transition->m_dictionaryKind = kind;
-    transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity;
-    transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties;
-    transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties;
-    transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount;
     
-    structure->materializePropertyMapIfNecessary();
-    transition->m_propertyTable = structure->copyPropertyTable();
+    ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
+    return transition;
+}
+
+Structure* Structure::toCacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure)
+{
+    return toDictionaryTransition(globalData, structure, CachedDictionaryKind);
+}
+
+Structure* Structure::toUncacheableDictionaryTransition(JSGlobalData& globalData, Structure* structure)
+{
+    return toDictionaryTransition(globalData, structure, UncachedDictionaryKind);
+}
+
+// In future we may want to cache this transition.
+Structure* Structure::sealTransition(JSGlobalData& globalData, Structure* structure)
+{
+    Structure* transition = preventExtensionsTransition(globalData, structure);
+
+    if (transition->m_propertyTable) {
+        PropertyTable::iterator end = transition->m_propertyTable->end();
+        for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
+            iter->attributes |= DontDelete;
+    }
+
+    return transition;
+}
+
+// In future we may want to cache this transition.
+Structure* Structure::freezeTransition(JSGlobalData& globalData, Structure* structure)
+{
+    Structure* transition = preventExtensionsTransition(globalData, structure);
+
+    if (transition->m_propertyTable) {
+        PropertyTable::iterator end = transition->m_propertyTable->end();
+        for (PropertyTable::iterator iter = transition->m_propertyTable->begin(); iter != end; ++iter)
+            iter->attributes |= (DontDelete | ReadOnly);
+    }
+
+    return transition;
+}
+
+// In future we may want to cache this transition.
+Structure* Structure::preventExtensionsTransition(JSGlobalData& globalData, Structure* structure)
+{
+    Structure* transition = create(globalData, structure);
+
+    // Don't set m_offset, as one can not transition to this.
+
+    structure->materializePropertyMapIfNecessary(globalData);
+    transition->m_propertyTable = structure->copyPropertyTable(globalData, transition);
     transition->m_isPinnedPropertyTable = true;
-    
+    transition->m_preventExtensions = true;
+
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
-    return transition.release();
+    return transition;
 }
 
-PassRefPtr<Structure> Structure::toCacheableDictionaryTransition(Structure* structure)
+// In future we may want to cache this property.
+bool Structure::isSealed(JSGlobalData& globalData)
 {
-    return toDictionaryTransition(structure, CachedDictionaryKind);
+    if (isExtensible())
+        return false;
+
+    materializePropertyMapIfNecessary(globalData);
+    if (!m_propertyTable)
+        return true;
+
+    PropertyTable::iterator end = m_propertyTable->end();
+    for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+        if ((iter->attributes & DontDelete) != DontDelete)
+            return false;
+    }
+    return true;
 }
 
-PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* structure)
+// In future we may want to cache this property.
+bool Structure::isFrozen(JSGlobalData& globalData)
 {
-    return toDictionaryTransition(structure, UncachedDictionaryKind);
+    if (isExtensible())
+        return false;
+
+    materializePropertyMapIfNecessary(globalData);
+    if (!m_propertyTable)
+        return true;
+
+    PropertyTable::iterator end = m_propertyTable->end();
+    for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+        if ((iter->attributes & (DontDelete | ReadOnly)) != (DontDelete | ReadOnly))
+            return false;
+    }
+    return true;
 }
 
-PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object)
+Structure* Structure::flattenDictionaryStructure(JSGlobalData& globalData, JSObject* object)
 {
     ASSERT(isDictionary());
     if (isUncacheableDictionary()) {
         ASSERT(m_propertyTable);
-        Vector<PropertyMapEntry*> sortedPropertyEntries(m_propertyTable->keyCount);
-        PropertyMapEntry** p = sortedPropertyEntries.data();
-        unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
-        for (unsigned i = 1; i <= entryCount; i++) {
-            if (m_propertyTable->entries()[i].key)
-                *p++ = &m_propertyTable->entries()[i];
-        }
-        size_t propertyCount = p - sortedPropertyEntries.data();
-        qsort(sortedPropertyEntries.data(), propertyCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
-        sortedPropertyEntries.resize(propertyCount);
 
-        // We now have the properties currently defined on this object
-        // in the order that they are expected to be in, but we need to
-        // reorder the storage, so we have to copy the current values out
-        Vector<JSValue> values(propertyCount);
         unsigned anonymousSlotCount = m_anonymousSlotCount;
-        for (unsigned i = 0; i < propertyCount; i++) {
-            PropertyMapEntry* entry = sortedPropertyEntries[i];
-            values[i] = object->getDirectOffset(entry->offset);
+        size_t propertyCount = m_propertyTable->size();
+        Vector<JSValue> values(propertyCount);
+
+        unsigned i = 0;
+        PropertyTable::iterator end = m_propertyTable->end();
+        for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter, ++i) {
+            values[i] = object->getDirectOffset(iter->offset);
             // Update property table to have the new property offsets
-            entry->offset = anonymousSlotCount + i;
-            entry->index = i;
+            iter->offset = anonymousSlotCount + i;
         }
         
         // Copy the original property values into their final locations
         for (unsigned i = 0; i < propertyCount; i++)
-            object->putDirectOffset(anonymousSlotCount + i, values[i]);
+            object->putDirectOffset(globalData, anonymousSlotCount + i, values[i]);
 
-        if (m_propertyTable->deletedOffsets) {
-            delete m_propertyTable->deletedOffsets;
-            m_propertyTable->deletedOffsets = 0;
-        }
+        m_propertyTable->clearDeletedOffsets();
     }
 
     m_dictionaryKind = NoneDictionaryKind;
     return this;
 }
 
-size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
+size_t Structure::addPropertyWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
 {
     ASSERT(!m_enumerationCache);
 
     if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         specificValue = 0;
 
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
 
     m_isPinnedPropertyTable = true;
 
-    size_t offset = put(propertyName, attributes, specificValue);
+    size_t offset = putSpecificValue(globalData, propertyName, attributes, specificValue);
     ASSERT(offset >= m_anonymousSlotCount);
     if (propertyStorageSize() > propertyStorageCapacity())
         growPropertyStorageCapacity();
     return offset;
 }
 
-size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName)
+size_t Structure::removePropertyWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName)
 {
     ASSERT(isUncacheableDictionary());
     ASSERT(!m_enumerationCache);
 
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
 
     m_isPinnedPropertyTable = true;
     size_t offset = remove(propertyName);
@@ -695,11 +622,6 @@ size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName
 
 #if DUMP_PROPERTYMAP_STATS
 
-static int numProbes;
-static int numCollisions;
-static int numRehashes;
-static int numRemoves;
-
 struct PropertyMapStatisticsExitLogger {
     ~PropertyMapStatisticsExitLogger();
 };
@@ -717,8 +639,6 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
 
 #endif
 
-static const unsigned deletedSentinelIndex = 1;
-
 #if !DO_PROPERTYMAP_CONSTENCY_CHECK
 
 inline void Structure::checkConsistency()
@@ -727,532 +647,208 @@ inline void Structure::checkConsistency()
 
 #endif
 
-PropertyMapHashTable* Structure::copyPropertyTable()
+PassOwnPtr<PropertyTable> Structure::copyPropertyTable(JSGlobalData& globalData, Structure* owner)
 {
-    if (!m_propertyTable)
-        return 0;
-
-    size_t tableSize = PropertyMapHashTable::allocationSize(m_propertyTable->size);
-    PropertyMapHashTable* newTable = static_cast<PropertyMapHashTable*>(fastMalloc(tableSize));
-    memcpy(newTable, m_propertyTable, tableSize);
-
-    unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
-    for (unsigned i = 1; i <= entryCount; ++i) {
-        if (UString::Rep* key = newTable->entries()[i].key)
-            key->ref();
-    }
-
-    // Copy the deletedOffsets vector.
-    if (m_propertyTable->deletedOffsets)
-        newTable->deletedOffsets = new Vector<unsigned>(*m_propertyTable->deletedOffsets);
-
-    return newTable;
+    return adoptPtr(m_propertyTable ? new PropertyTable(globalData, owner, *m_propertyTable) : 0);
 }
 
-size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue)
+size_t Structure::get(JSGlobalData& globalData, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue)
 {
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
     if (!m_propertyTable)
-        return notFound;
-
-    unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numProbes;
-#endif
-
-    unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-    if (entryIndex == emptyEntryIndex)
-        return notFound;
-
-    if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
-        attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
-        specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
-        ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
-        return m_propertyTable->entries()[entryIndex - 1].offset;
-    }
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numCollisions;
-#endif
-
-    unsigned k = 1 | doubleHash(rep->existingHash());
-
-    while (1) {
-        i += k;
+        return WTF::notFound;
 
-#if DUMP_PROPERTYMAP_STATS
-        ++numRehashes;
-#endif
-
-        entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        if (entryIndex == emptyEntryIndex)
-            return notFound;
+    PropertyMapEntry* entry = m_propertyTable->find(propertyName).first;
+    if (!entry)
+        return WTF::notFound;
 
-        if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
-            attributes = m_propertyTable->entries()[entryIndex - 1].attributes;
-            specificValue = m_propertyTable->entries()[entryIndex - 1].specificValue;
-            ASSERT(m_propertyTable->entries()[entryIndex - 1].offset >= m_anonymousSlotCount);
-            return m_propertyTable->entries()[entryIndex - 1].offset;
-        }
-    }
+    attributes = entry->attributes;
+    specificValue = entry->specificValue.get();
+    ASSERT(entry->offset >= m_anonymousSlotCount);
+    return entry->offset;
 }
 
-bool Structure::despecifyFunction(const Identifier& propertyName)
+bool Structure::despecifyFunction(JSGlobalData& globalData, const Identifier& propertyName)
 {
-    ASSERT(!propertyName.isNull());
-
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
     if (!m_propertyTable)
         return false;
 
-    UString::Rep* rep = propertyName._ustring.rep();
-
-    unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numProbes;
-#endif
-
-    unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-    if (entryIndex == emptyEntryIndex)
+    ASSERT(!propertyName.isNull());
+    PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
+    if (!entry)
         return false;
 
-    if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
-        ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
-        m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
-        return true;
-    }
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numCollisions;
-#endif
-
-    unsigned k = 1 | doubleHash(rep->existingHash());
-
-    while (1) {
-        i += k;
-
-#if DUMP_PROPERTYMAP_STATS
-        ++numRehashes;
-#endif
-
-        entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        if (entryIndex == emptyEntryIndex)
-            return false;
-
-        if (rep == m_propertyTable->entries()[entryIndex - 1].key) {
-            ASSERT(m_propertyTable->entries()[entryIndex - 1].specificValue);
-            m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
-            return true;
-        }
-    }
+    ASSERT(entry->specificValue);
+    entry->specificValue.clear();
+    return true;
 }
 
-void Structure::despecifyAllFunctions()
+void Structure::despecifyAllFunctions(JSGlobalData& globalData)
 {
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
     if (!m_propertyTable)
         return;
-    
-    unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
-    for (unsigned i = 1; i <= entryCount; ++i)
-        m_propertyTable->entries()[i].specificValue = 0;
+
+    PropertyTable::iterator end = m_propertyTable->end();
+    for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter)
+        iter->specificValue.clear();
 }
 
-size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
+size_t Structure::putSpecificValue(JSGlobalData& globalData, const Identifier& propertyName, unsigned attributes, JSCell* specificValue)
 {
     ASSERT(!propertyName.isNull());
-    ASSERT(get(propertyName) == notFound);
+    ASSERT(get(globalData, propertyName) == notFound);
 
     checkConsistency();
-
     if (attributes & DontEnum)
         m_hasNonEnumerableProperties = true;
 
-    UString::Rep* rep = propertyName._ustring.rep();
+    StringImpl* rep = propertyName.impl();
 
     if (!m_propertyTable)
-        createPropertyMapHashTable();
-
-    // FIXME: Consider a fast case for tables with no deleted sentinels.
-
-    unsigned i = rep->existingHash();
-    unsigned k = 0;
-    bool foundDeletedElement = false;
-    unsigned deletedElementIndex = 0; // initialize to make the compiler happy
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numProbes;
-#endif
-
-    while (1) {
-        unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        if (entryIndex == emptyEntryIndex)
-            break;
-
-        if (entryIndex == deletedSentinelIndex) {
-            // If we find a deleted-element sentinel, remember it for use later.
-            if (!foundDeletedElement) {
-                foundDeletedElement = true;
-                deletedElementIndex = i;
-            }
-        }
-
-        if (k == 0) {
-            k = 1 | doubleHash(rep->existingHash());
-#if DUMP_PROPERTYMAP_STATS
-            ++numCollisions;
-#endif
-        }
-
-        i += k;
-
-#if DUMP_PROPERTYMAP_STATS
-        ++numRehashes;
-#endif
-    }
-
-    // Figure out which entry to use.
-    unsigned entryIndex = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount + 2;
-    if (foundDeletedElement) {
-        i = deletedElementIndex;
-        --m_propertyTable->deletedSentinelCount;
-
-        // Since we're not making the table bigger, we can't use the entry one past
-        // the end that we were planning on using, so search backwards for the empty
-        // slot that we can use. We know it will be there because we did at least one
-        // deletion in the past that left an entry empty.
-        while (m_propertyTable->entries()[--entryIndex - 1].key) { }
-    }
-
-    // Create a new hash table entry.
-    m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
-
-    // Create a new hash table entry.
-    rep->ref();
-    m_propertyTable->entries()[entryIndex - 1].key = rep;
-    m_propertyTable->entries()[entryIndex - 1].attributes = attributes;
-    m_propertyTable->entries()[entryIndex - 1].specificValue = specificValue;
-    m_propertyTable->entries()[entryIndex - 1].index = ++m_propertyTable->lastIndexUsed;
+        createPropertyMap();
 
     unsigned newOffset;
-    if (m_propertyTable->deletedOffsets && !m_propertyTable->deletedOffsets->isEmpty()) {
-        newOffset = m_propertyTable->deletedOffsets->last();
-        m_propertyTable->deletedOffsets->removeLast();
-    } else
-        newOffset = m_propertyTable->keyCount + m_anonymousSlotCount;
-    m_propertyTable->entries()[entryIndex - 1].offset = newOffset;
-    
+
+    if (m_propertyTable->hasDeletedOffset())
+        newOffset = m_propertyTable->getDeletedOffset();
+    else
+        newOffset = m_propertyTable->size() + m_anonymousSlotCount;
     ASSERT(newOffset >= m_anonymousSlotCount);
-    ++m_propertyTable->keyCount;
 
-    if ((m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount) * 2 >= m_propertyTable->size)
-        expandPropertyMapHashTable();
+    m_propertyTable->add(PropertyMapEntry(globalData, this, rep, newOffset, attributes, specificValue));
 
     checkConsistency();
     return newOffset;
 }
 
-bool Structure::hasTransition(UString::Rep* rep, unsigned attributes)
-{
-    return transitionTableHasTransition(make_pair(rep, attributes));
-}
-
 size_t Structure::remove(const Identifier& propertyName)
 {
     ASSERT(!propertyName.isNull());
 
     checkConsistency();
 
-    UString::Rep* rep = propertyName._ustring.rep();
+    StringImpl* rep = propertyName.impl();
 
     if (!m_propertyTable)
         return notFound;
 
-#if DUMP_PROPERTYMAP_STATS
-    ++numProbes;
-    ++numRemoves;
-#endif
-
-    // Find the thing to remove.
-    unsigned i = rep->existingHash();
-    unsigned k = 0;
-    unsigned entryIndex;
-    UString::Rep* key = 0;
-    while (1) {
-        entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        if (entryIndex == emptyEntryIndex)
-            return notFound;
-
-        key = m_propertyTable->entries()[entryIndex - 1].key;
-        if (rep == key)
-            break;
-
-        if (k == 0) {
-            k = 1 | doubleHash(rep->existingHash());
-#if DUMP_PROPERTYMAP_STATS
-            ++numCollisions;
-#endif
-        }
-
-        i += k;
-
-#if DUMP_PROPERTYMAP_STATS
-        ++numRehashes;
-#endif
-    }
-
-    // Replace this one element with the deleted sentinel. Also clear out
-    // the entry so we can iterate all the entries as needed.
-    m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = deletedSentinelIndex;
+    PropertyTable::find_iterator position = m_propertyTable->find(rep);
+    if (!position.first)
+        return notFound;
 
-    size_t offset = m_propertyTable->entries()[entryIndex - 1].offset;
+    size_t offset = position.first->offset;
     ASSERT(offset >= m_anonymousSlotCount);
 
-    key->deref();
-    m_propertyTable->entries()[entryIndex - 1].key = 0;
-    m_propertyTable->entries()[entryIndex - 1].attributes = 0;
-    m_propertyTable->entries()[entryIndex - 1].specificValue = 0;
-    m_propertyTable->entries()[entryIndex - 1].offset = 0;
-
-    if (!m_propertyTable->deletedOffsets)
-        m_propertyTable->deletedOffsets = new Vector<unsigned>;
-    m_propertyTable->deletedOffsets->append(offset);
-
-    ASSERT(m_propertyTable->keyCount >= 1);
-    --m_propertyTable->keyCount;
-    ++m_propertyTable->deletedSentinelCount;
-
-    if (m_propertyTable->deletedSentinelCount * 4 >= m_propertyTable->size)
-        rehashPropertyMapHashTable();
+    m_propertyTable->remove(position);
+    m_propertyTable->addDeletedOffset(offset);
 
     checkConsistency();
     return offset;
 }
 
-void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry)
-{
-    ASSERT(m_propertyTable);
-    ASSERT(entry.offset >= m_anonymousSlotCount);
-    unsigned i = entry.key->existingHash();
-    unsigned k = 0;
-
-#if DUMP_PROPERTYMAP_STATS
-    ++numProbes;
-#endif
-
-    while (1) {
-        unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        if (entryIndex == emptyEntryIndex)
-            break;
-
-        if (k == 0) {
-            k = 1 | doubleHash(entry.key->existingHash());
-#if DUMP_PROPERTYMAP_STATS
-            ++numCollisions;
-#endif
-        }
-
-        i += k;
-
-#if DUMP_PROPERTYMAP_STATS
-        ++numRehashes;
-#endif
-    }
-
-    unsigned entryIndex = m_propertyTable->keyCount + 2;
-    m_propertyTable->entryIndices[i & m_propertyTable->sizeMask] = entryIndex;
-    m_propertyTable->entries()[entryIndex - 1] = entry;
-
-    ++m_propertyTable->keyCount;
-}
-
-void Structure::createPropertyMapHashTable()
-{
-    ASSERT(sizeForKeyCount(7) == newTableSize);
-    createPropertyMapHashTable(newTableSize);
-}
-
-void Structure::createPropertyMapHashTable(unsigned newTableSize)
+void Structure::createPropertyMap(unsigned capacity)
 {
     ASSERT(!m_propertyTable);
-    ASSERT(isPowerOf2(newTableSize));
 
     checkConsistency();
-
-    m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
-    m_propertyTable->size = newTableSize;
-    m_propertyTable->sizeMask = newTableSize - 1;
-
+    m_propertyTable = adoptPtr(new PropertyTable(capacity));
     checkConsistency();
 }
 
-void Structure::expandPropertyMapHashTable()
-{
-    ASSERT(m_propertyTable);
-    rehashPropertyMapHashTable(m_propertyTable->size * 2);
-}
-
-void Structure::rehashPropertyMapHashTable()
-{
-    ASSERT(m_propertyTable);
-    ASSERT(m_propertyTable->size);
-    rehashPropertyMapHashTable(m_propertyTable->size);
-}
-
-void Structure::rehashPropertyMapHashTable(unsigned newTableSize)
+void Structure::getPropertyNames(JSGlobalData& globalData, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
-    ASSERT(m_propertyTable);
-    ASSERT(isPowerOf2(newTableSize));
-
-    checkConsistency();
-
-    PropertyMapHashTable* oldTable = m_propertyTable;
+    materializePropertyMapIfNecessary(globalData);
+    if (!m_propertyTable)
+        return;
 
-    m_propertyTable = static_cast<PropertyMapHashTable*>(fastZeroedMalloc(PropertyMapHashTable::allocationSize(newTableSize)));
-    m_propertyTable->size = newTableSize;
-    m_propertyTable->sizeMask = newTableSize - 1;
+    bool knownUnique = !propertyNames.size();
 
-    unsigned lastIndexUsed = 0;
-    unsigned entryCount = oldTable->keyCount + oldTable->deletedSentinelCount;
-    for (unsigned i = 1; i <= entryCount; ++i) {
-        if (oldTable->entries()[i].key) {
-            lastIndexUsed = max(oldTable->entries()[i].index, lastIndexUsed);
-            insertIntoPropertyMapHashTable(oldTable->entries()[i]);
+    PropertyTable::iterator end = m_propertyTable->end();
+    for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+        ASSERT(m_hasNonEnumerableProperties || !(iter->attributes & DontEnum));
+        if (!(iter->attributes & DontEnum) || (mode == IncludeDontEnumProperties)) {
+            if (knownUnique)
+                propertyNames.addKnownUnique(iter->key);
+            else
+                propertyNames.add(iter->key);
         }
     }
-    m_propertyTable->lastIndexUsed = lastIndexUsed;
-    m_propertyTable->deletedOffsets = oldTable->deletedOffsets;
-
-    fastFree(oldTable);
-
-    checkConsistency();
-}
-
-int comparePropertyMapEntryIndices(const void* a, const void* b)
-{
-    unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index;
-    unsigned ib = static_cast<PropertyMapEntry* const*>(b)[0]->index;
-    if (ia < ib)
-        return -1;
-    if (ia > ib)
-        return +1;
-    return 0;
 }
 
-void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMode mode)
+void Structure::visitChildren(SlotVisitor& visitor)
 {
-    materializePropertyMapIfNecessary();
-    if (!m_propertyTable)
-        return;
-
-    if (m_propertyTable->keyCount < tinyMapThreshold) {
-        PropertyMapEntry* a[tinyMapThreshold];
-        int i = 0;
-        unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
-        for (unsigned k = 1; k <= entryCount; k++) {
-            ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[k].attributes & DontEnum));
-            if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || (mode == IncludeDontEnumProperties))) {
-                PropertyMapEntry* value = &m_propertyTable->entries()[k];
-                int j;
-                for (j = i - 1; j >= 0 && a[j]->index > value->index; --j)
-                    a[j + 1] = a[j];
-                a[j + 1] = value;
-                ++i;
-            }
-        }
-        if (!propertyNames.size()) {
-            for (int k = 0; k < i; ++k)
-                propertyNames.addKnownUnique(a[k]->key);
-        } else {
-            for (int k = 0; k < i; ++k)
-                propertyNames.add(a[k]->key);
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    JSCell::visitChildren(visitor);
+    if (m_prototype)
+        visitor.append(&m_prototype);
+    if (m_cachedPrototypeChain)
+        visitor.append(&m_cachedPrototypeChain);
+    if (m_previous)
+        visitor.append(&m_previous);
+    if (m_specificValueInPrevious)
+        visitor.append(&m_specificValueInPrevious);
+    if (m_enumerationCache)
+        visitor.append(&m_enumerationCache);
+    if (m_propertyTable) {
+        PropertyTable::iterator end = m_propertyTable->end();
+        for (PropertyTable::iterator ptr = m_propertyTable->begin(); ptr != end; ++ptr) {
+            if (ptr->specificValue)
+                visitor.append(&ptr->specificValue);
         }
-
-        return;
-    }
-
-    // Allocate a buffer to use to sort the keys.
-    Vector<PropertyMapEntry*, smallMapThreshold> sortedEnumerables(m_propertyTable->keyCount);
-
-    // Get pointers to the enumerable entries in the buffer.
-    PropertyMapEntry** p = sortedEnumerables.data();
-    unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount;
-    for (unsigned i = 1; i <= entryCount; i++) {
-        if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || (mode == IncludeDontEnumProperties)))
-            *p++ = &m_propertyTable->entries()[i];
-    }
-
-    size_t enumerableCount = p - sortedEnumerables.data();
-    // Sort the entries by index.
-    qsort(sortedEnumerables.data(), enumerableCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices);
-    sortedEnumerables.resize(enumerableCount);
-
-    // Put the keys of the sorted entries into the list.
-    if (!propertyNames.size()) {
-        for (size_t i = 0; i < sortedEnumerables.size(); ++i)
-            propertyNames.addKnownUnique(sortedEnumerables[i]->key);
-    } else {
-        for (size_t i = 0; i < sortedEnumerables.size(); ++i)
-            propertyNames.add(sortedEnumerables[i]->key);
     }
 }
 
 #if DO_PROPERTYMAP_CONSTENCY_CHECK
 
-void Structure::checkConsistency()
+void PropertyTable::checkConsistency()
 {
-    if (!m_propertyTable)
-        return;
-
-    ASSERT(m_propertyTable->size >= newTableSize);
-    ASSERT(m_propertyTable->sizeMask);
-    ASSERT(m_propertyTable->size == m_propertyTable->sizeMask + 1);
-    ASSERT(!(m_propertyTable->size & m_propertyTable->sizeMask));
-
-    ASSERT(m_propertyTable->keyCount <= m_propertyTable->size / 2);
-    ASSERT(m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 4);
+    ASSERT(m_indexSize >= PropertyTable::MinimumTableSize);
+    ASSERT(m_indexMask);
+    ASSERT(m_indexSize == m_indexMask + 1);
+    ASSERT(!(m_indexSize & m_indexMask));
 
-    ASSERT(m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount <= m_propertyTable->size / 2);
+    ASSERT(m_keyCount <= m_indexSize / 2);
+    ASSERT(m_keyCount + m_deletedCount <= m_indexSize / 2);
+    ASSERT(m_deletedCount <= m_indexSize / 4);
 
     unsigned indexCount = 0;
     unsigned deletedIndexCount = 0;
-    for (unsigned a = 0; a != m_propertyTable->size; ++a) {
-        unsigned entryIndex = m_propertyTable->entryIndices[a];
-        if (entryIndex == emptyEntryIndex)
+    for (unsigned a = 0; a != m_indexSize; ++a) {
+        unsigned entryIndex = m_index[a];
+        if (entryIndex == PropertyTable::EmptyEntryIndex)
             continue;
-        if (entryIndex == deletedSentinelIndex) {
+        if (entryIndex == deletedEntryIndex()) {
             ++deletedIndexCount;
             continue;
         }
-        ASSERT(entryIndex > deletedSentinelIndex);
-        ASSERT(entryIndex - 1 <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount);
+        ASSERT(entryIndex < deletedEntryIndex());
+        ASSERT(entryIndex - 1 <= usedCount());
         ++indexCount;
 
-        for (unsigned b = a + 1; b != m_propertyTable->size; ++b)
-            ASSERT(m_propertyTable->entryIndices[b] != entryIndex);
+        for (unsigned b = a + 1; b != m_indexSize; ++b)
+            ASSERT(m_index[b] != entryIndex);
     }
-    ASSERT(indexCount == m_propertyTable->keyCount);
-    ASSERT(deletedIndexCount == m_propertyTable->deletedSentinelCount);
+    ASSERT(indexCount == m_keyCount);
+    ASSERT(deletedIndexCount == m_deletedCount);
 
-    ASSERT(m_propertyTable->entries()[0].key == 0);
+    ASSERT(!table()[deletedEntryIndex() - 1].key);
 
     unsigned nonEmptyEntryCount = 0;
-    for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) {
-        ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum));
-        UString::Rep* rep = m_propertyTable->entries()[c].key;
-        ASSERT(m_propertyTable->entries()[c].offset >= m_anonymousSlotCount);
-        if (!rep)
+    for (unsigned c = 0; c < usedCount(); ++c) {
+        StringImpl* rep = table()[c].key;
+        if (rep == PROPERTY_MAP_DELETED_ENTRY_KEY)
             continue;
         ++nonEmptyEntryCount;
         unsigned i = rep->existingHash();
         unsigned k = 0;
         unsigned entryIndex;
         while (1) {
-            entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-            ASSERT(entryIndex != emptyEntryIndex);
-            if (rep == m_propertyTable->entries()[entryIndex - 1].key)
+            entryIndex = m_index[i & m_indexMask];
+            ASSERT(entryIndex != PropertyTable::EmptyEntryIndex);
+            if (rep == table()[entryIndex - 1].key)
                 break;
             if (k == 0)
                 k = 1 | doubleHash(rep->existingHash());
@@ -1261,7 +857,23 @@ void Structure::checkConsistency()
         ASSERT(entryIndex == c + 1);
     }
 
-    ASSERT(nonEmptyEntryCount == m_propertyTable->keyCount);
+    ASSERT(nonEmptyEntryCount == m_keyCount);
+}
+
+void Structure::checkConsistency()
+{
+    if (!m_propertyTable)
+        return;
+
+    if (!m_hasNonEnumerableProperties) {
+        PropertyTable::iterator end = m_propertyTable->end();
+        for (PropertyTable::iterator iter = m_propertyTable->begin(); iter != end; ++iter) {
+            ASSERT(!(iter->attributes & DontEnum));
+            ASSERT(iter->offset >= m_anonymousSlotCount);
+        }
+    }
+
+    m_propertyTable->checkConsistency();
 }
 
 #endif // DO_PROPERTYMAP_CONSTENCY_CHECK
index 968443a828d1b2e8e7f2e58465f5109e5afe84d9..f71d23c12bc46bd6ff13a45b833f5ec26524b3fd 100644 (file)
 #define Structure_h
 
 #include "Identifier.h"
+#include "JSCell.h"
 #include "JSType.h"
 #include "JSValue.h"
 #include "PropertyMapHashTable.h"
 #include "PropertyNameArray.h"
 #include "Protect.h"
-#include "StructureChain.h"
 #include "StructureTransitionTable.h"
 #include "JSTypeInfo.h"
 #include "UString.h"
-#include "WeakGCPtr.h"
+#include "Weak.h"
+#include <wtf/PassOwnPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 
-#ifndef NDEBUG
-#define DUMP_PROPERTYMAP_STATS 0
-#else
-#define DUMP_PROPERTYMAP_STATS 0
-#endif
 
 namespace JSC {
 
     class MarkStack;
     class PropertyNameArray;
     class PropertyNameArrayData;
+    class StructureChain;
+    typedef MarkStack SlotVisitor;
+
+    struct ClassInfo;
 
     enum EnumerationMode {
         ExcludeDontEnumProperties,
         IncludeDontEnumProperties
     };
 
-    class Structure : public RefCounted<Structure> {
+    class Structure : public JSCell {
     public:
-        friend class JIT;
         friend class StructureTransitionTable;
-        static PassRefPtr<Structure> create(JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount)
+        static Structure* create(JSGlobalData& globalData, JSValue prototype, const TypeInfo& typeInfo, unsigned anonymousSlotCount, const ClassInfo* classInfo)
         {
-            return adoptRef(new Structure(prototype, typeInfo, anonymousSlotCount));
+            ASSERT(globalData.structureStructure);
+            ASSERT(classInfo);
+            return new (&globalData) Structure(globalData, prototype, typeInfo, anonymousSlotCount, classInfo);
         }
 
-        static void startIgnoringLeaks();
-        static void stopIgnoringLeaks();
-
         static void dumpStatistics();
 
-        static PassRefPtr<Structure> addPropertyTransition(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
-        static PassRefPtr<Structure> addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
-        static PassRefPtr<Structure> removePropertyTransition(Structure*, const Identifier& propertyName, size_t& offset);
-        static PassRefPtr<Structure> changePrototypeTransition(Structure*, JSValue prototype);
-        static PassRefPtr<Structure> despecifyFunctionTransition(Structure*, const Identifier&);
-        static PassRefPtr<Structure> getterSetterTransition(Structure*);
-        static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*);
-        static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*);
-
-        PassRefPtr<Structure> flattenDictionaryStructure(JSObject*);
+        static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+        static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset);
+        static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset);
+        static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype);
+        static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&);
+        static Structure* getterSetterTransition(JSGlobalData&, Structure*);
+        static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*);
+        static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*);
+        static Structure* sealTransition(JSGlobalData&, Structure*);
+        static Structure* freezeTransition(JSGlobalData&, Structure*);
+        static Structure* preventExtensionsTransition(JSGlobalData&, Structure*);
+
+        bool isSealed(JSGlobalData&);
+        bool isFrozen(JSGlobalData&);
+        bool isExtensible() const { return !m_preventExtensions; }
+        bool didTransition() const { return m_didTransition; }
+
+        Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*);
 
         ~Structure();
 
         // These should be used with caution.  
-        size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
-        size_t removePropertyWithoutTransition(const Identifier& propertyName);
-        void setPrototypeWithoutTransition(JSValue prototype) { m_prototype = prototype; }
+        size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
+        size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName);
+        void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); }
         
         bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; }
         bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; }
 
-        const TypeInfo& typeInfo() const { return m_typeInfo; }
+        const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; }
 
-        JSValue storedPrototype() const { return m_prototype; }
+        JSValue storedPrototype() const { return m_prototype.get(); }
         JSValue prototypeForLookup(ExecState*) const;
         StructureChain* prototypeChain(ExecState*) const;
+        void visitChildren(SlotVisitor&);
 
-        Structure* previousID() const { return m_previous.get(); }
+        Structure* previousID() const { ASSERT(structure()->classInfo() == &s_info); return m_previous.get(); }
 
         void growPropertyStorageCapacity();
-        unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; }
-        unsigned propertyStorageSize() const { return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->keyCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : static_cast<unsigned>(m_offset + 1)); }
+        unsigned propertyStorageCapacity() const { ASSERT(structure()->classInfo() == &s_info); return m_propertyStorageCapacity; }
+        unsigned propertyStorageSize() const { ASSERT(structure()->classInfo() == &s_info); return m_anonymousSlotCount + (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast<unsigned>(m_offset + 1)); }
         bool isUsingInlineStorage() const;
 
-        size_t get(const Identifier& propertyName);
-        size_t get(const UString::Rep* rep, unsigned& attributes, JSCell*& specificValue);
-        size_t get(const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
+        size_t get(JSGlobalData&, const Identifier& propertyName);
+        size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue);
+        size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue)
         {
             ASSERT(!propertyName.isNull());
-            return get(propertyName.ustring().rep(), attributes, specificValue);
-        }
-        bool transitionedFor(const JSCell* specificValue)
-        {
-            return m_specificValueInPrevious == specificValue;
-        }
-        bool hasTransition(UString::Rep*, unsigned attributes);
-        bool hasTransition(const Identifier& propertyName, unsigned attributes)
-        {
-            return hasTransition(propertyName._ustring.rep(), attributes);
+            ASSERT(structure()->classInfo() == &s_info);
+            return get(globalData, propertyName.impl(), attributes, specificValue);
         }
 
         bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
@@ -130,48 +129,74 @@ namespace JSC {
         bool hasAnonymousSlots() const { return !!m_anonymousSlotCount; }
         unsigned anonymousSlotCount() const { return m_anonymousSlotCount; }
         
-        bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; }
+        bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; }
 
-        void despecifyDictionaryFunction(const Identifier& propertyName);
+        void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName);
         void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; }
 
-        void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
-        void clearEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
+        void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
         JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
-        void getPropertyNames(PropertyNameArray&, EnumerationMode mode);
+        void getPropertyNames(JSGlobalData&, PropertyNameArray&, EnumerationMode mode);
+
+        const ClassInfo* classInfo() const { return m_classInfo; }
+
+        static ptrdiff_t prototypeOffset()
+        {
+            return OBJECT_OFFSETOF(Structure, m_prototype);
+        }
+
+        static ptrdiff_t typeInfoFlagsOffset()
+        {
+            return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset();
+        }
+
+        static ptrdiff_t typeInfoTypeOffset()
+        {
+            return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
+        }
+
+        static Structure* createStructure(JSGlobalData& globalData)
+        {
+            ASSERT(!globalData.structureStructure);
+            return new (&globalData) Structure(globalData);
+        }
         
+        static JS_EXPORTDATA const ClassInfo s_info;
+
     private:
+        Structure(JSGlobalData&, JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount, const ClassInfo*);
+        Structure(JSGlobalData&);
+        Structure(JSGlobalData&, const Structure*);
 
-        Structure(JSValue prototype, const TypeInfo&, unsigned anonymousSlotCount);
+        static Structure* create(JSGlobalData& globalData, const Structure* structure)
+        {
+            ASSERT(globalData.structureStructure);
+            return new (&globalData) Structure(globalData, structure);
+        }
         
         typedef enum { 
             NoneDictionaryKind = 0,
             CachedDictionaryKind = 1,
             UncachedDictionaryKind = 2
         } DictionaryKind;
-        static PassRefPtr<Structure> toDictionaryTransition(Structure*, DictionaryKind);
+        static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind);
 
-        size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
+        size_t putSpecificValue(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue);
         size_t remove(const Identifier& propertyName);
 
-        void expandPropertyMapHashTable();
-        void rehashPropertyMapHashTable();
-        void rehashPropertyMapHashTable(unsigned newTableSize);
-        void createPropertyMapHashTable();
-        void createPropertyMapHashTable(unsigned newTableSize);
-        void insertIntoPropertyMapHashTable(const PropertyMapEntry&);
+        void createPropertyMap(unsigned keyCount = 0);
         void checkConsistency();
 
-        bool despecifyFunction(const Identifier&);
-        void despecifyAllFunctions();
+        bool despecifyFunction(JSGlobalData&, const Identifier&);
+        void despecifyAllFunctions(JSGlobalData&);
 
-        PropertyMapHashTable* copyPropertyTable();
-        void materializePropertyMap();
-        void materializePropertyMapIfNecessary()
+        PassOwnPtr<PropertyTable> copyPropertyTable(JSGlobalData&, Structure* owner);
+        void materializePropertyMap(JSGlobalData&);
+        void materializePropertyMapIfNecessary(JSGlobalData& globalData)
         {
-            if (m_propertyTable || !m_previous)             
-                return;
-            materializePropertyMap();
+            ASSERT(structure()->classInfo() == &s_info);
+            if (!m_propertyTable && m_previous)
+                materializePropertyMap(globalData);
         }
 
         signed char transitionCount() const
@@ -180,24 +205,8 @@ namespace JSC {
             return m_offset == noOffset ? 0 : m_offset + 1;
         }
 
-        typedef std::pair<Structure*, Structure*> Transition;
-        typedef HashMap<StructureTransitionTableHash::Key, Transition, StructureTransitionTableHash, StructureTransitionTableHashTraits> TransitionTable;
-
-        inline bool transitionTableContains(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
-        inline void transitionTableRemove(const StructureTransitionTableHash::Key& key, JSCell* specificValue);
-        inline void transitionTableAdd(const StructureTransitionTableHash::Key& key, Structure* structure, JSCell* specificValue);
-        inline bool transitionTableHasTransition(const StructureTransitionTableHash::Key& key) const;
-        inline Structure* transitionTableGet(const StructureTransitionTableHash::Key& key, JSCell* specificValue) const;
-
-        TransitionTable* transitionTable() const { ASSERT(!m_isUsingSingleSlot); return m_transitions.m_table; }
-        inline void setTransitionTable(TransitionTable* table);
-        Structure* singleTransition() const { ASSERT(m_isUsingSingleSlot); return m_transitions.m_singleTransition; }
-        void setSingleTransition(Structure* structure) { ASSERT(m_isUsingSingleSlot); m_transitions.m_singleTransition = structure; }
-        
         bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
 
-        static const unsigned emptyEntryIndex = 0;
-    
         static const signed char s_maxTransitionLength = 64;
 
         static const signed char noOffset = -1;
@@ -206,22 +215,20 @@ namespace JSC {
 
         TypeInfo m_typeInfo;
 
-        JSValue m_prototype;
-        mutable RefPtr<StructureChain> m_cachedPrototypeChain;
+        WriteBarrier<Unknown> m_prototype;
+        mutable WriteBarrier<StructureChain> m_cachedPrototypeChain;
 
-        RefPtr<Structure> m_previous;
-        RefPtr<UString::Rep> m_nameInPrevious;
-        JSCell* m_specificValueInPrevious;
+        WriteBarrier<Structure> m_previous;
+        RefPtr<StringImpl> m_nameInPrevious;
+        WriteBarrier<JSCell> m_specificValueInPrevious;
 
-        // 'm_isUsingSingleSlot' indicates whether we are using the single transition optimisation.
-        union {
-            TransitionTable* m_table;
-            Structure* m_singleTransition;
-        } m_transitions;
+        const ClassInfo* m_classInfo;
 
-        WeakGCPtr<JSPropertyNameIterator> m_enumerationCache;
+        StructureTransitionTable m_transitionTable;
 
-        PropertyMapHashTable* m_propertyTable;
+        WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
+
+        OwnPtr<PropertyTable> m_propertyTable;
 
         uint32_t m_propertyStorageCapacity;
 
@@ -242,53 +249,70 @@ namespace JSC {
 #endif
         unsigned m_specificFunctionThrashCount : 2;
         unsigned m_anonymousSlotCount : 5;
-        unsigned m_isUsingSingleSlot : 1;
-        // 4 free bits
+        unsigned m_preventExtensions : 1;
+        unsigned m_didTransition : 1;
+        // 3 free bits
     };
 
-    inline size_t Structure::get(const Identifier& propertyName)
+    inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName)
     {
-        ASSERT(!propertyName.isNull());
-
-        materializePropertyMapIfNecessary();
+        ASSERT(structure()->classInfo() == &s_info);
+        materializePropertyMapIfNecessary(globalData);
         if (!m_propertyTable)
-            return WTF::notFound;
+            return notFound;
 
-        UString::Rep* rep = propertyName._ustring.rep();
-
-        unsigned i = rep->existingHash();
-
-#if DUMP_PROPERTYMAP_STATS
-        ++numProbes;
-#endif
+        PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first;
+        ASSERT(!entry || entry->offset >= m_anonymousSlotCount);
+        return entry ? entry->offset : notFound;
+    }
 
-        unsigned entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-        if (entryIndex == emptyEntryIndex)
-            return WTF::notFound;
+    inline bool JSCell::isObject() const
+    {
+        return m_structure->typeInfo().type() == ObjectType;
+    }
 
-        if (rep == m_propertyTable->entries()[entryIndex - 1].key)
-            return m_propertyTable->entries()[entryIndex - 1].offset;
+    inline bool JSCell::isString() const
+    {
+        return m_structure->typeInfo().type() == StringType;
+    }
 
-#if DUMP_PROPERTYMAP_STATS
-        ++numCollisions;
+    inline const ClassInfo* JSCell::classInfo() const
+    {
+#if ENABLE(GC_VALIDATION)
+        return m_structure.unvalidatedGet()->classInfo();
+#else
+        return m_structure->classInfo();
 #endif
+    }
 
-        unsigned k = 1 | WTF::doubleHash(rep->existingHash());
-
-        while (1) {
-            i += k;
+    inline Structure* JSCell::createDummyStructure(JSGlobalData& globalData)
+    {
+        return Structure::create(globalData, jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount, &s_dummyCellInfo);
+    }
 
-#if DUMP_PROPERTYMAP_STATS
-            ++numRehashes;
-#endif
+    inline bool JSValue::needsThisConversion() const
+    {
+        if (UNLIKELY(!isCell()))
+            return true;
+        return asCell()->structure()->typeInfo().needsThisConversion();
+    }
 
-            entryIndex = m_propertyTable->entryIndices[i & m_propertyTable->sizeMask];
-            if (entryIndex == emptyEntryIndex)
-                return WTF::notFound;
+    ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell)
+    {
+        ASSERT(!m_isCheckingForDefaultMarkViolation);
+        ASSERT(cell);
+        if (Heap::testAndSetMarked(cell))
+            return;
+        if (cell->structure() && cell->structure()->typeInfo().type() >= CompoundType)
+            m_values.append(cell);
+    }
 
-            if (rep == m_propertyTable->entries()[entryIndex - 1].key)
-                return m_propertyTable->entries()[entryIndex - 1].offset;
-        }
+    inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure)
+    {
+        // Newer versions of the STL have an std::make_pair function that takes rvalue references.
+        // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue.
+        // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details.
+        return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious);
     }
 
 } // namespace JSC
index 085876c496b54ea5d5f0a072b1f07fd88677e65d..89a0ec0c2067b4696fa31e269b597d7c6b99baff 100644 (file)
 #include <wtf/RefPtr.h>
 
 namespace JSC {
+    
+ClassInfo StructureChain::s_info = { "StructureChain", 0, 0, 0 };
 
-StructureChain::StructureChain(Structure* head)
+StructureChain::StructureChain(JSGlobalData& globalData, Structure* structure, Structure* head)
+    : JSCell(globalData, structure)
 {
     size_t size = 0;
     for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
         ++size;
     
-    m_vector.set(new RefPtr<Structure>[size + 1]);
+    m_vector = adoptArrayPtr(new WriteBarrier<Structure>[size + 1]);
 
     size_t i = 0;
     for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure())
-        m_vector[i++] = current;
-    m_vector[i] = 0;
+        m_vector[i++].set(globalData, this, current);
+    m_vector[i].clear();
+}
+
+StructureChain::~StructureChain()
+{
+}
+
+void StructureChain::visitChildren(SlotVisitor& visitor)
+{
+    ASSERT_GC_OBJECT_INHERITS(this, &s_info);
+    ASSERT(structure()->typeInfo().overridesVisitChildren());
+    size_t i = 0;
+    while (m_vector[i])
+        visitor.append(&m_vector[i++]);
 }
 
 } // namespace JSC
index 816b66d5051550bceb2b4efa27e51419e2d9a33f..4fc1212bc7a28eda127fcc939360b4000290fbb8 100644 (file)
@@ -26,6 +26,9 @@
 #ifndef StructureChain_h
 #define StructureChain_h
 
+#include "JSCell.h"
+#include "Structure.h"
+
 #include <wtf/OwnArrayPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
@@ -35,17 +38,22 @@ namespace JSC {
 
     class Structure;
 
-    class StructureChain : public RefCounted<StructureChain> {
+    class StructureChain : public JSCell {
         friend class JIT;
 
     public:
-        static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); }
-        RefPtr<Structure>* head() { return m_vector.get(); }
+        static StructureChain* create(JSGlobalData& globalData, Structure* head) { return new (&globalData) StructureChain(globalData, globalData.structureChainStructure.get(), head); }
+        WriteBarrier<Structure>* head() { return m_vector.get(); }
+        void visitChildren(SlotVisitor&);
 
-    private:
-        StructureChain(Structure* head);
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { return Structure::create(globalData, prototype, TypeInfo(CompoundType, OverridesVisitChildren), 0, &s_info); }
+        
+        static ClassInfo s_info;
 
-        OwnArrayPtr<RefPtr<Structure> > m_vector;
+    private:
+        StructureChain(JSGlobalData&, Structure*, Structure* head);
+        ~StructureChain();
+        OwnArrayPtr<WriteBarrier<Structure> > m_vector;
     };
 
 } // namespace JSC
index d1dc2d9c645499c9981203f5f8528b38265a6552..adebad28480c24db39a5015da6cdad4add0747d3 100644 (file)
 #define StructureTransitionTable_h
 
 #include "UString.h"
+#include "WeakGCMap.h"
 #include <wtf/HashFunctions.h>
-#include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 
-    class Structure;
+class Structure;
 
-    struct StructureTransitionTableHash {
-        typedef std::pair<RefPtr<UString::Rep>, unsigned> Key;
+class StructureTransitionTable {
+    static const intptr_t UsingSingleSlotFlag = 1;
+
+    struct Hash {
+        typedef std::pair<RefPtr<StringImpl>, unsigned> Key;
         static unsigned hash(const Key& p)
         {
             return p.first->existingHash();
@@ -52,8 +55,8 @@ namespace JSC {
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
 
-    struct StructureTransitionTableHashTraits {
-        typedef WTF::HashTraits<RefPtr<UString::Rep> > FirstTraits;
+    struct HashTraits {
+        typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
         typedef WTF::GenericHashTraits<unsigned> SecondTraits;
         typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
 
@@ -66,6 +69,105 @@ namespace JSC {
         static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
     };
 
+    struct WeakGCMapFinalizerCallback {
+        static void* finalizerContextFor(Hash::Key)
+        {
+            return 0;
+        }
+
+        static inline Hash::Key keyForFinalizer(void* context, Structure* structure)
+        {
+            return keyForWeakGCMapFinalizer(context, structure);
+        }
+    };
+
+    typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
+
+    static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
+
+public:
+    StructureTransitionTable()
+        : m_data(UsingSingleSlotFlag)
+    {
+    }
+
+    ~StructureTransitionTable()
+    {
+        if (!isUsingSingleSlot())
+            delete map();
+        else
+            clearSingleTransition();
+    }
+
+    inline void add(JSGlobalData&, Structure*);
+    inline void remove(Structure*);
+    inline bool contains(StringImpl* rep, unsigned attributes) const;
+    inline Structure* get(StringImpl* rep, unsigned attributes) const;
+
+private:
+    bool isUsingSingleSlot() const
+    {
+        return m_data & UsingSingleSlotFlag;
+    }
+
+    TransitionMap* map() const
+    {
+        ASSERT(!isUsingSingleSlot());
+        return reinterpret_cast<TransitionMap*>(m_data);
+    }
+
+    HandleSlot slot() const
+    {
+        ASSERT(isUsingSingleSlot());
+        return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
+    }
+
+    void setMap(TransitionMap* map)
+    {
+        ASSERT(isUsingSingleSlot());
+        
+        if (HandleSlot slot = this->slot())
+            HandleHeap::heapFor(slot)->deallocate(slot);
+
+        // This implicitly clears the flag that indicates we're using a single transition
+        m_data = reinterpret_cast<intptr_t>(map);
+
+        ASSERT(!isUsingSingleSlot());
+    }
+
+    Structure* singleTransition() const
+    {
+        ASSERT(isUsingSingleSlot());
+        if (HandleSlot slot = this->slot()) {
+            if (*slot)
+                return reinterpret_cast<Structure*>(slot->asCell());
+        }
+        return 0;
+    }
+    
+    void clearSingleTransition()
+    {
+        ASSERT(isUsingSingleSlot());
+        if (HandleSlot slot = this->slot())
+            HandleHeap::heapFor(slot)->deallocate(slot);
+    }
+    
+    void setSingleTransition(JSGlobalData& globalData, Structure* structure)
+    {
+        ASSERT(isUsingSingleSlot());
+        HandleSlot slot = this->slot();
+        if (!slot) {
+            slot = globalData.allocateGlobalHandle();
+            HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0);
+            m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag;
+        }
+        HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure));
+        *slot = reinterpret_cast<JSCell*>(structure);
+    }
+
+    intptr_t m_data;
+};
+
 } // namespace JSC
 
 #endif // StructureTransitionTable_h
index f5e266960d61840d71f92cfe1e1e2089b3b026b0..2635501e11eaa4b74b3b462ad1bc00a0498d21f7 100644 (file)
@@ -119,10 +119,14 @@ namespace JSC {
         static const bool needsDestruction = false;
     };
 
-    typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
+    typedef HashMap<RefPtr<StringImpl>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, SymbolTableIndexHashTraits> SymbolTable;
 
-    class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable>
-    {
+    class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable> {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
+    private:
+        SharedSymbolTable() { }
     };
     
 } // namespace JSC
index 2a8acced8d12c8f1d15066a36f78c3a80a8bca35..81a096aad2826ca963ed2442930bd8b6970adaee 100644 (file)
@@ -98,7 +98,10 @@ static inline unsigned getCPUTime()
     return GETUPTIMEMS();
 #else
     // FIXME: We should return the time the current thread has spent executing.
-    return currentTime() * 1000;
+
+    // use a relative time from first call in order to avoid an overflow
+    static double firstTime = currentTime();
+    return static_cast<unsigned> ((currentTime() - firstTime) * 1000);
 #endif
 }
 
index 7bfa6d08305dc8b5f1d6370e2e92e8222e66ea27..5925641f80a366ad34061b562c74cd822e3cfe9b 100644 (file)
@@ -40,6 +40,7 @@ namespace JSC {
         TimeoutChecker();
 
         void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; }
+        unsigned timeoutInterval() const { return m_timeoutInterval; }
         
         unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; }
         
index 8fb0dfdd03d3011bf885da7dbb78ba416e9bbc8e..b70d505ce60cb193d3540451a1718d0db8ce31e3 100644 (file)
 #include "UString.h"
 
 #include "JSGlobalObjectFunctions.h"
-#include "Collector.h"
-#include "dtoa.h"
+#include "Heap.h"
 #include "Identifier.h"
 #include "Operations.h"
 #include <ctype.h>
 #include <limits.h>
 #include <limits>
-#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/Assertions.h>
+#include <wtf/DecimalNumber.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StringExtras.h>
 #include <wtf/Vector.h>
 #include <wtf/unicode/UTF8.h>
-#include <wtf/StringExtras.h>
 
 #if HAVE(STRINGS_H)
 #include <strings.h>
@@ -57,37 +54,43 @@ namespace JSC {
 extern const double NaN;
 extern const double Inf;
 
-// The null string is immutable, except for refCount.
-UString* UString::s_nullUString;
+COMPILE_ASSERT(sizeof(UString) == sizeof(void*), UString_should_stay_small);
 
-void initializeUString()
+// Construct a string with UTF-16 data.
+UString::UString(const UChar* characters, unsigned length)
+    : m_impl(characters ? StringImpl::create(characters, length) : 0)
 {
-    // UStringImpl::empty() does not construct its static string in a threadsafe fashion,
-    // so ensure it has been initialized from here.
-    UStringImpl::empty();
-
-    UString::s_nullUString = new UString;
 }
 
-UString::UString(const char* c)
-    : m_rep(Rep::create(c))
+// Construct a string with UTF-16 data, from a null-terminated source.
+UString::UString(const UChar* characters)
 {
+    if (!characters)
+        return;
+
+    int length = 0;
+    while (characters[length] != UChar(0))
+        ++length;
+
+    m_impl = StringImpl::create(characters, length);
 }
 
-UString::UString(const char* c, unsigned length)
-    : m_rep(Rep::create(c, length))
+// Construct a string with latin1 data.
+UString::UString(const char* characters, unsigned length)
+    : m_impl(characters ? StringImpl::create(characters, length) : 0)
 {
 }
 
-UString::UString(const UChar* c, unsigned length)
-    : m_rep(Rep::create(c, length))
+// Construct a string with latin1 data, from a null-terminated source.
+UString::UString(const char* characters)
+    : m_impl(characters ? StringImpl::create(characters) : 0)
 {
 }
 
-UString UString::from(int i)
+UString UString::number(int i)
 {
     UChar buf[1 + sizeof(i) * 3];
-    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
     UChar* p = end;
 
     if (i == 0)
@@ -113,17 +116,21 @@ UString UString::from(int i)
     return UString(p, static_cast<unsigned>(end - p));
 }
 
-UString UString::from(long long i)
+UString UString::number(long long i)
 {
     UChar buf[1 + sizeof(i) * 3];
-    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
     UChar* p = end;
 
     if (i == 0)
         *--p = '0';
     else if (i == std::numeric_limits<long long>::min()) {
         char minBuf[1 + sizeof(i) * 3];
+#if OS(WINDOWS)
+        snprintf(minBuf, sizeof(minBuf), "%I64d", std::numeric_limits<long long>::min());
+#else
         snprintf(minBuf, sizeof(minBuf), "%lld", std::numeric_limits<long long>::min());
+#endif
         return UString(minBuf);
     } else {
         bool negative = false;
@@ -142,10 +149,10 @@ UString UString::from(long long i)
     return UString(p, static_cast<unsigned>(end - p));
 }
 
-UString UString::from(unsigned u)
+UString UString::number(unsigned u)
 {
     UChar buf[sizeof(u) * 3];
-    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
     UChar* p = end;
 
     if (u == 0)
@@ -160,10 +167,10 @@ UString UString::from(unsigned u)
     return UString(p, static_cast<unsigned>(end - p));
 }
 
-UString UString::from(long l)
+UString UString::number(long l)
 {
     UChar buf[1 + sizeof(l) * 3];
-    UChar* end = buf + sizeof(buf) / sizeof(UChar);
+    UChar* end = buf + WTF_ARRAY_LENGTH(buf);
     UChar* p = end;
 
     if (l == 0)
@@ -189,329 +196,24 @@ UString UString::from(long l)
     return UString(p, end - p);
 }
 
-UString UString::from(double d)
+UString UString::number(double d)
 {
-    DtoaBuffer buffer;
-    unsigned length;
-    doubleToStringInJavaScriptFormat(d, buffer, &length);
+    NumberToStringBuffer buffer;
+    unsigned length = numberToString(d, buffer);
     return UString(buffer, length);
 }
 
-char* UString::ascii() const
-{
-    static char* asciiBuffer = 0;
-
-    unsigned length = size();
-    unsigned neededSize = length + 1;
-    delete[] asciiBuffer;
-    asciiBuffer = new char[neededSize];
-
-    const UChar* p = data();
-    char* q = asciiBuffer;
-    const UChar* limit = p + length;
-    while (p != limit) {
-        *q = static_cast<char>(p[0]);
-        ++p;
-        ++q;
-    }
-    *q = '\0';
-
-    return asciiBuffer;
-}
-
-bool UString::is8Bit() const
-{
-    const UChar* u = data();
-    const UChar* limit = u + size();
-    while (u < limit) {
-        if (u[0] > 0xFF)
-            return false;
-        ++u;
-    }
-
-    return true;
-}
-
-UChar UString::operator[](unsigned pos) const
-{
-    if (pos >= size())
-        return '\0';
-    return data()[pos];
-}
-
-double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const
-{
-    if (size() == 1) {
-        UChar c = data()[0];
-        if (isASCIIDigit(c))
-            return c - '0';
-        if (isASCIISpace(c) && tolerateEmptyString)
-            return 0;
-        return NaN;
-    }
-
-    // FIXME: If tolerateTrailingJunk is true, then we want to tolerate junk 
-    // after the number, even if it contains invalid UTF-16 sequences. So we
-    // shouldn't use the UTF8String function, which returns null when it
-    // encounters invalid UTF-16. Further, we have no need to convert the
-    // non-ASCII characters to UTF-8, so the UTF8String does quite a bit of
-    // unnecessary work.
-    CString s = UTF8String();
-    if (s.isNull())
-        return NaN;
-    const char* c = s.data();
-
-    // skip leading white space
-    while (isASCIISpace(*c))
-        c++;
-
-    // empty string ?
-    if (*c == '\0')
-        return tolerateEmptyString ? 0.0 : NaN;
-
-    double d;
-
-    // hex number ?
-    if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
-        const char* firstDigitPosition = c + 2;
-        c++;
-        d = 0.0;
-        while (*(++c)) {
-            if (*c >= '0' && *c <= '9')
-                d = d * 16.0 + *c - '0';
-            else if ((*c >= 'A' && *c <= 'F') || (*c >= 'a' && *c <= 'f'))
-                d = d * 16.0 + (*c & 0xdf) - 'A' + 10.0;
-            else
-                break;
-        }
-
-        if (d >= mantissaOverflowLowerBound)
-            d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
-    } else {
-        // regular number ?
-        char* end;
-        d = WTF::strtod(c, &end);
-        if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
-            c = end;
-        } else {
-            double sign = 1.0;
-
-            if (*c == '+')
-                c++;
-            else if (*c == '-') {
-                sign = -1.0;
-                c++;
-            }
-
-            // We used strtod() to do the conversion. However, strtod() handles
-            // infinite values slightly differently than JavaScript in that it
-            // converts the string "inf" with any capitalization to infinity,
-            // whereas the ECMA spec requires that it be converted to NaN.
-
-            if (c[0] == 'I' && c[1] == 'n' && c[2] == 'f' && c[3] == 'i' && c[4] == 'n' && c[5] == 'i' && c[6] == 't' && c[7] == 'y') {
-                d = sign * Inf;
-                c += 8;
-            } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
-                c = end;
-            else
-                return NaN;
-        }
-    }
-
-    // allow trailing white space
-    while (isASCIISpace(*c))
-        c++;
-    // don't allow anything after - unless tolerant=true
-    // FIXME: If string contains a U+0000 character, then this check is incorrect.
-    if (!tolerateTrailingJunk && *c != '\0')
-        d = NaN;
-
-    return d;
-}
-
-double UString::toDouble(bool tolerateTrailingJunk) const
-{
-    return toDouble(tolerateTrailingJunk, true);
-}
-
-double UString::toDouble() const
+UString UString::substringSharingImpl(unsigned offset, unsigned length) const
 {
-    return toDouble(false, true);
-}
-
-uint32_t UString::toUInt32(bool* ok) const
-{
-    double d = toDouble();
-    bool b = true;
+    // FIXME: We used to check against a limit of Heap::minExtraCost / sizeof(UChar).
 
-    if (d != static_cast<uint32_t>(d)) {
-        b = false;
-        d = 0;
-    }
-
-    if (ok)
-        *ok = b;
-
-    return static_cast<uint32_t>(d);
-}
+    unsigned stringLength = this->length();
+    offset = min(offset, stringLength);
+    length = min(length, stringLength - offset);
 
-uint32_t UString::toUInt32(bool* ok, bool tolerateEmptyString) const
-{
-    double d = toDouble(false, tolerateEmptyString);
-    bool b = true;
-
-    if (d != static_cast<uint32_t>(d)) {
-        b = false;
-        d = 0;
-    }
-
-    if (ok)
-        *ok = b;
-
-    return static_cast<uint32_t>(d);
-}
-
-uint32_t UString::toStrictUInt32(bool* ok) const
-{
-    if (ok)
-        *ok = false;
-
-    // Empty string is not OK.
-    unsigned len = m_rep->length();
-    if (len == 0)
-        return 0;
-    const UChar* p = m_rep->characters();
-    unsigned short c = p[0];
-
-    // If the first digit is 0, only 0 itself is OK.
-    if (c == '0') {
-        if (len == 1 && ok)
-            *ok = true;
-        return 0;
-    }
-
-    // Convert to UInt32, checking for overflow.
-    uint32_t i = 0;
-    while (1) {
-        // Process character, turning it into a digit.
-        if (c < '0' || c > '9')
-            return 0;
-        const unsigned d = c - '0';
-
-        // Multiply by 10, checking for overflow out of 32 bits.
-        if (i > 0xFFFFFFFFU / 10)
-            return 0;
-        i *= 10;
-
-        // Add in the digit, checking for overflow out of 32 bits.
-        const unsigned max = 0xFFFFFFFFU - d;
-        if (i > max)
-            return 0;
-        i += d;
-
-        // Handle end of string.
-        if (--len == 0) {
-            if (ok)
-                *ok = true;
-            return i;
-        }
-
-        // Get next character.
-        c = *(++p);
-    }
-}
-
-unsigned UString::find(const UString& f, unsigned pos) const
-{
-    unsigned fsz = f.size();
-
-    if (fsz == 1) {
-        UChar ch = f[0];
-        const UChar* end = data() + size();
-        for (const UChar* c = data() + pos; c < end; c++) {
-            if (*c == ch)
-                return static_cast<unsigned>(c - data());
-        }
-        return NotFound;
-    }
-
-    unsigned sz = size();
-    if (sz < fsz)
-        return NotFound;
-    if (fsz == 0)
-        return pos;
-    const UChar* end = data() + sz - fsz;
-    unsigned fsizeminusone = (fsz - 1) * sizeof(UChar);
-    const UChar* fdata = f.data();
-    unsigned short fchar = fdata[0];
-    ++fdata;
-    for (const UChar* c = data() + pos; c <= end; c++) {
-        if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone))
-            return static_cast<unsigned>(c - data());
-    }
-
-    return NotFound;
-}
-
-unsigned UString::find(UChar ch, unsigned pos) const
-{
-    const UChar* end = data() + size();
-    for (const UChar* c = data() + pos; c < end; c++) {
-        if (*c == ch)
-            return static_cast<unsigned>(c - data());
-    }
-
-    return NotFound;
-}
-
-unsigned UString::rfind(const UString& f, unsigned pos) const
-{
-    unsigned sz = size();
-    unsigned fsz = f.size();
-    if (sz < fsz)
-        return NotFound;
-    if (pos > sz - fsz)
-        pos = sz - fsz;
-    if (fsz == 0)
-        return pos;
-    unsigned fsizeminusone = (fsz - 1) * sizeof(UChar);
-    const UChar* fdata = f.data();
-    for (const UChar* c = data() + pos; c >= data(); c--) {
-        if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone))
-            return static_cast<unsigned>(c - data());
-    }
-
-    return NotFound;
-}
-
-unsigned UString::rfind(UChar ch, unsigned pos) const
-{
-    if (isEmpty())
-        return NotFound;
-    if (pos + 1 >= size())
-        pos = size() - 1;
-    for (const UChar* c = data() + pos; c >= data(); c--) {
-        if (*c == ch)
-            return static_cast<unsigned>(c - data());
-    }
-
-    return NotFound;
-}
-
-UString UString::substr(unsigned pos, unsigned len) const
-{
-    unsigned s = size();
-
-    if (pos >= s)
-        pos = s;
-    unsigned limit = s - pos;
-    if (len > limit)
-        len = limit;
-
-    if (pos == 0 && len == s)
+    if (!offset && length == stringLength)
         return *this;
-
-    return UString(Rep::create(m_rep, pos, len));
+    return UString(StringImpl::create(m_impl, offset, length));
 }
 
 bool operator==(const UString& s1, const char *s2)
@@ -519,8 +221,8 @@ bool operator==(const UString& s1, const char *s2)
     if (s2 == 0)
         return s1.isEmpty();
 
-    const UChar* u = s1.data();
-    const UChar* uend = u + s1.size();
+    const UChar* u = s1.characters();
+    const UChar* uend = u + s1.length();
     while (u != uend && *s2) {
         if (u[0] != (unsigned char)*s2)
             return false;
@@ -533,11 +235,11 @@ bool operator==(const UString& s1, const char *s2)
 
 bool operator<(const UString& s1, const UString& s2)
 {
-    const unsigned l1 = s1.size();
-    const unsigned l2 = s2.size();
+    const unsigned l1 = s1.length();
+    const unsigned l2 = s2.length();
     const unsigned lmin = l1 < l2 ? l1 : l2;
-    const UChar* c1 = s1.data();
-    const UChar* c2 = s2.data();
+    const UChar* c1 = s1.characters();
+    const UChar* c2 = s2.characters();
     unsigned l = 0;
     while (l < lmin && *c1 == *c2) {
         c1++;
@@ -552,11 +254,11 @@ bool operator<(const UString& s1, const UString& s2)
 
 bool operator>(const UString& s1, const UString& s2)
 {
-    const unsigned l1 = s1.size();
-    const unsigned l2 = s2.size();
+    const unsigned l1 = s1.length();
+    const unsigned l2 = s2.length();
     const unsigned lmin = l1 < l2 ? l1 : l2;
-    const UChar* c1 = s1.data();
-    const UChar* c2 = s2.data();
+    const UChar* c1 = s1.characters();
+    const UChar* c2 = s2.characters();
     unsigned l = 0;
     while (l < lmin && *c1 == *c2) {
         c1++;
@@ -569,45 +271,96 @@ bool operator>(const UString& s1, const UString& s2)
     return (l1 > l2);
 }
 
-int compare(const UString& s1, const UString& s2)
+CString UString::ascii() const
 {
-    const unsigned l1 = s1.size();
-    const unsigned l2 = s2.size();
-    const unsigned lmin = l1 < l2 ? l1 : l2;
-    const UChar* c1 = s1.data();
-    const UChar* c2 = s2.data();
-    unsigned l = 0;
-    while (l < lmin && *c1 == *c2) {
-        c1++;
-        c2++;
-        l++;
+    // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are
+    // preserved, characters outside of this range are converted to '?'.
+
+    unsigned length = this->length();
+    const UChar* characters = this->characters();
+
+    char* characterBuffer;
+    CString result = CString::newUninitialized(length, characterBuffer);
+
+    for (unsigned i = 0; i < length; ++i) {
+        UChar ch = characters[i];
+        characterBuffer[i] = ch && (ch < 0x20 || ch >= 0x7f) ? '?' : ch;
     }
 
-    if (l < lmin)
-        return (c1[0] > c2[0]) ? 1 : -1;
+    return result;
+}
 
-    if (l1 == l2)
-        return 0;
+CString UString::latin1() const
+{
+    // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are
+    // preserved, characters outside of this range are converted to '?'.
+
+    unsigned length = this->length();
+    const UChar* characters = this->characters();
 
-    return (l1 > l2) ? 1 : -1;
+    char* characterBuffer;
+    CString result = CString::newUninitialized(length, characterBuffer);
+
+    for (unsigned i = 0; i < length; ++i) {
+        UChar ch = characters[i];
+        characterBuffer[i] = ch > 0xff ? '?' : ch;
+    }
+
+    return result;
 }
 
-CString UString::UTF8String(bool strict) const
+// Helper to write a three-byte UTF-8 code point to the buffer, caller must check room is available.
+static inline void putUTF8Triple(char*& buffer, UChar ch)
 {
-    // Allocate a buffer big enough to hold all the characters.
-    const unsigned length = size();
+    ASSERT(ch >= 0x0800);
+    *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0);
+    *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80);
+    *buffer++ = static_cast<char>((ch & 0x3F) | 0x80);
+}
+
+CString UString::utf8(bool strict) const
+{
+    unsigned length = this->length();
+    const UChar* characters = this->characters();
+
+    // Allocate a buffer big enough to hold all the characters
+    // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes).
+    // Optimization ideas, if we find this function is hot:
+    //  * We could speculatively create a CStringBuffer to contain 'length' 
+    //    characters, and resize if necessary (i.e. if the buffer contains
+    //    non-ascii characters). (Alternatively, scan the buffer first for
+    //    ascii characters, so we know this will be sufficient).
+    //  * We could allocate a CStringBuffer with an appropriate size to
+    //    have a good chance of being able to write the string into the
+    //    buffer without reallocing (say, 1.5 x length).
     if (length > numeric_limits<unsigned>::max() / 3)
-        return CString(); 
-    Vector<char, 1024> buffer(length * 3);
-
-    // Convert to runs of 8-bit characters.
-    char* p = buffer.data();
-    const UChar* d = reinterpret_cast<const UChar*>(&data()[0]);
-    ConversionResult result = convertUTF16ToUTF8(&d, d + length, &p, p + buffer.size(), strict);
-    if (result != conversionOK)
         return CString();
+    Vector<char, 1024> bufferVector(length * 3);
+
+    char* buffer = bufferVector.data();
+    ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict);
+    ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion
+
+    // Only produced from strict conversion.
+    if (result == sourceIllegal)
+        return CString();
+
+    // Check for an unconverted high surrogate.
+    if (result == sourceExhausted) {
+        if (strict)
+            return CString();
+        // This should be one unpaired high surrogate. Treat it the same
+        // was as an unpaired high surrogate would have been handled in
+        // the middle of a string with non-strict conversion - which is
+        // to say, simply encode it to UTF-8.
+        ASSERT((characters + 1) == (this->characters() + length));
+        ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF));
+        // There should be room left, since one UChar hasn't been converted.
+        ASSERT((buffer + 3) <= (buffer + bufferVector.size()));
+        putUTF8Triple(buffer, *characters);
+    }
 
-    return CString(buffer.data(), p - buffer.data());
+    return CString(bufferVector.data(), buffer - bufferVector.data());
 }
 
 } // namespace JSC
index e3cd7a107f7cebdeada36f112fb22508df907437..b98e7b40d7f597244d248b1126cf244c6e71b591 100644 (file)
 /*
- *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *  Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
  *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
  *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  *
  */
 
 #ifndef UString_h
 #define UString_h
 
-#include "Collector.h"
-#include "UStringImpl.h"
-#include <stdint.h>
-#include <string.h>
-#include <wtf/Assertions.h>
-#include <wtf/CrossThreadRefCounted.h>
-#include <wtf/OwnFastMallocPtr.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
-#include <wtf/text/CString.h>
-#include <wtf/unicode/Unicode.h>
+#include <wtf/text/StringImpl.h>
 
 namespace JSC {
 
-    using WTF::PlacementNewAdoptType;
-    using WTF::PlacementNewAdopt;
+class UString {
+public:
+    // Construct a null string, distinguishable from an empty string.
+    UString() { }
 
-    class UString {
-        friend class JIT;
+    // Construct a string with UTF-16 data.
+    UString(const UChar* characters, unsigned length);
 
-    public:
-        typedef UStringImpl Rep;
-    
-    public:
-        UString() {}
-        UString(const char*); // Constructor for null-terminated string.
-        UString(const char*, unsigned length);
-        UString(const UChar*, unsigned length);
-        UString(const Vector<UChar>& buffer);
-
-        UString(const UString& s)
-            : m_rep(s.m_rep)
-        {
-        }
-
-        // Special constructor for cases where we overwrite an object in place.
-        UString(PlacementNewAdoptType)
-            : m_rep(PlacementNewAdopt)
-        {
-        }
-
-        template<size_t inlineCapacity>
-        static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector)
-        {
-            return Rep::adopt(vector);
-        }
-
-        static UString from(int);
-        static UString from(long long);
-        static UString from(unsigned);
-        static UString from(long);
-        static UString from(double);
-
-        // NOTE: This method should only be used for *debugging* purposes as it
-        // is neither Unicode safe nor free from side effects nor thread-safe.
-        char* ascii() const;
-
-        /**
-         * Convert the string to UTF-8, assuming it is UTF-16 encoded.
-         * In non-strict mode, this function is tolerant of badly formed UTF-16, it
-         * can create UTF-8 strings that are invalid because they have characters in
-         * the range U+D800-U+DDFF, U+FFFE, or U+FFFF, but the UTF-8 string is
-         * guaranteed to be otherwise valid.
-         * In strict mode, error is returned as null CString.
-         */
-        CString UTF8String(bool strict = false) const;
-
-        const UChar* data() const
-        {
-            if (!m_rep)
-                return 0;
-            return m_rep->characters();
-        }
-
-        unsigned size() const
-        {
-            if (!m_rep)
-                return 0;
-            return m_rep->length();
-        }
-
-        bool isNull() const { return !m_rep; }
-        bool isEmpty() const { return !m_rep || !m_rep->length(); }
-
-        bool is8Bit() const;
-
-        UChar operator[](unsigned pos) const;
-
-        double toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) const;
-        double toDouble(bool tolerateTrailingJunk) const;
-        double toDouble() const;
-
-        uint32_t toUInt32(bool* ok = 0) const;
-        uint32_t toUInt32(bool* ok, bool tolerateEmptyString) const;
-        uint32_t toStrictUInt32(bool* ok = 0) const;
-
-        unsigned toArrayIndex(bool* ok = 0) const;
-
-        static const unsigned NotFound = 0xFFFFFFFFu;
-        unsigned find(const UString& f, unsigned pos = 0) const;
-        unsigned find(UChar, unsigned pos = 0) const;
-        unsigned rfind(const UString& f, unsigned pos) const;
-        unsigned rfind(UChar, unsigned pos) const;
-
-        UString substr(unsigned pos = 0, unsigned len = 0xFFFFFFFF) const;
-
-        static const UString& null() { return *s_nullUString; }
-
-        Rep* rep() const { return m_rep.get(); }
-
-        UString(PassRefPtr<Rep> r)
-            : m_rep(r)
-        {
-        }
-
-        size_t cost() const
-        {
-            if (!m_rep)
-                return 0;
-            return m_rep->cost();
-        }
-
-    private:
-        RefPtr<Rep> m_rep;
-
-        static UString* s_nullUString;
-
-        friend void initializeUString();
-        friend bool operator==(const UString&, const UString&);
-    };
-
-    ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
-    {
-        UString::Rep* rep1 = s1.rep();
-        UString::Rep* rep2 = s2.rep();
-        unsigned size1 = 0;
-        unsigned size2 = 0;
-
-        if (rep1 == rep2) // If they're the same rep, they're equal.
-            return true;
-        
-        if (rep1)
-            size1 = rep1->length();
-            
-        if (rep2)
-            size2 = rep2->length();
-            
-        if (size1 != size2) // If the lengths are not the same, we're done.
-            return false;
-        
-        if (!size1)
-            return true;
-        
-        // At this point we know 
-        //   (a) that the strings are the same length and
-        //   (b) that they are greater than zero length.
-        const UChar* d1 = rep1->characters();
-        const UChar* d2 = rep2->characters();
-        
-        if (d1 == d2) // Check to see if the data pointers are the same.
-            return true;
-        
-        // Do quick checks for sizes 1 and 2.
-        switch (size1) {
-        case 1:
-            return d1[0] == d2[0];
-        case 2:
-            return (d1[0] == d2[0]) & (d1[1] == d2[1]);
-        default:
-            return memcmp(d1, d2, size1 * sizeof(UChar)) == 0;
-        }
-    }
+    // Construct a string with UTF-16 data, from a null-terminated source.
+    UString(const UChar*);
 
+    // Construct a string with latin1 data.
+    UString(const char* characters, unsigned length);
 
-    inline bool operator!=(const UString& s1, const UString& s2)
-    {
-        return !JSC::operator==(s1, s2);
-    }
+    // Construct a string with latin1 data, from a null-terminated source.
+    UString(const char* characters);
 
-    bool operator<(const UString& s1, const UString& s2);
-    bool operator>(const UString& s1, const UString& s2);
+    // Construct a string referencing an existing StringImpl.
+    UString(StringImpl* impl) : m_impl(impl) { }
+    UString(PassRefPtr<StringImpl> impl) : m_impl(impl) { }
+    UString(RefPtr<StringImpl> impl) : m_impl(impl) { }
 
-    bool operator==(const UString& s1, const char* s2);
+    // Inline the destructor.
+    ALWAYS_INLINE ~UString() { }
 
-    inline bool operator!=(const UString& s1, const char* s2)
-    {
-        return !JSC::operator==(s1, s2);
-    }
+    void swap(UString& o) { m_impl.swap(o.m_impl); }
 
-    inline bool operator==(const char *s1, const UString& s2)
-    {
-        return operator==(s2, s1);
-    }
+    template<size_t inlineCapacity>
+    static UString adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); }
 
-    inline bool operator!=(const char *s1, const UString& s2)
-    {
-        return !JSC::operator==(s1, s2);
-    }
+    bool isNull() const { return !m_impl; }
+    bool isEmpty() const { return !m_impl || !m_impl->length(); }
 
-    int compare(const UString&, const UString&);
+    StringImpl* impl() const { return m_impl.get(); }
 
-    // Rule from ECMA 15.2 about what an array index is.
-    // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1.
-    inline unsigned UString::toArrayIndex(bool* ok) const
+    unsigned length() const
     {
-        unsigned i = toStrictUInt32(ok);
-        if (ok && i >= 0xFFFFFFFFU)
-            *ok = false;
-        return i;
-    }
-
-    // We'd rather not do shared substring append for small strings, since
-    // this runs too much risk of a tiny initial string holding down a
-    // huge buffer.
-    static const unsigned minShareSize = Heap::minExtraCost / sizeof(UChar);
-
-    struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > {
-        static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); }
-        static unsigned hash(JSC::UString::Rep* key) { return key->existingHash(); }
-    };
-
-    void initializeUString();
-
-    template<typename StringType>
-    class StringTypeAdapter {
-    };
-
-    template<>
-    class StringTypeAdapter<char*> {
-    public:
-        StringTypeAdapter<char*>(char* buffer)
-            : m_buffer((unsigned char*)buffer)
-            , m_length(strlen(buffer))
-        {
-        }
-
-        unsigned length() { return m_length; }
-
-        void writeTo(UChar* destination)
-        {
-            for (unsigned i = 0; i < m_length; ++i)
-                destination[i] = m_buffer[i];
-        }
-
-    private:
-        const unsigned char* m_buffer;
-        unsigned m_length;
-    };
-
-    template<>
-    class StringTypeAdapter<const char*> {
-    public:
-        StringTypeAdapter<const char*>(const char* buffer)
-            : m_buffer((unsigned char*)buffer)
-            , m_length(strlen(buffer))
-        {
-        }
-
-        unsigned length() { return m_length; }
-
-        void writeTo(UChar* destination)
-        {
-            for (unsigned i = 0; i < m_length; ++i)
-                destination[i] = m_buffer[i];
-        }
-
-    private:
-        const unsigned char* m_buffer;
-        unsigned m_length;
-    };
-
-    template<>
-    class StringTypeAdapter<UString> {
-    public:
-        StringTypeAdapter<UString>(UString& string)
-            : m_data(string.data())
-            , m_length(string.size())
-        {
-        }
-
-        unsigned length() { return m_length; }
-
-        void writeTo(UChar* destination)
-        {
-            for (unsigned i = 0; i < m_length; ++i)
-                destination[i] = m_data[i];
-        }
-
-    private:
-        const UChar* m_data;
-        unsigned m_length;
-    };
-
-    inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
-    {
-        unsigned oldTotal = total;
-        total = oldTotal + addend;
-        if (total < oldTotal)
-            overflow = true;
-    }
-
-    template<typename StringType1, typename StringType2>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2)
-    {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-
-        UChar* buffer;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        if (overflow)
-            return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
+        if (!m_impl)
             return 0;
-
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-
-        return resultImpl;
+        return m_impl->length();
     }
 
-    template<typename StringType1, typename StringType2, typename StringType3>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
+    const UChar* characters() const
     {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-        StringTypeAdapter<StringType3> adapter3(string3);
-
-        UChar* buffer = 0;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        sumWithOverflow(length, adapter3.length(), overflow);
-        if (overflow)
+        if (!m_impl)
             return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
-            return 0;
-
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-        result += adapter2.length();
-        adapter3.writeTo(result);
-
-        return resultImpl;
+        return m_impl->characters();
     }
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+    CString ascii() const;
+    CString latin1() const;
+    CString utf8(bool strict = false) const;
+
+    UChar operator[](unsigned index) const
     {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-        StringTypeAdapter<StringType3> adapter3(string3);
-        StringTypeAdapter<StringType4> adapter4(string4);
-
-        UChar* buffer;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        sumWithOverflow(length, adapter3.length(), overflow);
-        sumWithOverflow(length, adapter4.length(), overflow);
-        if (overflow)
+        if (!m_impl || index >= m_impl->length())
             return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
-            return 0;
-
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-        result += adapter2.length();
-        adapter3.writeTo(result);
-        result += adapter3.length();
-        adapter4.writeTo(result);
+        return m_impl->characters()[index];
+    }
 
-        return resultImpl;
+    static UString number(int);
+    static UString number(unsigned);
+    static UString number(long);
+    static UString number(long long);
+    static UString number(double);
+
+    // Find a single character or string, also with match function & latin1 forms.
+    size_t find(UChar c, unsigned start = 0) const
+        { return m_impl ? m_impl->find(c, start) : notFound; }
+    size_t find(const UString& str, unsigned start = 0) const
+        { return m_impl ? m_impl->find(str.impl(), start) : notFound; }
+    size_t find(const char* str, unsigned start = 0) const
+        { return m_impl ? m_impl->find(str, start) : notFound; }
+
+    // Find the last instance of a single character or string.
+    size_t reverseFind(UChar c, unsigned start = UINT_MAX) const
+        { return m_impl ? m_impl->reverseFind(c, start) : notFound; }
+    size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const
+        { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; }
+
+    UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const;
+
+private:
+    RefPtr<StringImpl> m_impl;
+};
+
+ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2)
+{
+    StringImpl* rep1 = s1.impl();
+    StringImpl* rep2 = s2.impl();
+    unsigned size1 = 0;
+    unsigned size2 = 0;
+
+    if (rep1 == rep2) // If they're the same rep, they're equal.
+        return true;
+    
+    if (rep1)
+        size1 = rep1->length();
+        
+    if (rep2)
+        size2 = rep2->length();
+        
+    if (size1 != size2) // If the lengths are not the same, we're done.
+        return false;
+    
+    if (!size1)
+        return true;
+    
+    // At this point we know 
+    //   (a) that the strings are the same length and
+    //   (b) that they are greater than zero length.
+    const UChar* d1 = rep1->characters();
+    const UChar* d2 = rep2->characters();
+    
+    if (d1 == d2) // Check to see if the data pointers are the same.
+        return true;
+    
+    // Do quick checks for sizes 1 and 2.
+    switch (size1) {
+    case 1:
+        return d1[0] == d2[0];
+    case 2:
+        return (d1[0] == d2[0]) & (d1[1] == d2[1]);
+    default:
+        return memcmp(d1, d2, size1 * sizeof(UChar)) == 0;
     }
+}
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
-    {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-        StringTypeAdapter<StringType3> adapter3(string3);
-        StringTypeAdapter<StringType4> adapter4(string4);
-        StringTypeAdapter<StringType5> adapter5(string5);
-
-        UChar* buffer;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        sumWithOverflow(length, adapter3.length(), overflow);
-        sumWithOverflow(length, adapter4.length(), overflow);
-        sumWithOverflow(length, adapter5.length(), overflow);
-        if (overflow)
-            return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
-            return 0;
 
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-        result += adapter2.length();
-        adapter3.writeTo(result);
-        result += adapter3.length();
-        adapter4.writeTo(result);
-        result += adapter4.length();
-        adapter5.writeTo(result);
-
-        return resultImpl;
-    }
+inline bool operator!=(const UString& s1, const UString& s2)
+{
+    return !JSC::operator==(s1, s2);
+}
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
-    {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-        StringTypeAdapter<StringType3> adapter3(string3);
-        StringTypeAdapter<StringType4> adapter4(string4);
-        StringTypeAdapter<StringType5> adapter5(string5);
-        StringTypeAdapter<StringType6> adapter6(string6);
-
-        UChar* buffer;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        sumWithOverflow(length, adapter3.length(), overflow);
-        sumWithOverflow(length, adapter4.length(), overflow);
-        sumWithOverflow(length, adapter5.length(), overflow);
-        sumWithOverflow(length, adapter6.length(), overflow);
-        if (overflow)
-            return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
-            return 0;
+bool operator<(const UString& s1, const UString& s2);
+bool operator>(const UString& s1, const UString& s2);
 
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-        result += adapter2.length();
-        adapter3.writeTo(result);
-        result += adapter3.length();
-        adapter4.writeTo(result);
-        result += adapter4.length();
-        adapter5.writeTo(result);
-        result += adapter5.length();
-        adapter6.writeTo(result);
-
-        return resultImpl;
-    }
+bool operator==(const UString& s1, const char* s2);
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
-    {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-        StringTypeAdapter<StringType3> adapter3(string3);
-        StringTypeAdapter<StringType4> adapter4(string4);
-        StringTypeAdapter<StringType5> adapter5(string5);
-        StringTypeAdapter<StringType6> adapter6(string6);
-        StringTypeAdapter<StringType7> adapter7(string7);
-
-        UChar* buffer;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        sumWithOverflow(length, adapter3.length(), overflow);
-        sumWithOverflow(length, adapter4.length(), overflow);
-        sumWithOverflow(length, adapter5.length(), overflow);
-        sumWithOverflow(length, adapter6.length(), overflow);
-        sumWithOverflow(length, adapter7.length(), overflow);
-        if (overflow)
-            return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
-            return 0;
+inline bool operator!=(const UString& s1, const char* s2)
+{
+    return !JSC::operator==(s1, s2);
+}
 
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-        result += adapter2.length();
-        adapter3.writeTo(result);
-        result += adapter3.length();
-        adapter4.writeTo(result);
-        result += adapter4.length();
-        adapter5.writeTo(result);
-        result += adapter5.length();
-        adapter6.writeTo(result);
-        result += adapter6.length();
-        adapter7.writeTo(result);
-
-        return resultImpl;
-    }
+inline bool operator==(const char *s1, const UString& s2)
+{
+    return operator==(s2, s1);
+}
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
-    PassRefPtr<UStringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
-    {
-        StringTypeAdapter<StringType1> adapter1(string1);
-        StringTypeAdapter<StringType2> adapter2(string2);
-        StringTypeAdapter<StringType3> adapter3(string3);
-        StringTypeAdapter<StringType4> adapter4(string4);
-        StringTypeAdapter<StringType5> adapter5(string5);
-        StringTypeAdapter<StringType6> adapter6(string6);
-        StringTypeAdapter<StringType7> adapter7(string7);
-        StringTypeAdapter<StringType8> adapter8(string8);
-
-        UChar* buffer;
-        bool overflow = false;
-        unsigned length = adapter1.length();
-        sumWithOverflow(length, adapter2.length(), overflow);
-        sumWithOverflow(length, adapter3.length(), overflow);
-        sumWithOverflow(length, adapter4.length(), overflow);
-        sumWithOverflow(length, adapter5.length(), overflow);
-        sumWithOverflow(length, adapter6.length(), overflow);
-        sumWithOverflow(length, adapter7.length(), overflow);
-        sumWithOverflow(length, adapter8.length(), overflow);
-        if (overflow)
-            return 0;
-        PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer);
-        if (!resultImpl)
-            return 0;
+inline bool operator!=(const char *s1, const UString& s2)
+{
+    return !JSC::operator==(s1, s2);
+}
 
-        UChar* result = buffer;
-        adapter1.writeTo(result);
-        result += adapter1.length();
-        adapter2.writeTo(result);
-        result += adapter2.length();
-        adapter3.writeTo(result);
-        result += adapter3.length();
-        adapter4.writeTo(result);
-        result += adapter4.length();
-        adapter5.writeTo(result);
-        result += adapter5.length();
-        adapter6.writeTo(result);
-        result += adapter6.length();
-        adapter7.writeTo(result);
-        result += adapter7.length();
-        adapter8.writeTo(result);
-
-        return resultImpl;
-    }
+inline int codePointCompare(const UString& s1, const UString& s2)
+{
+    return codePointCompare(s1.impl(), s2.impl());
+}
 
-    template<typename StringType1, typename StringType2>
-    UString makeString(StringType1 string1, StringType2 string2)
+struct UStringHash {
+    static unsigned hash(StringImpl* key) { return key->hash(); }
+    static bool equal(const StringImpl* a, const StringImpl* b)
     {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
-    }
+        if (a == b)
+            return true;
+        if (!a || !b)
+            return false;
 
-    template<typename StringType1, typename StringType2, typename StringType3>
-    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3)
-    {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
-    }
+        unsigned aLength = a->length();
+        unsigned bLength = b->length();
+        if (aLength != bLength)
+            return false;
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
-    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
-    {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
-    }
+        // FIXME: perhaps we should have a more abstract macro that indicates when
+        // going 4 bytes at a time is unsafe
+#if CPU(ARM) || CPU(SH4) || CPU(MIPS)
+        const UChar* aChars = a->characters();
+        const UChar* bChars = b->characters();
+        for (unsigned i = 0; i != aLength; ++i) {
+            if (*aChars++ != *bChars++)
+                return false;
+        }
+        return true;
+#else
+        /* Do it 4-bytes-at-a-time on architectures where it's safe */
+        const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters());
+        const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters());
+
+        unsigned halfLength = aLength >> 1;
+        for (unsigned i = 0; i != halfLength; ++i)
+            if (*aChars++ != *bChars++)
+                return false;
+
+        if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars))
+            return false;
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
-    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
-    {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
+        return true;
+#endif
     }
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
-    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+    static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); }
+    static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b)
     {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
+        return equal(a.get(), b.get());
     }
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
-    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+    static unsigned hash(const UString& key) { return key.impl()->hash(); }
+    static bool equal(const UString& a, const UString& b)
     {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
+        return equal(a.impl(), b.impl());
     }
 
-    template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
-    UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
-    {
-        PassRefPtr<UStringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
-        if (!resultImpl)
-            CRASH();
-        return resultImpl;
-    }
+    static const bool safeToCompareToEmptyOrDeleted = false;
+};
 
 } // namespace JSC
 
 namespace WTF {
 
-    template<typename T> struct DefaultHash;
-    template<typename T> struct StrHash;
-
-    template<> struct StrHash<JSC::UString::Rep*> {
-        static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); }
-        static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return ::equal(a, b); }
-        static const bool safeToCompareToEmptyOrDeleted = false;
-    };
-
-    template<> struct StrHash<RefPtr<JSC::UString::Rep> > : public StrHash<JSC::UString::Rep*> {
-        using StrHash<JSC::UString::Rep*>::hash;
-        static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); }
-        using StrHash<JSC::UString::Rep*>::equal;
-        static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a.get(), b.get()); }
-        static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a, b.get()); }
-        static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return ::equal(a.get(), b); }
+// UStringHash is the default hash for UString
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::UString> {
+    typedef JSC::UStringHash Hash;
+};
 
-        static const bool safeToCompareToEmptyOrDeleted = false;
-    };
+template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits { };
 
-    template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits
-    {
-        static const bool canInitializeWithMemset = true;
-    };
-    
 } // namespace WTF
 
 #endif
+
diff --git a/runtime/UStringBuilder.h b/runtime/UStringBuilder.h
new file mode 100644 (file)
index 0000000..31ccf38
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 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 UStringBuilder_h
+#define UStringBuilder_h
+
+#include <wtf/text/StringBuilder.h>
+
+namespace JSC {
+
+class UStringBuilder : public StringBuilder {
+public:
+    using StringBuilder::append;
+    void append(const UString& str) { append(String(str.impl())); }
+
+    UString toUString() { return toString().impl(); }
+};
+
+} // namespace JSC
+
+#endif // UStringBuilder_h
diff --git a/runtime/UStringConcatenate.h b/runtime/UStringConcatenate.h
new file mode 100644 (file)
index 0000000..0990c72
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2010 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 UStringConcatenate_h
+#define UStringConcatenate_h
+
+#include "UString.h"
+#include <wtf/text/StringConcatenate.h>
+
+namespace WTF {
+
+template<>
+class StringTypeAdapter<JSC::UString> {
+public:
+    StringTypeAdapter<JSC::UString>(JSC::UString& string)
+        : m_data(string.characters())
+        , m_length(string.length())
+    {
+    }
+
+    unsigned length() { return m_length; }
+
+    void writeTo(UChar* destination)
+    {
+        for (unsigned i = 0; i < m_length; ++i)
+            destination[i] = m_data[i];
+    }
+
+private:
+    const UChar* m_data;
+    unsigned m_length;
+};
+
+}; // namespace WTF
+
+namespace JSC {
+
+template<typename StringType1, typename StringType2>
+UString makeUString(StringType1 string1, StringType2 string2)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3>
+UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
+UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
+UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
+UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
+UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6, string7);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
+UString makeUString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
+{
+    PassRefPtr<StringImpl> resultImpl = WTF::tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl;
+}
+
+} // namespace JSC
+
+#endif
diff --git a/runtime/UStringImpl.h b/runtime/UStringImpl.h
deleted file mode 100644 (file)
index 08f1fa5..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef UStringImpl_h
-#define UStringImpl_h
-
-// FIXME: Remove this redundant name!
-#include <wtf/text/StringImpl.h>
-namespace JSC { typedef WebCore::StringImpl UStringImpl; }
-
-#endif
index 39a91c5fa59adb605ae37351eaec1723395b1987..5ad1c62a3e97298d24047f649878d197259e22f6 100644 (file)
 #ifndef WeakGCMap_h
 #define WeakGCMap_h
 
-#include "Collector.h"
+#include "Handle.h"
+#include "JSGlobalData.h"
 #include <wtf/HashMap.h>
 
 namespace JSC {
 
-class JSCell;
+// A HashMap for GC'd values that removes entries when the associated value
+// dies.
+template <typename KeyType, typename MappedType> struct DefaultWeakGCMapFinalizerCallback {
+    static void* finalizerContextFor(KeyType key)
+    {
+        return reinterpret_cast<void*>(key);
+    }
+
+    static KeyType keyForFinalizer(void* context, typename HandleTypes<MappedType>::ExternalType)
+    {
+        return reinterpret_cast<KeyType>(context);
+    }
+};
 
-// A HashMap whose get() function returns emptyValue() for cells awaiting destruction.
-template<typename KeyType, typename MappedType>
-class WeakGCMap : public FastAllocBase {
-    /*
-    Invariants:
-        * A value enters the WeakGCMap marked. (Guaranteed by set().)
-        * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.)
-        * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.)
-        * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.)
-    */
+template<typename KeyType, typename MappedType, typename FinalizerCallback = DefaultWeakGCMapFinalizerCallback<KeyType, MappedType>, typename HashArg = typename DefaultHash<KeyType>::Hash, typename KeyTraitsArg = HashTraits<KeyType> >
+class WeakGCMap : private WeakHandleOwner {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(WeakGCMap);
+
+    typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType;
+    typedef typename HandleTypes<MappedType>::ExternalType ExternalType;
+    typedef typename MapType::iterator map_iterator;
 
 public:
-    typedef typename HashMap<KeyType, MappedType>::iterator iterator;
-    typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator;
-    
+
+    struct iterator {
+        friend class WeakGCMap;
+        iterator(map_iterator iter)
+            : m_iterator(iter)
+        {
+        }
+        
+        std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); }
+        std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; }
+        
+        iterator& operator++() { ++m_iterator; return *this; }
+        
+        // postfix ++ intentionally omitted
+        
+        // Comparison.
+        bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; }
+        bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; }
+        
+    private:
+        map_iterator m_iterator;
+    };
+
+    WeakGCMap()
+    {
+    }
+
     bool isEmpty() { return m_map.isEmpty(); }
+    void clear()
+    {
+        map_iterator end = m_map.end();
+        for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr)
+            HandleHeap::heapFor(ptr->second)->deallocate(ptr->second);
+        m_map.clear();
+    }
 
-    MappedType get(const KeyType& key) const;
-    pair<iterator, bool> set(const KeyType&, const MappedType&); 
-    MappedType take(const KeyType& key);
+    bool contains(const KeyType& key) const
+    {
+        return m_map.contains(key);
+    }
 
-    // These unchecked functions provide access to a value even if the value's
-    // mark bit is not set. This is used, among other things, to retrieve values
-    // during the GC mark phase, which begins by clearing all mark bits.
+    iterator find(const KeyType& key)
+    {
+        return m_map.find(key);
+    }
 
-    MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); }
-    bool uncheckedRemove(const KeyType&, const MappedType&);
+    void remove(iterator iter)
+    {
+        ASSERT(iter.m_iterator != m_map.end());
+        HandleSlot slot = iter.m_iterator->second;
+        ASSERT(slot);
+        HandleHeap::heapFor(slot)->deallocate(slot);
+        m_map.remove(iter.m_iterator);
+    }
 
-    iterator uncheckedBegin() { return m_map.begin(); }
-    iterator uncheckedEnd() { return m_map.end(); }
+    ExternalType get(const KeyType& key) const
+    {
+        return HandleTypes<MappedType>::getFromSlot(m_map.get(key));
+    }
 
-    const_iterator uncheckedBegin() const { return m_map.begin(); }
-    const_iterator uncheckedEnd() const { return m_map.end(); }
+    HandleSlot getSlot(const KeyType& key) const
+    {
+        return m_map.get(key);
+    }
 
-private:
-    HashMap<KeyType, MappedType> m_map;
-};
+    pair<iterator, bool> add(JSGlobalData& globalData, const KeyType& key, ExternalType value)
+    {
+        pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
+        if (iter.second) {
+            HandleSlot slot = globalData.allocateGlobalHandle();
+            iter.first->second = slot;
+            HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key));
+            HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+            *slot = value;
+        }
+        return iter;
+    }
+    
+    void set(iterator iter, ExternalType value)
+    {
+        HandleSlot slot = iter.m_iterator->second;
+        ASSERT(slot);
+        HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+        *slot = value;
+    }
 
-template<typename KeyType, typename MappedType>
-inline MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const
-{
-    MappedType result = m_map.get(key);
-    if (result == HashTraits<MappedType>::emptyValue())
-        return result;
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key)
-{
-    MappedType result = m_map.take(key);
-    if (result == HashTraits<MappedType>::emptyValue())
+    void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
+    {
+        pair<typename MapType::iterator, bool> iter = m_map.add(key, 0);
+        HandleSlot slot = iter.first->second;
+        if (iter.second) {
+            slot = globalData.allocateGlobalHandle();
+            HandleHeap::heapFor(slot)->makeWeak(slot, this, key);
+            iter.first->second = slot;
+        }
+        HandleHeap::heapFor(slot)->writeBarrier(slot, value);
+        *slot = value;
+    }
+
+    ExternalType take(const KeyType& key)
+    {
+        HandleSlot slot = m_map.take(key);
+        if (!slot)
+            return HashTraits<ExternalType>::emptyValue();
+        ExternalType result = HandleTypes<MappedType>::getFromSlot(slot);
+        HandleHeap::heapFor(slot)->deallocate(slot);
         return result;
-    if (!Heap::isCellMarked(result))
-        return HashTraits<MappedType>::emptyValue();
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value)
-{
-    Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now.
-    pair<iterator, bool> result = m_map.add(key, value);
-    if (!result.second) { // pre-existing entry
-        result.second = !Heap::isCellMarked(result.first->second);
-        result.first->second = value;
     }
-    return result;
-}
-
-template<typename KeyType, typename MappedType>
-bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value)
-{
-    iterator it = m_map.find(key);
-    if (it == m_map.end())
-        return false;
-    if (it->second != value)
-        return false;
-    m_map.remove(it);
-    return true;
-}
+
+    size_t size() { return m_map.size(); }
+
+    iterator begin() { return iterator(m_map.begin()); }
+    iterator end() { return iterator(m_map.end()); }
+    
+    ~WeakGCMap()
+    {
+        clear();
+    }
+    
+private:
+    virtual void finalize(Handle<Unknown> handle, void* context)
+    {
+        HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot())));
+        ASSERT(slot);
+        HandleHeap::heapFor(slot)->deallocate(slot);
+    }
+
+    MapType m_map;
+};
 
 } // namespace JSC
 
diff --git a/runtime/WeakGCPtr.h b/runtime/WeakGCPtr.h
deleted file mode 100644 (file)
index 9dce858..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2009 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. AND ITS CONTRIBUTORS ``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 ITS 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 WeakGCPtr_h
-#define WeakGCPtr_h
-
-#include "Collector.h"
-#include <wtf/Noncopyable.h>
-
-namespace JSC {
-
-// A smart pointer whose get() function returns 0 for cells awaiting destruction.
-template <typename T> class WeakGCPtr : Noncopyable {
-public:
-    WeakGCPtr() : m_ptr(0) { }
-    WeakGCPtr(T* ptr) { assign(ptr); }
-
-    T* get() const
-    {
-        if (!m_ptr || !Heap::isCellMarked(m_ptr))
-            return 0;
-        return m_ptr;
-    }
-    
-    bool clear(JSCell* ptr)
-    {
-        if (ptr == m_ptr) {
-            m_ptr = 0;
-            return true;
-        }
-        return false;
-    }
-
-    T& operator*() const { return *get(); }
-    T* operator->() const { return get(); }
-    
-    bool operator!() const { return !get(); }
-
-    // This conversion operator allows implicit conversion to bool but not to other integer types.
-#if COMPILER(WINSCW)
-    operator bool() const { return m_ptr; }
-#else
-    typedef T* WeakGCPtr::*UnspecifiedBoolType;
-    operator UnspecifiedBoolType() const { return get() ? &WeakGCPtr::m_ptr : 0; }
-#endif
-
-    WeakGCPtr& operator=(T*);
-
-#if !ASSERT_DISABLED
-    bool hasDeadObject() const { return !!m_ptr; }
-#endif
-
-private:
-    void assign(T* ptr)
-    {
-        ASSERT(ptr);
-        Heap::markCell(ptr);
-        m_ptr = ptr;
-    }
-
-    T* m_ptr;
-};
-
-template <typename T> inline WeakGCPtr<T>& WeakGCPtr<T>::operator=(T* optr)
-{
-    assign(optr);
-    return *this;
-}
-
-template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b)
-{ 
-    return a.get() == b.get(); 
-}
-
-template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, U* b)
-{ 
-    return a.get() == b; 
-}
-
-template <typename T, typename U> inline bool operator==(T* a, const WeakGCPtr<U>& b) 
-{
-    return a == b.get(); 
-}
-
-template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b)
-{ 
-    return a.get() != b.get(); 
-}
-
-template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, U* b)
-{
-    return a.get() != b; 
-}
-
-template <typename T, typename U> inline bool operator!=(T* a, const WeakGCPtr<U>& b)
-{ 
-    return a != b.get(); 
-}
-
-template <typename T, typename U> inline WeakGCPtr<T> static_pointer_cast(const WeakGCPtr<U>& p)
-{ 
-    return WeakGCPtr<T>(static_cast<T*>(p.get())); 
-}
-
-template <typename T, typename U> inline WeakGCPtr<T> const_pointer_cast(const WeakGCPtr<U>& p)
-{ 
-    return WeakGCPtr<T>(const_cast<T*>(p.get())); 
-}
-
-template <typename T> inline T* getPtr(const WeakGCPtr<T>& p)
-{
-    return p.get();
-}
-
-} // namespace JSC
-
-#endif // WeakGCPtr_h
index ff3995e80a95d973cbe93166c24981509c656f52..6083980d222a385ff9aa780f25841ab4df8b2247 100644 (file)
@@ -68,6 +68,11 @@ public:
         return advance() / (UINT_MAX + 1.0);
     }
 
+    unsigned getUint32()
+    {
+        return advance();
+    }
+
 private:
     unsigned advance()
     {
diff --git a/runtime/WriteBarrier.h b/runtime/WriteBarrier.h
new file mode 100644 (file)
index 0000000..8998947
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 WriteBarrier_h
+#define WriteBarrier_h
+
+#include "HandleTypes.h"
+#include "Heap.h"
+#include "TypeTraits.h"
+
+namespace JSC {
+
+class JSCell;
+class JSGlobalData;
+class JSGlobalObject;
+
+template<class T> class WriteBarrierBase;
+template<> class WriteBarrierBase<JSValue>;
+
+void slowValidateCell(JSCell*);
+void slowValidateCell(JSGlobalObject*);
+    
+#if ENABLE(GC_VALIDATION)
+template<class T> inline void validateCell(T cell)
+{
+    ASSERT_GC_OBJECT_INHERITS(cell, &WTF::RemovePointer<T>::Type::s_info);
+}
+
+template<> inline void validateCell<JSCell*>(JSCell* cell)
+{
+    slowValidateCell(cell);
+}
+
+template<> inline void validateCell<JSGlobalObject*>(JSGlobalObject* globalObject)
+{
+    slowValidateCell(globalObject);
+}
+#else
+template<class T> inline void validateCell(T)
+{
+}
+#endif
+
+// We have a separate base class with no constructors for use in Unions.
+template <typename T> class WriteBarrierBase {
+public:
+    void set(JSGlobalData& globalData, const JSCell* owner, T* value)
+    {
+        ASSERT(value);
+        validateCell(value);
+        setEarlyValue(globalData, owner, value);
+    }
+
+    void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
+    {
+        if (value)
+            validateCell(value);
+        setEarlyValue(globalData, owner, value);
+    }
+
+    // Should only be used by JSCell during early initialisation
+    // when some basic types aren't yet completely instantiated
+    void setEarlyValue(JSGlobalData&, const JSCell* owner, T* value)
+    {
+        this->m_cell = reinterpret_cast<JSCell*>(value);
+        Heap::writeBarrier(owner, this->m_cell);
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie(owner));
+        ASSERT(!isZombie(m_cell));
+#endif
+    }
+    
+    T* get() const
+    {
+        if (m_cell)
+            validateCell(m_cell);
+        return reinterpret_cast<T*>(m_cell);
+    }
+
+    T* operator*() const
+    {
+        ASSERT(m_cell);
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie(m_cell));
+#endif
+        validateCell<T>(static_cast<T*>(m_cell));
+        return static_cast<T*>(m_cell);
+    }
+
+    T* operator->() const
+    {
+        ASSERT(m_cell);
+        validateCell(static_cast<T*>(m_cell));
+        return static_cast<T*>(m_cell);
+    }
+
+    void clear() { m_cell = 0; }
+    
+    JSCell** slot() { return &m_cell; }
+    
+    typedef T* (WriteBarrierBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    
+    bool operator!() const { return !m_cell; }
+
+    void setWithoutWriteBarrier(T* value)
+    {
+        this->m_cell = reinterpret_cast<JSCell*>(value);
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!m_cell || !isZombie(m_cell));
+#endif
+    }
+
+#if ENABLE(GC_VALIDATION)
+    T* unvalidatedGet() const { return reinterpret_cast<T*>(m_cell); }
+#endif
+
+private:
+    JSCell* m_cell;
+};
+
+template <> class WriteBarrierBase<Unknown> {
+public:
+    void set(JSGlobalData&, const JSCell* owner, JSValue value)
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!isZombie(owner));
+        ASSERT(!value.isZombie());
+#endif
+        m_value = JSValue::encode(value);
+        Heap::writeBarrier(owner, value);
+    }
+
+    void setWithoutWriteBarrier(JSValue value)
+    {
+#if ENABLE(JSC_ZOMBIES)
+        ASSERT(!value.isZombie());
+#endif
+        m_value = JSValue::encode(value);
+    }
+
+    JSValue get() const
+    {
+        return JSValue::decode(m_value);
+    }
+    void clear() { m_value = JSValue::encode(JSValue()); }
+    void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
+    bool isNumber() const { return get().isNumber(); }
+    bool isObject() const { return get().isObject(); }
+    bool isNull() const { return get().isNull(); }
+    bool isGetterSetter() const { return get().isGetterSetter(); }
+    
+    JSValue* slot()
+    { 
+        union {
+            EncodedJSValue* v;
+            JSValue* slot;
+        } u;
+        u.v = &m_value;
+        return u.slot;
+    }
+    
+    typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+    bool operator!() const { return !get(); } 
+    
+private:
+    EncodedJSValue m_value;
+};
+
+template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
+public:
+    WriteBarrier()
+    {
+        this->setWithoutWriteBarrier(0);
+    }
+
+    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
+    {
+        this->set(globalData, owner, value);
+    }
+
+    enum MayBeNullTag { MayBeNull };
+    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value, MayBeNullTag)
+    {
+        this->setMayBeNull(globalData, owner, value);
+    }
+};
+
+template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
+public:
+    WriteBarrier()
+    {
+        this->setWithoutWriteBarrier(JSValue());
+    }
+
+    WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
+    {
+        this->set(globalData, owner, value);
+    }
+};
+
+template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
+{
+    return lhs.get() == rhs.get();
+}
+
+// MarkStack functions
+
+template<typename T> inline void MarkStack::append(WriteBarrierBase<T>* slot)
+{
+    internalAppend(*slot->slot());
+}
+
+inline void MarkStack::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count, MarkSetProperties properties)
+{
+    JSValue* values = barriers->slot();
+#if ENABLE(GC_VALIDATION)
+    validateSet(values, count);
+#endif
+    if (count)
+        m_markSets.append(MarkSet(values, values + count, properties));
+}
+
+} // namespace JSC
+
+#endif // WriteBarrier_h
diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a327204
--- /dev/null
@@ -0,0 +1,25 @@
+SET(JSC_HEADERS
+)
+
+SET(JSC_SOURCES
+    ../jsc.cpp
+)
+
+SET(JSC_LIBRARIES
+    ${JavaScriptCore_LIBRARY_NAME}
+)
+
+INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/shell/CMakeLists${PORT}.txt)
+
+WEBKIT_WRAP_SOURCELIST(${JSC_SOURCES})
+INCLUDE_DIRECTORIES(./ ${JavaScriptCore_INCLUDE_DIRECTORIES})
+ADD_EXECUTABLE(${JSC_EXECUTABLE_NAME} ${JSC_HEADERS} ${JSC_SOURCES})
+TARGET_LINK_LIBRARIES(${JSC_EXECUTABLE_NAME} ${JSC_LIBRARIES})
+
+IF (JSC_LINK_FLAGS)
+    ADD_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} LINK_FLAGS "${JSC_LINK_FLAGS}")
+ENDIF ()
+
+IF (SHARED_CORE)
+    SET_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} PROPERTIES VERSION ${PROJECT_VERSION})
+ENDIF ()
diff --git a/shell/CMakeListsEfl.txt b/shell/CMakeListsEfl.txt
new file mode 100644 (file)
index 0000000..58d44f4
--- /dev/null
@@ -0,0 +1,8 @@
+LIST(APPEND JSC_LIBRARIES
+    ${Glib_LIBRARIES}
+    ${ECORE_LIBRARIES}
+)
+
+LIST(APPEND JSC_LINK_FLAGS
+    ${ECORE_LDFLAGS}
+)
diff --git a/shell/CMakeListsWinCE.txt b/shell/CMakeListsWinCE.txt
new file mode 100644 (file)
index 0000000..0b7a3bf
--- /dev/null
@@ -0,0 +1,3 @@
+LIST(APPEND JSC_SOURCES
+    ../os-win32/WinMain.cpp
+)
index fdcb4e96c5114bbc62e672844f6580afa56f0e61..7dd958b9814d3265eb69a63b6c0f6c65470aa4a0 100644 (file)
@@ -7,11 +7,11 @@
 <p class='results_summary'>
 Test List: All tests<br>
 Skip List: ecma/Date/15.9.2.1.js, ecma/Date/15.9.2.2-1.js, ecma/Date/15.9.2.2-2.js, ecma/Date/15.9.2.2-3.js, ecma/Date/15.9.2.2-4.js, ecma/Date/15.9.2.2-5.js, ecma/Date/15.9.2.2-6.js, ecma_3/Date/15.9.5.7.js<br>
-1127 test(s) selected, 1119 test(s) completed, 49 failures reported (4.37% failed)<br>
-Engine command line: "/Volumes/Big/ggaren/build/Debug/jsc" <br>
-OS type: Darwin il0301a-dhcp53.apple.com 9.7.0 Darwin Kernel Version 9.7.0: Tue Mar 31 22:52:17 PDT 2009; root:xnu-1228.12.14~1/RELEASE_I386 i386<br>
-Testcase execution time: 3 minutes, 18 seconds.<br>
-Tests completed on Tue Apr 21 12:56:28 2009.<br><br>
+1127 test(s) selected, 1119 test(s) completed, 51 failures reported (4.55% failed)<br>
+Engine command line: "/Volumes/BigData/git/WebKit/WebKitBuild/Debug/jsc" <br>
+OS type: Darwin 10.6.0 Darwin Kernel Version 10.6.0: Wed Nov 10 18:13:17 PST 2010; root:xnu-1504.9.26~3/RELEASE_I386 i386<br>
+Testcase execution time: 1 minutes, 3 seconds.<br>
+Tests completed on Wed Jan 19 13:26:57 2011.<br><br>
 [ <a href='#fail_detail'>Failure Details</a> | <a href='#retest_list'>Retest List</a> | <a href='menu.html'>Test Selection Page</a> ]<br>
 <hr>
 <a name='fail_detail'></a>
@@ -22,7 +22,6 @@ Tests completed on Tue Apr 21 12:56:28 2009.<br><br>
 Failure messages were:<br>
 - "-0x123456789abcde8" = NaN FAILED! expected: 81985529216486880<br>
 - "-0x123456789abcde8" = NaN FAILED! expected: 81985529216486880<br>
--"\u20001234\u2001" = NaN FAILED! expected: -1234<br>
 </tt><br>
 <a name='failure2'></a><dd><b>Testcase <a target='other_window' href='./ecma_2/Exceptions/function-001.js'>ecma_2/Exceptions/function-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
  [ <a href='#failure1'>Previous Failure</a> | <a href='#failure3'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
@@ -30,159 +29,67 @@ Failure messages were:<br>
 Failure messages were:<br>
 eval("function f(){}function g(){}") (threw no exception thrown = fail FAILED! expected: pass<br>
 </tt><br>
-<a name='failure3'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/FunExpr/fe-001.js'>ecma_3/FunExpr/fe-001.js</a> failed</b> <br>
+<a name='failure3'></a><dd><b>Testcase <a target='other_window' href='./ecma_2/RegExp/regress-001.js'>ecma_2/RegExp/regress-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=2157' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=2157</a><br>
  [ <a href='#failure2'>Previous Failure</a> | <a href='#failure4'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+RegExp/hex-001.js JS regexp anchoring on empty match bug<br>
+BUGNUMBER: http://bugzilla.mozilla.org/show_bug.cgi?id=2157<br>
+</tt><br>
+<a name='failure4'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/FunExpr/fe-001.js'>ecma_3/FunExpr/fe-001.js</a> failed</b> <br>
+ [ <a href='#failure3'>Previous Failure</a> | <a href='#failure5'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: Function Expression Statements basic test.<br>
 Failure messages were:<br>
 FAILED!: [reported from test()] Both functions were defined.<br>
 FAILED!: [reported from test()] Expected value '1', Actual value '0'<br>
 FAILED!: [reported from test()] <br>
 </tt><br>
-<a name='failure4'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/15.10.2-1.js'>ecma_3/RegExp/15.10.2-1.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=(none)' target='other_window'>Bug Number (none)</a><br>
- [ <a href='#failure3'>Previous Failure</a> | <a href='#failure5'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt>STATUS: RegExp conformance test<br>
-Failure messages were:<br>
-FAILED!: [reported from test()] Section 7 of test -<br>
-FAILED!: [reported from test()] regexp = /(z)((a+)?(b+)?(c))*/<br>
-FAILED!: [reported from test()] string = 'zaacbbbcac'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["zaacbbbcac", "z", "ac", "a", , "c"]<br>
-FAILED!: [reported from test()] Actual: ["zaacbbbcac", "z", "ac", "a", "bbb", "c"]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 8 of test -<br>
-FAILED!: [reported from test()] regexp = /(a*)*/<br>
-FAILED!: [reported from test()] string = 'b'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["", , ]<br>
-FAILED!: [reported from test()] Actual: ["", ""]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 12 of test -<br>
-FAILED!: [reported from test()] regexp = /(.*?)a(?!(a+)b\2c)\2(.*)/<br>
-FAILED!: [reported from test()] string = 'baaabaac'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["baaabaac", "ba", , "abaac"]<br>
-FAILED!: [reported from test()] Actual: ["baaabaac", "ba", "aa", "abaac"]<br>
-FAILED!: [reported from test()] <br>
-</tt><br>
-<a name='failure5'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/perlstress-001.js'>ecma_3/RegExp/perlstress-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=85721' target='other_window'>Bug Number 85721</a><br>
+<a name='failure5'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Statements/regress-194364.js'>ecma_3/Statements/regress-194364.js</a> failed</b> <br>
  [ <a href='#failure4'>Previous Failure</a> | <a href='#failure6'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt>STATUS: Testing regular expression edge cases<br>
-Failure messages were:<br>
-FAILED!: [reported from test()] Section 218 of test -<br>
-FAILED!: [reported from test()] regexp = /((foo)|(bar))*/<br>
-FAILED!: [reported from test()] string = 'foobar'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["foobar", "bar", , "bar"]<br>
-FAILED!: [reported from test()] Actual: ["foobar", "bar", "foo", "bar"]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 234 of test -<br>
-FAILED!: [reported from test()] regexp = /(?:(f)(o)(o)|(b)(a)(r))*/<br>
-FAILED!: [reported from test()] string = 'foobar'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["foobar", , , , "b", "a", "r"]<br>
-FAILED!: [reported from test()] Actual: ["foobar", "f", "o", "o", "b", "a", "r"]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 241 of test -<br>
-FAILED!: [reported from test()] regexp = /^(?:b|a(?=(.)))*\1/<br>
-FAILED!: [reported from test()] string = 'abc'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["ab", , ]<br>
-FAILED!: [reported from test()] Actual: ["ab", "b"]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 412 of test -<br>
-FAILED!: [reported from test()] regexp = /^(a(b)?)+$/<br>
-FAILED!: [reported from test()] string = 'aba'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["aba", "a", , ]<br>
-FAILED!: [reported from test()] Actual: ["aba", "a", "b"]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 413 of test -<br>
-FAILED!: [reported from test()] regexp = /^(aa(bb)?)+$/<br>
-FAILED!: [reported from test()] string = 'aabbaa'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["aabbaa", "aa", , ]<br>
-FAILED!: [reported from test()] Actual: ["aabbaa", "aa", "bb"]<br>
-FAILED!: [reported from test()] <br>
-</tt><br>
-<a name='failure6'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/RegExp/regress-209919.js'>ecma_3/RegExp/regress-209919.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=209919' target='other_window'>Bug Number 209919</a><br>
- [ <a href='#failure5'>Previous Failure</a> | <a href='#failure7'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt>STATUS: Testing regexp submatches with quantifiers<br>
-Failure messages were:<br>
-FAILED!: [reported from test()] Section 1 of test -<br>
-FAILED!: [reported from test()] regexp = /(a|b*)*/<br>
-FAILED!: [reported from test()] string = 'a'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["a", "a"]<br>
-FAILED!: [reported from test()] Actual: ["a", ""]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 3 of test -<br>
-FAILED!: [reported from test()] regexp = /(b*)*/<br>
-FAILED!: [reported from test()] string = 'a'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["", , ]<br>
-FAILED!: [reported from test()] Actual: ["", ""]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 5 of test -<br>
-FAILED!: [reported from test()] regexp = /^\-?(\d{1,}|\.{0,})*(\,\d{1,})?$/<br>
-FAILED!: [reported from test()] string = '100.00'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["100.00", "00", , ]<br>
-FAILED!: [reported from test()] Actual: ["100.00", "", , ]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 6 of test -<br>
-FAILED!: [reported from test()] regexp = /^\-?(\d{1,}|\.{0,})*(\,\d{1,})?$/<br>
-FAILED!: [reported from test()] string = '100,00'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["100,00", "100", ",00"]<br>
-FAILED!: [reported from test()] Actual: ["100,00", "", ",00"]<br>
-FAILED!: [reported from test()] <br>
-FAILED!: [reported from test()] Section 7 of test -<br>
-FAILED!: [reported from test()] regexp = /^\-?(\d{1,}|\.{0,})*(\,\d{1,})?$/<br>
-FAILED!: [reported from test()] string = '1.000,00'<br>
-FAILED!: [reported from test()] ERROR !!! regexp failed to give expected match array:<br>
-FAILED!: [reported from test()] Expect: ["1.000,00", "000", ",00"]<br>
-FAILED!: [reported from test()] Actual: ["1.000,00", "", ",00"]<br>
-FAILED!: [reported from test()] <br>
-</tt><br>
-<a name='failure7'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Statements/regress-194364.js'>ecma_3/Statements/regress-194364.js</a> failed</b> <br>
- [ <a href='#failure6'>Previous Failure</a> | <a href='#failure8'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure8'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Unicode/uc-001.js'>ecma_3/Unicode/uc-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=23610' target='other_window'>Bug Number 23610</a><br>
- [ <a href='#failure7'>Previous Failure</a> | <a href='#failure9'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure6'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Unicode/uc-001.js'>ecma_3/Unicode/uc-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=23610' target='other_window'>Bug Number 23610</a><br>
+ [ <a href='#failure5'>Previous Failure</a> | <a href='#failure7'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: Unicode format-control character (Category Cf) test.<br>
 Failure messages were:<br>
 FAILED!: [reported from test()] Unicode format-control character test (Category Cf.)<br>
 FAILED!: [reported from test()] Expected value 'no error', Actual value 'no‎ error'<br>
 FAILED!: [reported from test()] <br>
 </tt><br>
-<a name='failure9'></a><dd><b>Testcase <a target='other_window' href='./js1_2/Objects/toString-001.js'>js1_2/Objects/toString-001.js</a> failed</b> <br>
- [ <a href='#failure8'>Previous Failure</a> | <a href='#failure10'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
-<tt><br>
-Failure messages were:<br>
-var o = new Object(); o.toString() = [object Object] FAILED! expected: {}<br>
-o = {}; o.toString() = [object Object] FAILED! expected: {}<br>
-o = { name:"object", length:0, value:"hello" }; o.toString() = false FAILED! expected: true<br>
+<a name='failure7'></a><dd><b>Testcase <a target='other_window' href='./js1_2/Objects/toString-001.js'>js1_2/Objects/toString-001.js</a> failed</b> <br>
+ [ <a href='#failure6'>Previous Failure</a> | <a href='#failure8'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+JS1_2 Object.toString()<br>
 </tt><br>
-<a name='failure10'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/Function_object.js'>js1_2/function/Function_object.js</a> failed</b> <br>
- [ <a href='#failure9'>Previous Failure</a> | <a href='#failure11'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure8'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/Function_object.js'>js1_2/function/Function_object.js</a> failed</b> <br>
+ [ <a href='#failure7'>Previous Failure</a> | <a href='#failure9'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 f.arity = undefined FAILED! expected: 3<br>
 } FAILED! expected: <br>
 </tt><br>
-<a name='failure11'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/function-001-n.js'>js1_2/function/function-001-n.js</a> failed</b> <br>
- [ <a href='#failure10'>Previous Failure</a> | <a href='#failure12'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure9'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/function-001-n.js'>js1_2/function/function-001-n.js</a> failed</b> <br>
+ [ <a href='#failure8'>Previous Failure</a> | <a href='#failure10'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 3, got 0<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 function-001.js functions not separated by semicolons are errors in version 120 and higher<br>
 eval("function f(){}function g(){}") = undefined FAILED! expected: error<br>
 </tt><br>
-<a name='failure12'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-1.js'>js1_2/function/tostring-1.js</a> failed</b> <br>
- [ <a href='#failure11'>Previous Failure</a> | <a href='#failure13'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure10'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/regexparg-1.js'>js1_2/function/regexparg-1.js</a> failed</b> <br>
+ [ <a href='#failure9'>Previous Failure</a> | <a href='#failure11'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+JS_1.2 The variable statment<br>
+</tt><br>
+<a name='failure11'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-1.js'>js1_2/function/tostring-1.js</a> failed</b> <br>
+ [ <a href='#failure10'>Previous Failure</a> | <a href='#failure12'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 } FAILED! expected: <br>
@@ -191,8 +98,8 @@ Failure messages were:<br>
 } FAILED! expected: <br>
 } FAILED! expected: <br>
 </tt><br>
-<a name='failure13'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-2.js'>js1_2/function/tostring-2.js</a> failed</b> <br>
- [ <a href='#failure12'>Previous Failure</a> | <a href='#failure14'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure12'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-2.js'>js1_2/function/tostring-2.js</a> failed</b> <br>
+ [ <a href='#failure11'>Previous Failure</a> | <a href='#failure13'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 } FAILED! expected: <br>
@@ -205,22 +112,22 @@ Failure messages were:<br>
 } FAILED! expected: <br>
 } FAILED! expected: <br>
 </tt><br>
-<a name='failure14'></a><dd><b>Testcase <a target='other_window' href='./js1_2/operator/equality.js'>js1_2/operator/equality.js</a> failed</b> <br>
- [ <a href='#failure13'>Previous Failure</a> | <a href='#failure15'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure13'></a><dd><b>Testcase <a target='other_window' href='./js1_2/operator/equality.js'>js1_2/operator/equality.js</a> failed</b> <br>
+ [ <a href='#failure12'>Previous Failure</a> | <a href='#failure14'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 (new String('x') == 'x')                  = true FAILED! expected: false<br>
 ('x' == new String('x'))                  = true FAILED! expected: false<br>
 </tt><br>
-<a name='failure15'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_lastIndex.js'>js1_2/regexp/RegExp_lastIndex.js</a> failed</b> <br>
- [ <a href='#failure14'>Previous Failure</a> | <a href='#failure16'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure14'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_lastIndex.js'>js1_2/regexp/RegExp_lastIndex.js</a> failed</b> <br>
+ [ <a href='#failure13'>Previous Failure</a> | <a href='#failure15'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 re=/x./g; re.lastIndex=4; re.exec('xyabcdxa') = xa FAILED! expected: ["xa"]<br>
 re.exec('xyabcdef') = xy FAILED! expected: ["xy"]<br>
 </tt><br>
-<a name='failure16'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline.js'>js1_2/regexp/RegExp_multiline.js</a> failed</b> <br>
- [ <a href='#failure15'>Previous Failure</a> | <a href='#failure17'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure15'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline.js'>js1_2/regexp/RegExp_multiline.js</a> failed</b> <br>
+ [ <a href='#failure14'>Previous Failure</a> | <a href='#failure16'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 (multiline == true) '123\n456'.match(/^4../) = null FAILED! expected: 456<br>
@@ -229,8 +136,8 @@ Failure messages were:<br>
 (multiline == true) 'a11\na22\na23\na24'.match(/a..$/g) = a24 FAILED! expected: a11,a22,a23,a24<br>
 (multiline == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) = a24 FAILED! expected: a11,a22,a23,a24<br>
 </tt><br>
-<a name='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline_as_array.js'>js1_2/regexp/RegExp_multiline_as_array.js</a> failed</b> <br>
- [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure16'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline_as_array.js'>js1_2/regexp/RegExp_multiline_as_array.js</a> failed</b> <br>
+ [ <a href='#failure15'>Previous Failure</a> | <a href='#failure17'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 (['$*'] == true) '123\n456'.match(/^4../) = null FAILED! expected: 456<br>
@@ -239,20 +146,42 @@ Failure messages were:<br>
 (['$*'] == true) 'a11\na22\na23\na24'.match(/a..$/g) = a24 FAILED! expected: a11,a22,a23,a24<br>
 (['$*'] == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) = a24 FAILED! expected: a11,a22,a23,a24<br>
 </tt><br>
-<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/beginLine.js'>js1_2/regexp/beginLine.js</a> failed</b> <br>
- [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/beginLine.js'>js1_2/regexp/beginLine.js</a> failed</b> <br>
+ [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 123xyz'.match(new RegExp('^\d+')) = null FAILED! expected: 123<br>
 </tt><br>
-<a name='failure19'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/endLine.js'>js1_2/regexp/endLine.js</a> failed</b> <br>
- [ <a href='#failure18'>Previous Failure</a> | <a href='#failure20'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/endLine.js'>js1_2/regexp/endLine.js</a> failed</b> <br>
+ [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 xyz'.match(new RegExp('\d+$')) = null FAILED! expected: 890<br>
 </tt><br>
-<a name='failure20'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/string_split.js'>js1_2/regexp/string_split.js</a> failed</b> <br>
+<a name='failure19'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/regress-6359.js'>js1_2/regexp/regress-6359.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=6359' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=6359</a><br>
+ [ <a href='#failure18'>Previous Failure</a> | <a href='#failure20'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+BUGNUMBER: http://bugzilla.mozilla.org/show_bug.cgi?id=6359<br>
+</tt><br>
+<a name='failure20'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/regress-9141.js'>js1_2/regexp/regress-9141.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=9141' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=9141</a><br>
  [ <a href='#failure19'>Previous Failure</a> | <a href='#failure21'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+BUGNUMBER: http://bugzilla.mozilla.org/show_bug.cgi?id=9141<br>
+</tt><br>
+<a name='failure21'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/simple_form.js'>js1_2/regexp/simple_form.js</a> failed</b> <br>
+ [ <a href='#failure20'>Previous Failure</a> | <a href='#failure22'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<tt>Expected exit code 0, got 3<br>
+Testcase terminated with signal 0<br>
+Complete testcase output was:<br>
+Executing script: simple_form.js<br>
+As described in Netscape doc "Whats new in JavaScript 1.2" RegExp: simple form<br>
+</tt><br>
+<a name='failure22'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/string_split.js'>js1_2/regexp/string_split.js</a> failed</b> <br>
+ [ <a href='#failure21'>Previous Failure</a> | <a href='#failure23'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 'abc'.split(/[a-z]/) = ,,, FAILED! expected: ,,<br>
@@ -260,22 +189,22 @@ Failure messages were:<br>
 'abc'.split(new RegExp('[a-z]')) = ,,, FAILED! expected: ,,<br>
 'abc'.split(new RegExp('[a-z]')) = ,,, FAILED! expected: ,,<br>
 </tt><br>
-<a name='failure21'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/boolean-001.js'>js1_2/version120/boolean-001.js</a> failed</b> <br>
- [ <a href='#failure20'>Previous Failure</a> | <a href='#failure22'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure23'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/boolean-001.js'>js1_2/version120/boolean-001.js</a> failed</b> <br>
+ [ <a href='#failure22'>Previous Failure</a> | <a href='#failure24'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt><br>
 Failure messages were:<br>
 new Boolean(false) = true FAILED! expected: false<br>
 </tt><br>
-<a name='failure22'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/regress-99663.js'>js1_2/version120/regress-99663.js</a> failed</b> <br>
- [ <a href='#failure21'>Previous Failure</a> | <a href='#failure23'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure24'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/regress-99663.js'>js1_2/version120/regress-99663.js</a> failed</b> <br>
+ [ <a href='#failure23'>Previous Failure</a> | <a href='#failure25'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: Regression test for Bugzilla bug 99663<br>
 Failure messages were:<br>
 Section 1 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br>
 Section 2 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br>
 Section 3 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br>
 </tt><br>
-<a name='failure23'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/function-001-n.js'>js1_3/Script/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
- [ <a href='#failure22'>Previous Failure</a> | <a href='#failure24'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure25'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/function-001-n.js'>js1_3/Script/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
+ [ <a href='#failure24'>Previous Failure</a> | <a href='#failure26'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 3, got 0<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
@@ -283,15 +212,15 @@ BUGNUMBER: 10278<br>
 function-001.js functions not separated by semicolons are errors in version 120 and higher<br>
 eval("function f(){}function g(){}") = undefined FAILED! expected: error<br>
 </tt><br>
-<a name='failure24'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/script-001.js'>js1_3/Script/script-001.js</a> failed</b> <br>
- [ <a href='#failure23'>Previous Failure</a> | <a href='#failure25'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure26'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/script-001.js'>js1_3/Script/script-001.js</a> failed</b> <br>
+ [ <a href='#failure25'>Previous Failure</a> | <a href='#failure27'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 script-001 NativeScript<br>
 </tt><br>
-<a name='failure25'></a><dd><b>Testcase <a target='other_window' href='./js1_3/regress/function-001-n.js'>js1_3/regress/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
- [ <a href='#failure24'>Previous Failure</a> | <a href='#failure26'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure27'></a><dd><b>Testcase <a target='other_window' href='./js1_3/regress/function-001-n.js'>js1_3/regress/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br>
+ [ <a href='#failure26'>Previous Failure</a> | <a href='#failure28'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 3, got 0<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
@@ -299,90 +228,90 @@ BUGNUMBER: 10278<br>
 function-001.js functions not separated by semicolons are errors in version 120 and higher<br>
 eval("function f(){}function g(){}") = undefined FAILED! expected: error<br>
 </tt><br>
-<a name='failure26'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-001.js'>js1_5/Exceptions/catchguard-001.js</a> failed</b> <br>
- [ <a href='#failure25'>Previous Failure</a> | <a href='#failure27'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure28'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-001.js'>js1_5/Exceptions/catchguard-001.js</a> failed</b> <br>
+ [ <a href='#failure27'>Previous Failure</a> | <a href='#failure29'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure27'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-002.js'>js1_5/Exceptions/catchguard-002.js</a> failed</b> <br>
- [ <a href='#failure26'>Previous Failure</a> | <a href='#failure28'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure29'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-002.js'>js1_5/Exceptions/catchguard-002.js</a> failed</b> <br>
+ [ <a href='#failure28'>Previous Failure</a> | <a href='#failure30'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure28'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br>
- [ <a href='#failure27'>Previous Failure</a> | <a href='#failure29'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure30'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br>
+ [ <a href='#failure29'>Previous Failure</a> | <a href='#failure31'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure29'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br>
- [ <a href='#failure28'>Previous Failure</a> | <a href='#failure30'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure31'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br>
+ [ <a href='#failure30'>Previous Failure</a> | <a href='#failure32'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure30'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/regress-50447.js'>js1_5/Exceptions/regress-50447.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=50447' target='other_window'>Bug Number 50447</a><br>
- [ <a href='#failure29'>Previous Failure</a> | <a href='#failure31'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure32'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/regress-50447.js'>js1_5/Exceptions/regress-50447.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=50447' target='other_window'>Bug Number 50447</a><br>
+ [ <a href='#failure31'>Previous Failure</a> | <a href='#failure33'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 BUGNUMBER: 50447<br>
 STATUS: Test (non-ECMA) Error object properties fileName, lineNumber<br>
 </tt><br>
-<a name='failure31'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br>
- [ <a href='#failure30'>Previous Failure</a> | <a href='#failure32'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure33'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br>
+ [ <a href='#failure32'>Previous Failure</a> | <a href='#failure34'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure32'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-002.js'>js1_5/GetSet/getset-002.js</a> failed</b> <br>
- [ <a href='#failure31'>Previous Failure</a> | <a href='#failure33'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure34'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-002.js'>js1_5/GetSet/getset-002.js</a> failed</b> <br>
+ [ <a href='#failure33'>Previous Failure</a> | <a href='#failure35'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure33'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br>
- [ <a href='#failure32'>Previous Failure</a> | <a href='#failure34'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure35'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br>
+ [ <a href='#failure34'>Previous Failure</a> | <a href='#failure36'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure34'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br>
- [ <a href='#failure33'>Previous Failure</a> | <a href='#failure35'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure36'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br>
+ [ <a href='#failure35'>Previous Failure</a> | <a href='#failure37'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure35'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br>
- [ <a href='#failure34'>Previous Failure</a> | <a href='#failure36'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure37'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br>
+ [ <a href='#failure36'>Previous Failure</a> | <a href='#failure38'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure36'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-001.js'>js1_5/Object/regress-96284-001.js</a> failed</b> <br>
- [ <a href='#failure35'>Previous Failure</a> | <a href='#failure37'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure38'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-001.js'>js1_5/Object/regress-96284-001.js</a> failed</b> <br>
+ [ <a href='#failure37'>Previous Failure</a> | <a href='#failure39'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure37'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-002.js'>js1_5/Object/regress-96284-002.js</a> failed</b> <br>
- [ <a href='#failure36'>Previous Failure</a> | <a href='#failure38'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure39'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-002.js'>js1_5/Object/regress-96284-002.js</a> failed</b> <br>
+ [ <a href='#failure38'>Previous Failure</a> | <a href='#failure40'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure38'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-44009.js'>js1_5/Regress/regress-44009.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=44009' target='other_window'>Bug Number 44009</a><br>
- [ <a href='#failure37'>Previous Failure</a> | <a href='#failure39'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure40'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-44009.js'>js1_5/Regress/regress-44009.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=44009' target='other_window'>Bug Number 44009</a><br>
+ [ <a href='#failure39'>Previous Failure</a> | <a href='#failure41'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 BUGNUMBER: 44009<br>
 STATUS: Testing that we don't crash on obj.toSource()<br>
 </tt><br>
-<a name='failure39'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-103602.js'>js1_5/Regress/regress-103602.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=103602' target='other_window'>Bug Number 103602</a><br>
- [ <a href='#failure38'>Previous Failure</a> | <a href='#failure40'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure41'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-103602.js'>js1_5/Regress/regress-103602.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=103602' target='other_window'>Bug Number 103602</a><br>
+ [ <a href='#failure40'>Previous Failure</a> | <a href='#failure42'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: Reassignment to a const is NOT an error per ECMA<br>
 Failure messages were:<br>
 FAILED!: [reported from test()] Section 1 of test -<br>
@@ -392,26 +321,26 @@ FAILED!: [reported from test()] Section 3 of test -<br>
 FAILED!: [reported from test()] Expected value '1', Actual value '2'<br>
 FAILED!: [reported from test()] <br>
 </tt><br>
-<a name='failure40'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-104077.js'>js1_5/Regress/regress-104077.js</a> failed</b> <br>
- [ <a href='#failure39'>Previous Failure</a> | <a href='#failure41'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure42'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-104077.js'>js1_5/Regress/regress-104077.js</a> failed</b> <br>
+ [ <a href='#failure41'>Previous Failure</a> | <a href='#failure43'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure41'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-127557.js'>js1_5/Regress/regress-127557.js</a> failed</b> <br>
- [ <a href='#failure40'>Previous Failure</a> | <a href='#failure42'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure43'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-127557.js'>js1_5/Regress/regress-127557.js</a> failed</b> <br>
+ [ <a href='#failure42'>Previous Failure</a> | <a href='#failure44'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure42'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-172699.js'>js1_5/Regress/regress-172699.js</a> failed</b> <br>
- [ <a href='#failure41'>Previous Failure</a> | <a href='#failure43'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure44'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-172699.js'>js1_5/Regress/regress-172699.js</a> failed</b> <br>
+ [ <a href='#failure43'>Previous Failure</a> | <a href='#failure45'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure43'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-179524.js'>js1_5/Regress/regress-179524.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=179524' target='other_window'>Bug Number 179524</a><br>
- [ <a href='#failure42'>Previous Failure</a> | <a href='#failure44'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure45'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-179524.js'>js1_5/Regress/regress-179524.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=179524' target='other_window'>Bug Number 179524</a><br>
+ [ <a href='#failure44'>Previous Failure</a> | <a href='#failure46'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: Don't crash on extraneous arguments to str.match(), etc.<br>
 Failure messages were:<br>
 FAILED!: [reported from test()] Section 14 of test -<br>
@@ -461,14 +390,14 @@ FAILED!: [reported from test()] Section 36 of test -<br>
 FAILED!: [reported from test()] Expected value 'SHOULD HAVE FALLEN INTO CATCH-BLOCK!', Actual value 'ABC Zbc'<br>
 FAILED!: [reported from test()] <br>
 </tt><br>
-<a name='failure44'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/regress-220584.js'>js1_5/Scope/regress-220584.js</a> failed</b> <br>
- [ <a href='#failure43'>Previous Failure</a> | <a href='#failure45'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure46'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/regress-220584.js'>js1_5/Scope/regress-220584.js</a> failed</b> <br>
+ [ <a href='#failure45'>Previous Failure</a> | <a href='#failure47'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure45'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/scope-001.js'>js1_5/Scope/scope-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=53268' target='other_window'>Bug Number 53268</a><br>
- [ <a href='#failure44'>Previous Failure</a> | <a href='#failure46'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure47'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/scope-001.js'>js1_5/Scope/scope-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=53268' target='other_window'>Bug Number 53268</a><br>
+ [ <a href='#failure46'>Previous Failure</a> | <a href='#failure48'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: Testing scope after changing obj.__proto__<br>
 Failure messages were:<br>
 FAILED!: [reported from test()] Step 1:  setting obj.__proto__ = global object<br>
@@ -479,8 +408,8 @@ FAILED!: [reported from test()] Type mismatch, expected type undefined, actual t
 FAILED!: [reported from test()] Expected value 'undefined', Actual value '1'<br>
 FAILED!: [reported from test()] <br>
 </tt><br>
-<a name='failure46'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-301574.js'>js1_6/Regress/regress-301574.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=301574' target='other_window'>Bug Number 301574</a><br>
- [ <a href='#failure45'>Previous Failure</a> | <a href='#failure47'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure48'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-301574.js'>js1_6/Regress/regress-301574.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=301574' target='other_window'>Bug Number 301574</a><br>
+ [ <a href='#failure47'>Previous Failure</a> | <a href='#failure49'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>STATUS: E4X should be enabled even when e4x=1 not specified<br>
 Failure messages were:<br>
 FAILED!: E4X should be enabled even when e4x=1 not specified: XML()<br>
@@ -490,20 +419,20 @@ FAILED!: E4X should be enabled even when e4x=1 not specified: XMLList()<br>
 FAILED!: Expected value 'No error', Actual value 'error: ReferenceError: Can't find variable: XML'<br>
 FAILED!: <br>
 </tt><br>
-<a name='failure47'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-309242.js'>js1_6/Regress/regress-309242.js</a> failed</b> <br>
- [ <a href='#failure46'>Previous Failure</a> | <a href='#failure48'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure49'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-309242.js'>js1_6/Regress/regress-309242.js</a> failed</b> <br>
+ [ <a href='#failure48'>Previous Failure</a> | <a href='#failure50'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure48'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-314887.js'>js1_6/Regress/regress-314887.js</a> failed</b> <br>
- [ <a href='#failure47'>Previous Failure</a> | <a href='#failure49'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure50'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-314887.js'>js1_6/Regress/regress-314887.js</a> failed</b> <br>
+ [ <a href='#failure49'>Previous Failure</a> | <a href='#failure51'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
 Testcase produced no output!</tt><br>
-<a name='failure49'></a><dd><b>Testcase <a target='other_window' href='./js1_6/String/regress-306591.js'>js1_6/String/regress-306591.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=306591' target='other_window'>Bug Number 306591</a><br>
- [ <a href='#failure48'>Previous Failure</a> | <a href='#failure50'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
+<a name='failure51'></a><dd><b>Testcase <a target='other_window' href='./js1_6/String/regress-306591.js'>js1_6/String/regress-306591.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=306591' target='other_window'>Bug Number 306591</a><br>
+ [ <a href='#failure50'>Previous Failure</a> | <a href='#failure52'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br>
 <tt>Expected exit code 0, got 3<br>
 Testcase terminated with signal 0<br>
 Complete testcase output was:<br>
@@ -517,20 +446,19 @@ STATUS: See https://bugzilla.mozilla.org/show_bug.cgi?id=304828<br>
 <pre>
 <a name='retest_list'></a>
 <h2>Retest List</h2><br>
-# Retest List, squirrelfish, generated Tue Apr 21 12:56:28 2009.
+# Retest List, squirrelfish, generated Wed Jan 19 13:26:57 2011.
 # Original test base was: All tests.
-# 1119 of 1127 test(s) were completed, 49 failures reported.
+# 1119 of 1127 test(s) were completed, 51 failures reported.
 ecma/TypeConversion/9.3.1-3.js
 ecma_2/Exceptions/function-001.js
+ecma_2/RegExp/regress-001.js
 ecma_3/FunExpr/fe-001.js
-ecma_3/RegExp/15.10.2-1.js
-ecma_3/RegExp/perlstress-001.js
-ecma_3/RegExp/regress-209919.js
 ecma_3/Statements/regress-194364.js
 ecma_3/Unicode/uc-001.js
 js1_2/Objects/toString-001.js
 js1_2/function/Function_object.js
 js1_2/function/function-001-n.js
+js1_2/function/regexparg-1.js
 js1_2/function/tostring-1.js
 js1_2/function/tostring-2.js
 js1_2/operator/equality.js
@@ -539,6 +467,9 @@ js1_2/regexp/RegExp_multiline.js
 js1_2/regexp/RegExp_multiline_as_array.js
 js1_2/regexp/beginLine.js
 js1_2/regexp/endLine.js
+js1_2/regexp/regress-6359.js
+js1_2/regexp/regress-9141.js
+js1_2/regexp/simple_form.js
 js1_2/regexp/string_split.js
 js1_2/version120/boolean-001.js
 js1_2/version120/regress-99663.js
index 01c145c1a5f24846a63eb054c8235fe1cc0aab66..26db14cf6d07d704e887dfccacc5b4b1f0aa36a4 100644 (file)
        testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.exec('2345')",
                                            String(["2345"]), String(/\d+/.exec('2345')));
 
-    // RegExp.input = "abcd12357efg"; /\d+/.exec()
+    // RegExp.input = "abcd12357efg"; /\d+/.exec(RegExp.input)
     RegExp.input = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.exec()",
-                                           String(["12357"]), String(/\d+/.exec()));
+       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.exec(RegExp.input)",
+                                           String(["12357"]), String(/\d+/.exec(RegExp.input)));
 
-    // RegExp.input = "abcd12357efg"; /[h-z]+/.exec()
+    // RegExp.input = "abcd12357efg"; /[h-z]+/.exec(RegExp.input)
     RegExp.input = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.exec()",
-                                           null, /[h-z]+/.exec());
+       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.exec(RegExp.input)",
+                                           null, /[h-z]+/.exec(RegExp.input));
 
     // RegExp.input = "abcd12357efg"; /\d+/.test('2345')
     RegExp.input = "abcd12357efg";
        testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.test('2345')",
                                            true, /\d+/.test('2345'));
 
-    // RegExp.input = "abcd12357efg"; /\d+/.test()
+    // RegExp.input = "abcd12357efg"; /\d+/.test(RegExp.input)
     RegExp.input = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.test()",
-                                           true, /\d+/.test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /\\d+/.test(RegExp.input)",
+                                           true, /\d+/.test(RegExp.input));
 
-    // RegExp.input = "abcd12357efg"; (new RegExp('d+')).test()
+    // RegExp.input = "abcd12357efg"; (new RegExp('d+')).test(RegExp.input)
     RegExp.input = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('d+')).test()",
-                                           true, (new RegExp('d+')).test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('d+')).test(RegExp.input)",
+                                           true, (new RegExp('d+')).test(RegExp.input));
 
-    // RegExp.input = "abcd12357efg"; /[h-z]+/.test()
+    // RegExp.input = "abcd12357efg"; /[h-z]+/.test(RegExp.input)
     RegExp.input = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.test()",
-                                           false, /[h-z]+/.test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; /[h-z]+/.test(RegExp.input)",
+                                           false, /[h-z]+/.test(RegExp.input));
 
-    // RegExp.input = "abcd12357efg"; (new RegExp('[h-z]+')).test()
+    // RegExp.input = "abcd12357efg"; (new RegExp('[h-z]+')).test(RegExp.input)
     RegExp.input = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('[h-z]+')).test()",
-                                           false, (new RegExp('[h-z]+')).test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp.input = 'abcd12357efg'; (new RegExp('[h-z]+')).test(RegExp.input)",
+                                           false, (new RegExp('[h-z]+')).test(RegExp.input));
 
        function test()
        {
index a1ed113c742904994b6d534cc44f8f4e873d6da8..9afdb14edf452e3cff6d27ada7fe47d304aafa11 100644 (file)
        testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec('2345')",
                                            String(["2345"]), String(/\d+/.exec('2345')));
 
-    // RegExp['$_'] = "abcd12357efg"; /\d+/.exec()
+    // RegExp['$_'] = "abcd12357efg"; /\d+/.exec(RegExp.input)
     RegExp['$_'] = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec()",
-                                           String(["12357"]), String(/\d+/.exec()));
+       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec(RegExp.input)",
+                                           String(["12357"]), String(/\d+/.exec(RegExp.input)));
 
-    // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.exec()
+    // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.exec(RegExp.input)
     RegExp['$_'] = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.exec()",
-                                           null, /[h-z]+/.exec());
+       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.exec(RegExp.input)",
+                                           null, /[h-z]+/.exec(RegExp.input));
 
     // RegExp['$_'] = "abcd12357efg"; /\d+/.test('2345')
     RegExp['$_'] = "abcd12357efg";
        testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.test('2345')",
                                            true, /\d+/.test('2345'));
 
-    // RegExp['$_'] = "abcd12357efg"; /\d+/.test()
+    // RegExp['$_'] = "abcd12357efg"; /\d+/.test(RegExp.input)
     RegExp['$_'] = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.test()",
-                                           true, /\d+/.test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.test(RegExp.input)",
+                                           true, /\d+/.test(RegExp.input));
 
-    // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.test()
+    // RegExp['$_'] = "abcd12357efg"; /[h-z]+/.test(RegExp.input)
     RegExp['$_'] = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.test()",
-                                           false, /[h-z]+/.test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /[h-z]+/.test(RegExp.input)",
+                                           false, /[h-z]+/.test(RegExp.input));
 
-    // RegExp['$_'] = "abcd12357efg"; (new RegExp('\d+')).test()
+    // RegExp['$_'] = "abcd12357efg"; (new RegExp('\d+')).test(RegExp.input)
     RegExp['$_'] = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('\d+')).test()",
-                                           true, (new RegExp('\d+')).test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('\d+')).test(RegExp.input)",
+                                           true, (new RegExp('\d+')).test(RegExp.input));
 
-    // RegExp['$_'] = "abcd12357efg"; (new RegExp('[h-z]+')).test()
+    // RegExp['$_'] = "abcd12357efg"; (new RegExp('[h-z]+')).test(RegExp.input)
     RegExp['$_'] = "abcd12357efg";
-       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('[h-z]+')).test()",
-                                           false, (new RegExp('[h-z]+')).test());
+       testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; (new RegExp('[h-z]+')).test(RegExp.input)",
+                                           false, (new RegExp('[h-z]+')).test(RegExp.input));
 
        function test()
        {
diff --git a/wscript b/wscript
index 61ad1fbc972b7dc2a165a12827e3d7137785b159..3df3ded546839691ffaddf95668c0b6996e5f414 100644 (file)
--- a/wscript
+++ b/wscript
@@ -29,47 +29,26 @@ import commands
 
 from settings import *
 
-jscore_excludes = ['jsc.cpp', 'ucptable.cpp']
-jscore_excludes.extend(get_excludes(jscore_dir, ['*Brew.cpp', '*CF.cpp', '*Symbian.cpp']))
-
-sources = []
+def build(bld):
 
-jscore_excludes.extend(get_excludes(jscore_dir, ['*None.cpp']))
+    import Options
 
-if building_on_win32:
-    jscore_excludes += ['ExecutableAllocatorPosix.cpp', 'MarkStackPosix.cpp', 'ThreadingPthreads.cpp']
-    sources += ['jit/ExecutableAllocatorWin.cpp', 'runtime/MarkStackWin.cpp']
-else:
-    jscore_excludes.append('JSStringRefBSTR.cpp')
-    jscore_excludes.extend(get_excludes(jscore_dir, ['*Win.cpp']))
+    jscore_excludes = ['jsc.cpp', 'ProfilerServer.mm', 'ExecutableAllocatorPosix.cpp']
+    jscore_excludes.extend(get_excludes(jscore_dir, ['*Brew.cpp', '*CF.cpp', '*Symbian.cpp']))
 
-def generate_jscore_derived_sources():
-    # build the derived sources
-    js_dir = jscore_dir
-    if building_on_win32:
-        js_dir = get_output('cygpath --unix "%s"' % js_dir)
-    derived_sources_dir = os.path.join(jscore_dir, 'DerivedSources')
-    if not os.path.exists(derived_sources_dir):
-        os.mkdir(derived_sources_dir)
+    jscore_excludes.extend(get_excludes(jscore_dir, ['*None.cpp']))
 
-    olddir = os.getcwd()
-    os.chdir(derived_sources_dir)
+    sources = []
 
-    command = 'make -f %s/DerivedSources.make JavaScriptCore=%s BUILT_PRODUCTS_DIR=%s all FEATURE_DEFINES="%s"' % (js_dir, js_dir, js_dir, ' '.join(feature_defines))
-    os.system(command)
-    os.chdir(olddir)
+    if Options.options.port == "wx":
+        if building_on_win32:
+            jscore_excludes += ['MarkStackPosix.cpp', 'OSAllocatorPosix.cpp', 'ThreadingPthreads.cpp']
+            sources += ['heap/MarkStackWin.cpp']
+        else:
+            jscore_excludes.append('JSStringRefBSTR.cpp')
+            jscore_excludes.extend(get_excludes(jscore_dir, ['*Win.cpp']))
 
-def set_options(opt):
-    common_set_options(opt)
-
-def configure(conf):
-    common_configure(conf)
-    generate_jscore_derived_sources()
-    
-def build(bld):
-    import Options
-
-    full_dirs = get_dirs_for_features(jscore_dir, features=[build_port], dirs=jscore_dirs)
+    full_dirs = get_dirs_for_features(jscore_dir, features=[Options.options.port.lower()], dirs=jscore_dirs)
 
     includes = common_includes + full_dirs
     if sys.platform.startswith('darwin'):
@@ -85,8 +64,8 @@ def build(bld):
         uselib_local = '',
         install_path = output_dir)
 
-    jscore.find_sources_in_dirs(full_dirs, excludes = jscore_excludes)  
-        
+    jscore.find_sources_in_dirs(full_dirs, excludes = jscore_excludes)
+    
     obj = bld.new_task_gen(
         features = 'cxx cprogram',
         includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes),
@@ -97,10 +76,10 @@ def build(bld):
         install_path = output_dir,
         )
         
-    # we'll get an error if exceptions are on because of an unwind error when using __try
     if building_on_win32:
-        flags = obj.env.CXXFLAGS
-        flags.remove('/EHsc')
-        obj.env.CXXFLAGS = flags
+        myenv = obj.env.copy()
+        myenv.CXXFLAGS = myenv.CXXFLAGS[:]
+        myenv.CXXFLAGS.remove('/EHsc')
+        obj.env = myenv
 
     bld.install_files(os.path.join(output_dir, 'JavaScriptCore'), 'API/*.h')
index b43bb378514c9fbb52908ba9c0b1a0edd6067aa1..83f274b7b1c1cbbe574cafa217a3b4dd397daadc 100644 (file)
@@ -49,6 +49,7 @@ namespace WTF {
     inline bool isASCII(wchar_t c) { return !(c & ~0x7F); }
 #endif
     inline bool isASCII(int c) { return !(c & ~0x7F); }
+    inline bool isASCII(unsigned c) { return !(c & ~0x7F); }
 
     inline bool isASCIIAlpha(char c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
     inline bool isASCIIAlpha(unsigned short c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
@@ -56,6 +57,7 @@ namespace WTF {
     inline bool isASCIIAlpha(wchar_t c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
 #endif
     inline bool isASCIIAlpha(int c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
+    inline bool isASCIIAlpha(unsigned c) { return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; }
 
     inline bool isASCIIAlphanumeric(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
     inline bool isASCIIAlphanumeric(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
@@ -63,6 +65,7 @@ namespace WTF {
     inline bool isASCIIAlphanumeric(wchar_t c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
 #endif
     inline bool isASCIIAlphanumeric(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
+    inline bool isASCIIAlphanumeric(unsigned c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'z'); }
 
     inline bool isASCIIDigit(char c) { return (c >= '0') & (c <= '9'); }
     inline bool isASCIIDigit(unsigned short c) { return (c >= '0') & (c <= '9'); }
@@ -70,6 +73,7 @@ namespace WTF {
     inline bool isASCIIDigit(wchar_t c) { return (c >= '0') & (c <= '9'); }
 #endif
     inline bool isASCIIDigit(int c) { return (c >= '0') & (c <= '9'); }
+    inline bool isASCIIDigit(unsigned c) { return (c >= '0') & (c <= '9'); }
 
     inline bool isASCIIHexDigit(char c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
     inline bool isASCIIHexDigit(unsigned short c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
@@ -77,6 +81,7 @@ namespace WTF {
     inline bool isASCIIHexDigit(wchar_t c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
 #endif
     inline bool isASCIIHexDigit(int c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
+    inline bool isASCIIHexDigit(unsigned c) { return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); }
 
     inline bool isASCIIOctalDigit(char c) { return (c >= '0') & (c <= '7'); }
     inline bool isASCIIOctalDigit(unsigned short c) { return (c >= '0') & (c <= '7'); }
@@ -84,6 +89,7 @@ namespace WTF {
     inline bool isASCIIOctalDigit(wchar_t c) { return (c >= '0') & (c <= '7'); }
 #endif
     inline bool isASCIIOctalDigit(int c) { return (c >= '0') & (c <= '7'); }
+    inline bool isASCIIOctalDigit(unsigned c) { return (c >= '0') & (c <= '7'); }
 
     inline bool isASCIILower(char c) { return c >= 'a' && c <= 'z'; }
     inline bool isASCIILower(unsigned short c) { return c >= 'a' && c <= 'z'; }
@@ -91,6 +97,7 @@ namespace WTF {
     inline bool isASCIILower(wchar_t c) { return c >= 'a' && c <= 'z'; }
 #endif
     inline bool isASCIILower(int c) { return c >= 'a' && c <= 'z'; }
+    inline bool isASCIILower(unsigned c) { return c >= 'a' && c <= 'z'; }
 
     inline bool isASCIIUpper(char c) { return c >= 'A' && c <= 'Z'; }
     inline bool isASCIIUpper(unsigned short c) { return c >= 'A' && c <= 'Z'; }
@@ -98,6 +105,7 @@ namespace WTF {
     inline bool isASCIIUpper(wchar_t c) { return c >= 'A' && c <= 'Z'; }
 #endif
     inline bool isASCIIUpper(int c) { return c >= 'A' && c <= 'Z'; }
+    inline bool isASCIIUpper(unsigned c) { return c >= 'A' && c <= 'Z'; }
 
     /*
         Statistics from a run of Apple's page load test for callers of isASCIISpace:
@@ -118,6 +126,7 @@ namespace WTF {
     inline bool isASCIISpace(wchar_t c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
 #endif
     inline bool isASCIISpace(int c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
+    inline bool isASCIISpace(unsigned c) { return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); }
 
     inline char toASCIILower(char c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
     inline unsigned short toASCIILower(unsigned short c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
@@ -125,20 +134,28 @@ namespace WTF {
     inline wchar_t toASCIILower(wchar_t c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
 #endif
     inline int toASCIILower(int c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
+    inline unsigned toASCIILower(unsigned c) { return c | ((c >= 'A' && c <= 'Z') << 5); }
 
+    // FIXME: Why do these need static_cast?
     inline char toASCIIUpper(char c) { return static_cast<char>(c & ~((c >= 'a' && c <= 'z') << 5)); }
     inline unsigned short toASCIIUpper(unsigned short c) { return static_cast<unsigned short>(c & ~((c >= 'a' && c <= 'z') << 5)); }
 #if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
     inline wchar_t toASCIIUpper(wchar_t c) { return static_cast<wchar_t>(c & ~((c >= 'a' && c <= 'z') << 5)); }
 #endif
     inline int toASCIIUpper(int c) { return static_cast<int>(c & ~((c >= 'a' && c <= 'z') << 5)); }
+    inline unsigned toASCIIUpper(unsigned c) { return static_cast<unsigned>(c & ~((c >= 'a' && c <= 'z') << 5)); }
 
     inline int toASCIIHexValue(char c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+    inline int toASCIIHexValue(char upperValue, char lowerValue) { ASSERT(isASCIIHexDigit(upperValue) && isASCIIHexDigit(lowerValue)); return ((toASCIIHexValue(upperValue) << 4) & 0xF0) | toASCIIHexValue(lowerValue); }
     inline int toASCIIHexValue(unsigned short c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
 #if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED)
     inline int toASCIIHexValue(wchar_t c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
 #endif
     inline int toASCIIHexValue(int c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+    inline int toASCIIHexValue(unsigned c) { ASSERT(isASCIIHexDigit(c)); return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; }
+
+    inline char lowerNibbleToASCIIHexDigit(char c) { char nibble = c & 0xF; return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; }
+    inline char upperNibbleToASCIIHexDigit(char c) { char nibble = (c >> 4) & 0xF; return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; }
 
     inline bool isASCIIPrintable(char c) { return c >= ' ' && c <= '~'; }
     inline bool isASCIIPrintable(unsigned short c) { return c >= ' ' && c <= '~'; }
@@ -146,6 +163,7 @@ namespace WTF {
     inline bool isASCIIPrintable(wchar_t c) { return c >= ' ' && c <= '~'; }
 #endif
     inline bool isASCIIPrintable(int c) { return c >= ' ' && c <= '~'; }
+    inline bool isASCIIPrintable(unsigned c) { return c >= ' ' && c <= '~'; }
 }
 
 using WTF::isASCII;
@@ -161,5 +179,7 @@ using WTF::isASCIIUpper;
 using WTF::toASCIIHexValue;
 using WTF::toASCIILower;
 using WTF::toASCIIUpper;
+using WTF::lowerNibbleToASCIIHexDigit;
+using WTF::upperNibbleToASCIIHexDigit;
 
 #endif
index d7470e7f956588eacbb6362efc591f4de74baeb6..ec8a63951d34663615b73d988a1c0efbf358adda 100644 (file)
@@ -33,6 +33,7 @@
 #define AVL_TREE_H_
 
 #include "Assertions.h"
+#include <wtf/FixedArray.h>
 
 namespace WTF {
 
@@ -70,7 +71,7 @@ public:
     void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; }
 
 private:
-    bool m_data[maxDepth];
+    FixedArray<bool, maxDepth> m_data;
 };
 
 // How to determine maxDepth:
diff --git a/wtf/Alignment.h b/wtf/Alignment.h
new file mode 100644 (file)
index 0000000..1903aad
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2005, 2006, 2007, 2008 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
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_Alignment_h
+#define WTF_Alignment_h
+
+#include <wtf/Platform.h>
+
+#if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW) || COMPILER(GCCE)
+    #define WTF_ALIGN_OF(type) __alignof__(type)
+    #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
+#elif COMPILER(MSVC)
+    #define WTF_ALIGN_OF(type) __alignof(type)
+    #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
+#else
+    #error WTF_ALIGN macros need alignment control.
+#endif
+
+#endif // WTF_Alignment_h
index 34f8b74b837b9c35ec08201d4d2ab632ac935b09..bacbdd0d5b2fae94310d591f647ae5a984295806 100644 (file)
@@ -41,7 +41,7 @@
 #endif
 
 #ifndef UNLIKELY
-#if COMPILER(GCC)
+#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__))
 #define UNLIKELY(x) __builtin_expect((x), 0)
 #else
 #define UNLIKELY(x) (x)
@@ -49,7 +49,7 @@
 #endif
 
 #ifndef LIKELY
-#if COMPILER(GCC)
+#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__))
 #define LIKELY(x) __builtin_expect((x), 1)
 #else
 #define LIKELY(x) (x)
index 309c1c411cda15e11ef2bf09c22af1f9585afc67..7027143f4748aa1d0cf0b46693f6f8babdc2f6a5 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// The vprintf_stderr_common function triggers this error in the Mac build.
+// Feel free to remove this pragma if this file builds on Mac.
+// According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas
+// we need to place this directive before any data or functions are defined.
+#pragma GCC diagnostic ignored "-Wmissing-format-attribute"
+
 #include "config.h"
 #include "Assertions.h"
 
 
 #include <CoreFoundation/CFString.h>
 
-#if COMPILER(MSVC) && !OS(WINCE)
+#if COMPILER(MSVC) && !OS(WINCE) && !PLATFORM(BREWMP)
 #ifndef WINVER
 #define WINVER 0x0500
 #endif
 #ifndef _WIN32_WINNT
 #define _WIN32_WINNT 0x0500
 #endif
-#include <windows.h>
 #include <crtdbg.h>
 #endif
 
-#if OS(WINCE)
-#include <winbase.h>
+#if OS(WINDOWS)
+#include <windows.h>
+#endif
+
+#if PLATFORM(BREWMP)
+#include <AEEdbg.h>
+#include <wtf/Vector.h>
+#endif
+
+#if PLATFORM(MAC)
+#include <cxxabi.h>
+#include <dlfcn.h>
+#include <execinfo.h>
 #endif
 
 extern "C" {
 
+#if PLATFORM(BREWMP)
+
+static void printLog(const Vector<char>& buffer)
+{
+    // Each call to DBGPRINTF generates at most 128 bytes of output on the Windows SDK.
+    // On Qualcomm chipset targets, DBGPRINTF() comes out the diag port (though this may change).
+    // The length of each output string is constrained even more than on the Windows SDK.
+#if COMPILER(MSVC)
+    const int printBufferSize = 128;
+#else
+    const int printBufferSize = 32;
+#endif
+
+    char printBuffer[printBufferSize + 1];
+    printBuffer[printBufferSize] = 0; // to guarantee null termination
+
+    const char* p = buffer.data();
+    const char* end = buffer.data() + buffer.size();
+    while (p < end) {
+        strncpy(printBuffer, p, printBufferSize);
+        dbg_Message(printBuffer, DBG_MSG_LEVEL_HIGH, __FILE__, __LINE__);
+        p += printBufferSize;
+    }
+}
+
+#endif
+
 WTF_ATTRIBUTE_PRINTF(1, 0)
 static void vprintf_stderr_common(const char* format, va_list args)
 {
@@ -67,7 +110,8 @@ static void vprintf_stderr_common(const char* format, va_list args)
         free(buffer);
         CFRelease(str);
         CFRelease(cfFormat);
-    } else
+        return;
+    }
 #if OS(SYMBIAN)
     vfprintf(stdout, format, args);
 #else
@@ -86,10 +130,13 @@ static void printf_stderr_common(const char* format, ...)
 
 static void printCallSite(const char* file, int line, const char* function)
 {
-#if OS(WIN) && !OS(WINCE) && defined _DEBUG
+#if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG)
     _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function);
 #else
-    printf_stderr_common("(%s:%d %s)\n", file, line, function);
+    // By using this format, which matches the format used by MSVC for compiler errors, developers
+    // using Visual Studio can double-click the file/line number in the Output Window to have the
+    // editor navigate to that line of code. It seems fine for other developers, too.
+    printf_stderr_common("%s(%d) : %s\n", file, line, function);
 #endif
 }
 
@@ -119,6 +166,34 @@ void WTFReportArgumentAssertionFailure(const char* file, int line, const char* f
     printCallSite(file, line, function);
 }
 
+void WTFReportBacktrace()
+{
+#if PLATFORM(MAC)
+    static const int maxFrames = 32;
+    void* samples[maxFrames];
+    int frames = backtrace(samples, maxFrames);
+
+    for (int i = 1; i < frames; ++i) {
+        void* pointer = samples[i];
+
+        // Try to get a symbol name from the dynamic linker.
+        Dl_info info;
+        if (dladdr(pointer, &info) && info.dli_sname) {
+            const char* mangledName = info.dli_sname;
+
+            // Assume c++ & try to demangle the name.
+            char* demangledName = abi::__cxa_demangle(mangledName, 0, 0, 0);
+            if (demangledName) {
+                fprintf(stderr, "%-3d %s\n", i, demangledName);
+                free(demangledName);
+            } else
+                fprintf(stderr, "%-3d %s\n", i, mangledName);
+        } else
+            fprintf(stderr, "%-3d %p\n", i, pointer);
+    }
+#endif
+}
+
 void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...)
 {
     printf_stderr_common("FATAL ERROR: ");
@@ -150,7 +225,9 @@ void WTFLog(WTFLogChannel* channel, const char* format, ...)
     va_start(args, format);
     vprintf_stderr_common(format, args);
     va_end(args);
-    if (format[strlen(format) - 1] != '\n')
+    
+    size_t formatLength = strlen(format);
+    if (formatLength && format[formatLength - 1] != '\n')
         printf_stderr_common("\n");
 }
 
@@ -163,8 +240,11 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
     va_start(args, format);
     vprintf_stderr_common(format, args);
     va_end(args);
-    if (format[strlen(format) - 1] != '\n')
+
+    size_t formatLength = strlen(format);
+    if (formatLength && format[formatLength - 1] != '\n')
         printf_stderr_common("\n");
+
     printCallSite(file, line, function);
 }
 
index 168e8ba0e7c3e7efcea0bae150874cb6bf4ebdb2..f6187bbe359b0cdd531d7434d6e8fc8256caa537 100644 (file)
@@ -46,9 +46,9 @@
 
 #include <stdbool.h>
 
-#if COMPILER(MSVC)
 #include <stddef.h>
-#else
+
+#if !COMPILER(MSVC)
 #include <inttypes.h>
 #endif
 
 #include <e32debug.h>
 #endif
 
+#if PLATFORM(BREWMP)
+#include <AEEError.h>
+#include <AEEdbg.h>
+#endif
+
 #ifdef NDEBUG
 /* Disable ASSERT* macros in release mode. */
 #define ASSERTIONS_DISABLED_DEFAULT 1
 #define HAVE_VARIADIC_MACRO 1
 #endif
 
+#ifndef BACKTRACE_DISABLED
+#define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT
+#endif
+
 #ifndef ASSERT_DISABLED
 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #endif
 #else
 #define CLANG_ANALYZER_NORETURN
 #endif
+/* For project uses WTF but has no config.h, we need to explicitly set the export defines here. */
+#ifndef WTF_EXPORT_PRIVATE
+#define WTF_EXPORT_PRIVATE
+#endif
 
 /* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */
 
@@ -146,13 +159,14 @@ typedef struct {
     WTFLogChannelState state;
 } WTFLogChannel;
 
-void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion) CLANG_ANALYZER_NORETURN;
-void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) CLANG_ANALYZER_NORETURN WTF_ATTRIBUTE_PRINTF(5, 6);
-void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion) CLANG_ANALYZER_NORETURN;
-void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) CLANG_ANALYZER_NORETURN WTF_ATTRIBUTE_PRINTF(4, 5);
-void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
-void WTFLog(WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
-void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
+WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion) CLANG_ANALYZER_NORETURN;
+WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) CLANG_ANALYZER_NORETURN WTF_ATTRIBUTE_PRINTF(5, 6);
+WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion) CLANG_ANALYZER_NORETURN;
+WTF_EXPORT_PRIVATE void WTFReportBacktrace();
+WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) CLANG_ANALYZER_NORETURN WTF_ATTRIBUTE_PRINTF(4, 5);
+WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5);
+WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
+WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6);
 
 #ifdef __cplusplus
 }
@@ -172,14 +186,38 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
     __DEBUGGER(); \
     User::Panic(_L("Webkit CRASH"),0); \
     } while(false)
+#elif PLATFORM(BREWMP)
+#define CRASH() do { \
+    dbg_Message("WebKit CRASH", DBG_MSG_LEVEL_FATAL, __FILE__, __LINE__); \
+    *(int *)(uintptr_t)0xbbadbeef = 0; \
+    ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
+} while(false)
 #else
 #define CRASH() do { \
+    WTFReportBacktrace(); \
     *(int *)(uintptr_t)0xbbadbeef = 0; \
     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
 } while(false)
 #endif
 #endif
 
+/* BACKTRACE
+
+  Print a backtrace to the same location as ASSERT messages.
+*/
+
+#if BACKTRACE_DISABLED
+
+#define BACKTRACE() ((void)0)
+
+#else
+
+#define BACKTRACE() do { \
+    WTFReportBacktrace(); \
+} while(false)
+
+#endif
+
 /* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED
 
   These macros are compiled out of release builds.
@@ -211,7 +249,14 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
 
 #define ASSERT(assertion) ((void)0)
 #define ASSERT_NOT_REACHED() ((void)0)
+
+#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
+template<typename T>
+inline void assertUnused(T& x) { (void)x; }
+#define ASSERT_UNUSED(variable, assertion) (assertUnused(variable))
+#else
 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
+#endif
 
 #else
 
@@ -247,6 +292,29 @@ while (0)
     } \
 while (0)
 #endif
+
+/* ASSERT_WITH_MESSAGE_UNUSED */
+
+#if COMPILER(MSVC7_OR_LOWER)
+#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion) ((void)0)
+#elif COMPILER(WINSCW)
+#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, arg...) ((void)0)
+#elif ASSERT_MSG_DISABLED
+#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
+template<typename T>
+inline void assertWithMessageUnused(T& x) { (void)x; }
+#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) (assertWithMessageUnused(variable))
+#else
+#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable)
+#endif
+#else
+#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do \
+    if (!(assertion)) { \
+        WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \
+        CRASH(); \
+    } \
+while (0)
+#endif
                         
                         
 /* ASSERT_ARG */
@@ -324,4 +392,23 @@ while (0)
 #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__)
 #endif
 
+#if ENABLE(GC_VALIDATION)
+#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { \
+    if (!(cell))\
+        CRASH();\
+    if (cell->unvalidatedStructure()->unvalidatedStructure() != cell->unvalidatedStructure()->unvalidatedStructure()->unvalidatedStructure())\
+        CRASH();\
+} while (0)
+
+#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do {\
+    ASSERT_GC_OBJECT_LOOKS_VALID(object); \
+    if (!object->inherits(classInfo)) \
+        CRASH();\
+} while (0)
+
+#else
+#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { (void)cell; } while (0)
+#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do { (void)object; (void)classInfo; } while (0)
+#endif
+
 #endif /* WTF_Assertions_h */
index 1d190a323516c5211b6d51b11d370b1dbef0a8be..1ebd4876fff179744f84fa24d9b443b77e548216 100644 (file)
@@ -78,7 +78,7 @@
 namespace WTF {
 
 #if OS(WINDOWS)
-#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1
 
 #if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE)
 inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); }
@@ -89,7 +89,7 @@ inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(r
 #endif
 
 #elif OS(DARWIN)
-#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1
 
 inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); }
 inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); }
@@ -100,7 +100,7 @@ inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(add
 inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); }
 
 #elif COMPILER(GCC) && !CPU(SPARC64) && !OS(SYMBIAN) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc
-#define WTF_USE_LOCKFREE_THREADSAFESHARED 1
+#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1
 
 inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; }
 inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; }
@@ -109,7 +109,7 @@ inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_
 
 } // namespace WTF
 
-#if USE(LOCKFREE_THREADSAFESHARED)
+#if USE(LOCKFREE_THREADSAFEREFCOUNTED)
 using WTF::atomicDecrement;
 using WTF::atomicIncrement;
 #endif
diff --git a/wtf/Bitmap.h b/wtf/Bitmap.h
new file mode 100644 (file)
index 0000000..9ee7f4a
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ *  Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifndef Bitmap_h
+#define Bitmap_h
+
+#include "FixedArray.h"
+#include "StdLibExtras.h"
+#include <stdint.h>
+#include <string.h>
+
+namespace WTF {
+
+template<size_t size>
+class Bitmap {
+private:
+    typedef uint32_t WordType;
+
+public:
+    Bitmap();
+
+    bool get(size_t) const;
+    void set(size_t);
+    bool testAndSet(size_t);
+    size_t nextPossiblyUnset(size_t) const;
+    void clear(size_t);
+    void clearAll();
+    int64_t findRunOfZeros(size_t) const;
+    size_t count(size_t = 0) const;
+    size_t isEmpty() const;
+    size_t isFull() const;
+
+private:
+    static const WordType wordSize = sizeof(WordType) * 8;
+    static const WordType words = (size + wordSize - 1) / wordSize;
+
+    // the literal '1' is of type signed int.  We want to use an unsigned
+    // version of the correct size when doing the calculations because if
+    // WordType is larger than int, '1 << 31' will first be sign extended
+    // and then casted to unsigned, meaning that set(31) when WordType is
+    // a 64 bit unsigned int would give 0xffff8000
+    static const WordType one = 1;
+
+    FixedArray<WordType, words> bits;
+};
+
+template<size_t size>
+inline Bitmap<size>::Bitmap()
+{
+    clearAll();
+}
+
+template<size_t size>
+inline bool Bitmap<size>::get(size_t n) const
+{
+    return !!(bits[n / wordSize] & (one << (n % wordSize)));
+}
+
+template<size_t size>
+inline void Bitmap<size>::set(size_t n)
+{
+    bits[n / wordSize] |= (one << (n % wordSize));
+}
+
+template<size_t size>
+inline bool Bitmap<size>::testAndSet(size_t n)
+{
+    WordType mask = one << (n % wordSize);
+    size_t index = n / wordSize;
+    bool result = bits[index] & mask;
+    bits[index] |= mask;
+    return result;
+}
+
+template<size_t size>
+inline void Bitmap<size>::clear(size_t n)
+{
+    bits[n / wordSize] &= ~(one << (n % wordSize));
+}
+
+template<size_t size>
+inline void Bitmap<size>::clearAll()
+{
+    memset(bits.data(), 0, sizeof(bits));
+}
+
+template<size_t size>
+inline size_t Bitmap<size>::nextPossiblyUnset(size_t start) const
+{
+    if (!~bits[start / wordSize])
+        return ((start / wordSize) + 1) * wordSize;
+    return start + 1;
+}
+
+template<size_t size>
+inline int64_t Bitmap<size>::findRunOfZeros(size_t runLength) const
+{
+    if (!runLength) 
+        runLength = 1; 
+     
+    for (size_t i = 0; i <= (size - runLength) ; i++) {
+        bool found = true; 
+        for (size_t j = i; j <= (i + runLength - 1) ; j++) { 
+            if (get(j)) {
+                found = false; 
+                break;
+            }
+        }
+        if (found)  
+            return i; 
+    }
+    return -1;
+}
+
+template<size_t size>
+inline size_t Bitmap<size>::count(size_t start) const
+{
+    size_t result = 0;
+    for ( ; (start % wordSize); ++start) {
+        if (get(start))
+            ++result;
+    }
+    for (size_t i = start / wordSize; i < words; ++i)
+        result += WTF::bitCount(bits[i]);
+    return result;
+}
+
+template<size_t size>
+inline size_t Bitmap<size>::isEmpty() const
+{
+    for (size_t i = 0; i < words; ++i)
+        if (bits[i])
+            return false;
+    return true;
+}
+
+template<size_t size>
+inline size_t Bitmap<size>::isFull() const
+{
+    for (size_t i = 0; i < words; ++i)
+        if (~bits[i])
+            return false;
+    return true;
+}
+
+}
+#endif
diff --git a/wtf/BlockStack.h b/wtf/BlockStack.h
new file mode 100644 (file)
index 0000000..a4d7425
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 BlockStack_h
+#define BlockStack_h
+
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+
+template <typename T> class BlockStack {
+public:
+    static const size_t blockSize = 4096;
+    static const size_t blockLength = blockSize / sizeof(T);
+
+    BlockStack();
+    ~BlockStack();
+
+    T* grow();
+    void shrink(T*);
+
+    const Vector<T*>& blocks();
+
+private:
+    Vector<T*> m_blocks;
+    T* m_spareBlock; // Used to avoid thrash at block boundaries.
+};
+
+template <typename T> BlockStack<T>::BlockStack()
+    : m_spareBlock(0)
+{
+}
+
+template <typename T> BlockStack<T>::~BlockStack()
+{
+    if (m_spareBlock)
+        free(m_spareBlock);
+    for (size_t i = 0; i < m_blocks.size(); ++i)
+        free(m_blocks[i]);
+}
+
+template <typename T> inline const Vector<T*>& BlockStack<T>::blocks()
+{
+    return m_blocks;
+}
+
+template <typename T> T* BlockStack<T>::grow()
+{
+    T* block = m_spareBlock ? m_spareBlock : static_cast<T*>(malloc(blockSize));
+    m_spareBlock = 0;
+
+    m_blocks.append(block);
+    return block;
+}
+
+template <typename T> void BlockStack<T>::shrink(T* newEnd)
+{
+    ASSERT(newEnd != m_blocks.last() + blockLength);
+    m_spareBlock = m_blocks.last();
+    m_blocks.removeLast();
+
+    while (m_blocks.last() + blockLength != newEnd) {
+        free(m_blocks.last());
+        m_blocks.removeLast();
+    }
+}
+
+}
+
+using WTF::BlockStack;
+
+#endif
diff --git a/wtf/BloomFilter.h b/wtf/BloomFilter.h
new file mode 100644 (file)
index 0000000..f81d83e
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 BloomFilter_h
+#define BloomFilter_h
+
+#include <wtf/AlwaysInline.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WTF {
+
+// Counting bloom filter with k=2 and 8 bit counters. Uses 2^keyBits bytes of memory.
+// False positive rate is approximately (1-e^(-2n/m))^2, where n is the number of unique 
+// keys and m is the table size (==2^keyBits).
+template <unsigned keyBits>
+class BloomFilter {
+public:
+    COMPILE_ASSERT(keyBits <= 16, bloom_filter_key_size);
+
+    static const size_t tableSize = 1 << keyBits;
+    static const unsigned keyMask = (1 << keyBits) - 1;
+    static uint8_t maximumCount() { return std::numeric_limits<uint8_t>::max(); }
+    
+    BloomFilter() { clear(); }
+
+    void add(unsigned hash);
+    void remove(unsigned hash);
+
+    // The filter may give false positives (claim it may contain a key it doesn't)
+    // but never false negatives (claim it doesn't contain a key it does).
+    bool mayContain(unsigned hash) const { return firstSlot(hash) && secondSlot(hash); }
+    
+    // The filter must be cleared before reuse even if all keys are removed.
+    // Otherwise overflowed keys will stick around.
+    void clear();
+
+    void add(const AtomicString& string) { add(string.impl()->existingHash()); }
+    void add(const String& string) { add(string.impl()->hash()); }
+    void remove(const AtomicString& string) { remove(string.impl()->existingHash()); }
+    void remove(const String& string) { remove(string.impl()->hash()); }
+
+    bool mayContain(const AtomicString& string) const { return mayContain(string.impl()->existingHash()); }
+    bool mayContain(const String& string) const { return mayContain(string.impl()->hash()); }
+
+#if !ASSERT_DISABLED
+    // Slow.
+    bool likelyEmpty() const;
+    bool isClear() const;
+#endif
+
+private:
+    uint8_t& firstSlot(unsigned hash) { return m_table[hash & keyMask]; }
+    uint8_t& secondSlot(unsigned hash) { return m_table[(hash >> 16) & keyMask]; }
+    const uint8_t& firstSlot(unsigned hash) const { return m_table[hash & keyMask]; }
+    const uint8_t& secondSlot(unsigned hash) const { return m_table[(hash >> 16) & keyMask]; }
+
+    uint8_t m_table[tableSize];
+};
+    
+template <unsigned keyBits>
+inline void BloomFilter<keyBits>::add(unsigned hash)
+{
+    uint8_t& first = firstSlot(hash);
+    uint8_t& second = secondSlot(hash);
+    if (LIKELY(first < maximumCount()))
+        ++first;
+    if (LIKELY(second < maximumCount()))
+        ++second;
+}
+
+template <unsigned keyBits>
+inline void BloomFilter<keyBits>::remove(unsigned hash)
+{
+    uint8_t& first = firstSlot(hash);
+    uint8_t& second = secondSlot(hash);
+    ASSERT(first);
+    ASSERT(second);
+    // In case of an overflow, the slot sticks in the table until clear().
+    if (LIKELY(first < maximumCount()))
+        --first;
+    if (LIKELY(second < maximumCount()))
+        --second;
+}
+    
+template <unsigned keyBits>
+inline void BloomFilter<keyBits>::clear()
+{
+    memset(m_table, 0, tableSize);
+}
+
+#if !ASSERT_DISABLED
+template <unsigned keyBits>
+bool BloomFilter<keyBits>::likelyEmpty() const
+{
+    for (size_t n = 0; n < tableSize; ++n) {
+        if (m_table[n] && m_table[n] != maximumCount())
+            return false;
+    }
+    return true;
+}
+
+template <unsigned keyBits>
+bool BloomFilter<keyBits>::isClear() const
+{
+    for (size_t n = 0; n < tableSize; ++n) {
+        if (m_table[n])
+            return false;
+    }
+    return true;
+}
+#endif
+
+}
+
+using WTF::BloomFilter;
+
+#endif
diff --git a/wtf/BumpPointerAllocator.h b/wtf/BumpPointerAllocator.h
new file mode 100644 (file)
index 0000000..682283c
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2010 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 BumpPointerAllocator_h
+#define BumpPointerAllocator_h
+
+#include <wtf/PageAllocation.h>
+
+namespace WTF {
+
+#define MINIMUM_BUMP_POOL_SIZE 0x1000
+
+class BumpPointerPool {
+public:
+    // ensureCapacity will check whether the current pool has capacity to
+    // allocate 'size' bytes of memory  If it does not, it will attempt to
+    // allocate a new pool (which will be added to this one in a chain).
+    //
+    // If allocation fails (out of memory) this method will return null.
+    // If the return value is non-null, then callers should update any
+    // references they have to this current (possibly full) BumpPointerPool
+    // to instead point to the newly returned BumpPointerPool.
+    BumpPointerPool* ensureCapacity(size_t size)
+    {
+        void* allocationEnd = static_cast<char*>(m_current) + size;
+        ASSERT(allocationEnd > m_current); // check for overflow
+        if (allocationEnd <= static_cast<void*>(this))
+            return this;
+        return ensureCapacityCrossPool(this, size);
+    }
+
+    // alloc should only be called after calling ensureCapacity; as such
+    // alloc will never fail.
+    void* alloc(size_t size)
+    {
+        void* current = m_current;
+        void* allocationEnd = static_cast<char*>(current) + size;
+        ASSERT(allocationEnd > current); // check for overflow
+        ASSERT(allocationEnd <= static_cast<void*>(this));
+        m_current = allocationEnd;
+        return current;
+    }
+
+    // The dealloc method releases memory allocated using alloc.  Memory
+    // must be released in a LIFO fashion, e.g. if the client calls alloc
+    // four times, returning pointer A, B, C, D, then the only valid order
+    // in which these may be deallocaed is D, C, B, A.
+    //
+    // The client may optionally skip some deallocations.  In the example
+    // above, it would be valid to only explicitly dealloc C, A (D being
+    // dealloced along with C, B along with A).
+    //
+    // If pointer was not allocated from this pool (or pools) then dealloc
+    // will CRASH().  Callers should update any references they have to
+    // this current BumpPointerPool to instead point to the returned
+    // BumpPointerPool.
+    BumpPointerPool* dealloc(void* position)
+    {
+        if ((position >= m_start) && (position <= static_cast<void*>(this))) {
+            ASSERT(position <= m_current);
+            m_current = position;
+            return this;
+        }
+        return deallocCrossPool(this, position);
+    }
+
+private:
+    // Placement operator new, returns the last 'size' bytes of allocation for use as this.
+    void* operator new(size_t size, const PageAllocation& allocation)
+    {
+        ASSERT(size < allocation.size());
+        return reinterpret_cast<char*>(reinterpret_cast<intptr_t>(allocation.base()) + allocation.size()) - size;
+    }
+
+    BumpPointerPool(const PageAllocation& allocation)
+        : m_current(allocation.base())
+        , m_start(allocation.base())
+        , m_next(0)
+        , m_previous(0)
+        , m_allocation(allocation)
+    {
+    }
+
+    static BumpPointerPool* create(size_t minimumCapacity = 0)
+    {
+        // Add size of BumpPointerPool object, check for overflow.
+        minimumCapacity += sizeof(BumpPointerPool);
+        if (minimumCapacity < sizeof(BumpPointerPool))
+            return 0;
+
+        size_t poolSize = MINIMUM_BUMP_POOL_SIZE;
+        while (poolSize < minimumCapacity) {
+            poolSize <<= 1;
+            // The following if check relies on MINIMUM_BUMP_POOL_SIZE being a power of 2!
+            ASSERT(!(MINIMUM_BUMP_POOL_SIZE & (MINIMUM_BUMP_POOL_SIZE - 1)));
+            if (!poolSize)
+                return 0;
+        }
+
+        PageAllocation allocation = PageAllocation::allocate(poolSize);
+        if (!!allocation)
+            return new(allocation) BumpPointerPool(allocation);
+        return 0;
+    }
+
+    void shrink()
+    {
+        ASSERT(!m_previous);
+        m_current = m_start;
+        while (m_next) {
+            BumpPointerPool* nextNext = m_next->m_next;
+            m_next->destroy();
+            m_next = nextNext;
+        }
+    }
+
+    void destroy()
+    {
+        m_allocation.deallocate();
+    }
+
+    static BumpPointerPool* ensureCapacityCrossPool(BumpPointerPool* previousPool, size_t size)
+    {
+        // The pool passed should not have capacity, so we'll start with the next one.
+        ASSERT(previousPool);
+        ASSERT((static_cast<char*>(previousPool->m_current) + size) > previousPool->m_current); // check for overflow
+        ASSERT((static_cast<char*>(previousPool->m_current) + size) > static_cast<void*>(previousPool));
+        BumpPointerPool* pool = previousPool->m_next;
+
+        while (true) {
+            if (!pool) {
+                // We've run to the end; allocate a new pool.
+                pool = BumpPointerPool::create(size);
+                previousPool->m_next = pool;
+                pool->m_previous = previousPool;
+                return pool;
+            }
+
+            // 
+            void* current = pool->m_current;
+            void* allocationEnd = static_cast<char*>(current) + size;
+            ASSERT(allocationEnd > current); // check for overflow
+            if (allocationEnd <= static_cast<void*>(pool))
+                return pool;
+        }
+    }
+
+    static BumpPointerPool* deallocCrossPool(BumpPointerPool* pool, void* position)
+    {
+        // Should only be called if position is not in the current pool.
+        ASSERT((position < pool->m_start) || (position > static_cast<void*>(pool)));
+
+        while (true) {
+            // Unwind the current pool to the start, move back in the chain to the previous pool.
+            pool->m_current = pool->m_start;
+            pool = pool->m_previous;
+
+            // position was nowhere in the chain!
+            if (!pool)
+                CRASH();
+
+            if ((position >= pool->m_start) && (position <= static_cast<void*>(pool))) {
+                ASSERT(position <= pool->m_current);
+                pool->m_current = position;
+                return pool;
+            }
+        }
+    }
+
+    void* m_current;
+    void* m_start;
+    BumpPointerPool* m_next;
+    BumpPointerPool* m_previous;
+    PageAllocation m_allocation;
+
+    friend class BumpPointerAllocator;
+};
+
+// A BumpPointerAllocator manages a set of BumpPointerPool objects, which
+// can be used for LIFO (stack like) allocation.
+//
+// To begin allocating using this class call startAllocator().  The result
+// of this method will be null if the initial pool allocation fails, or a
+// pointer to a BumpPointerPool object that can be used to perform
+// allocations.  Whilst running no memory will be released until
+// stopAllocator() is called.  At this point all allocations made through
+// this allocator will be reaped, and underlying memory may be freed.
+//
+// (In practice we will still hold on to the initial pool to allow allocation
+// to be quickly restared, but aditional pools will be freed).
+//
+// This allocator is non-renetrant, it is encumbant on the clients to ensure
+// startAllocator() is not called again until stopAllocator() has been called.
+class BumpPointerAllocator {
+public:
+    BumpPointerAllocator()
+        : m_head(0)
+    {
+    }
+
+    ~BumpPointerAllocator()
+    {
+        if (m_head)
+            m_head->destroy();
+    }
+
+    BumpPointerPool* startAllocator()
+    {
+        if (!m_head)
+            m_head = BumpPointerPool::create();
+        return m_head;
+    }
+
+    void stopAllocator()
+    {
+        if (m_head)
+            m_head->shrink();
+    }
+
+private:
+    BumpPointerPool* m_head;
+};
+
+}
+
+using WTF::BumpPointerAllocator;
+
+#endif // BumpPointerAllocator_h
index 526f1478253036c54ad01d2ece2269f931ae9661..910af598a8cc4a1c12dd19bb7f0ab81bc0722e84 100644 (file)
 
 #include "config.h"
 #include "ByteArray.h"
+#include "StdLibExtras.h"
 
 namespace WTF {
 
 PassRefPtr<ByteArray> ByteArray::create(size_t size)
 {
-    unsigned char* buffer = new unsigned char[size + sizeof(ByteArray) - sizeof(size_t)];
+    unsigned char* buffer = new unsigned char[size + OBJECT_OFFSETOF(ByteArray, m_data)];
     ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0);
     return adoptRef(new (buffer) ByteArray(size));
 }
index f5f5ded8ffe8cf3c1ef7387538c59b57e60437e5..bdec630b4d186201e070227860fd1e3658389f08 100644 (file)
@@ -26,7 +26,9 @@
 #ifndef ByteArray_h
 #define ByteArray_h
 
+#include <limits.h>
 #include <wtf/PassRefPtr.h>
+#include <wtf/Platform.h>
 #include <wtf/RefCounted.h>
 
 namespace WTF {
@@ -86,8 +88,17 @@ namespace WTF {
         {
         }
         size_t m_size;
-        unsigned char m_data[sizeof(size_t)];
+// MSVC can't handle correctly unsized array.
+// warning C4200: nonstandard extension used : zero-sized array in struct/union
+// Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array
+#if COMPILER(MSVC)
+        unsigned char m_data[INT_MAX];
+#else
+        unsigned char m_data[];
+#endif
     };
-}
+} // namespace WTF
+
+using WTF::ByteArray;
 
 #endif
diff --git a/wtf/CMakeLists.txt b/wtf/CMakeLists.txt
new file mode 100644 (file)
index 0000000..87674b1
--- /dev/null
@@ -0,0 +1,172 @@
+SET(WTF_HEADERS
+    ASCIICType.h
+    AVLTree.h
+    Alignment.h
+    AlwaysInline.h
+    Assertions.h
+    Atomics.h
+    Bitmap.h
+    BumpPointerAllocator.h
+    ByteArray.h
+    Complex.h
+    CrossThreadRefCounted.h
+    CryptographicallyRandomNumber.h
+    CurrentTime.h
+    DateMath.h
+    DecimalNumber.h
+    Decoder.h
+    Deque.h
+    DisallowCType.h
+    DoublyLinkedList.h
+    DynamicAnnotations.h
+    Encoder.h
+    FastAllocBase.h
+    FastMalloc.h
+    FixedArray.h
+    Forward.h
+    GetPtr.h
+    HashCountedSet.h
+    HashFunctions.h
+    HashIterators.h
+    HashMap.h
+    HashSet.h
+    HashTable.h
+    HashTraits.h
+    HexNumber.h
+    ListHashSet.h
+    ListRefPtr.h
+    Locker.h
+    MD5.h
+    MainThread.h
+    MallocZoneSupport.h
+    MathExtras.h
+    MessageQueue.h
+    NonCopyingSort.h
+    Noncopyable.h
+    NotFound.h
+    NullPtr.h
+    OSAllocator.h
+    OSRandomSource.h
+    OwnArrayPtr.h
+    OwnFastMallocPtr.h
+    OwnPtr.h
+    OwnPtrCommon.h
+    PageAllocation.h
+    PageAllocationAligned.h
+    PageBlock.h
+    PageReservation.h
+    PassOwnArrayPtr.h
+    PassOwnPtr.h
+    PassRefPtr.h
+    PassTraits.h
+    ParallelJobs.h
+    ParallelJobsGeneric.h
+    ParallelJobsLibdispatch.h
+    ParallelJobsOpenMP.h
+    Platform.h
+    PossiblyNull.h
+    RandomNumber.h
+    RandomNumberSeed.h
+    RefCounted.h
+    RefCountedLeakCounter.h
+    RefPtr.h
+    RefPtrHashMap.h
+    RetainPtr.h
+    SegmentedVector.h
+    SHA1.h
+    StackBounds.h
+    StaticConstructors.h
+    StdLibExtras.h
+    StringExtras.h
+    StringHasher.h
+    TCPackedCache.h
+    TCPageMap.h
+    TCSpinLock.h
+    TCSystemAlloc.h
+    ThreadIdentifierDataPthreads.h
+    ThreadSafeRefCounted.h
+    ThreadSpecific.h
+    Threading.h
+    ThreadingPrimitives.h
+    TypeTraits.h
+    UnusedParam.h
+    VMTags.h
+    ValueCheck.h
+    Vector.h
+    VectorTraits.h
+    WTFThreadData.h
+    dtoa.h
+
+    text/AtomicString.h
+    text/AtomicStringImpl.h
+    text/CString.h
+    text/StringBuffer.h
+    text/StringHash.h
+    text/StringImpl.h
+    text/StringImplBase.h
+    text/WTFString.h
+
+    unicode/CharacterNames.h
+    unicode/Collator.h
+    unicode/UTF8.h
+    unicode/Unicode.h
+)
+
+SET(WTF_SOURCES
+    Assertions.cpp
+    ByteArray.cpp
+    CryptographicallyRandomNumber.cpp
+    CurrentTime.cpp
+    DecimalNumber.cpp
+    DynamicAnnotations.cpp
+    FastMalloc.cpp
+    HashTable.cpp
+    MainThread.cpp
+    MD5.cpp
+    OSRandomSource.cpp
+    ParallelJobsGeneric.cpp
+    RandomNumber.cpp
+    RefCountedLeakCounter.cpp
+    SHA1.cpp
+    StackBounds.cpp
+    StringExtras.cpp
+    Threading.cpp
+    TypeTraits.cpp
+    WTFThreadData.cpp
+    dtoa.cpp
+
+    text/AtomicString.cpp
+    text/CString.cpp
+    text/StringBuilder.cpp
+    text/StringImpl.cpp
+    text/StringStatics.cpp
+    text/WTFString.cpp
+
+    unicode/UTF8.cpp
+)
+
+SET(WTF_LIBRARIES
+)
+
+SET(WTF_PORT_FLAGS )
+INCLUDE_IF_EXISTS(${JAVASCRIPTCORE_DIR}/wtf/CMakeLists${PORT}.txt)
+
+LIST(APPEND WTF_INCLUDE_DIRECTORIES
+    "${CMAKE_BINARY_DIR}"
+    "${CMAKE_SOURCE_DIR}/ThirdParty"
+)
+
+WEBKIT_WRAP_SOURCELIST(${WTF_SOURCES})
+INCLUDE_DIRECTORIES(${WTF_INCLUDE_DIRECTORIES})
+ADD_DEFINITIONS(-DBUILDING_WTF)
+ADD_LIBRARY(${WTF_LIBRARY_NAME} ${WTF_LIBRARY_TYPE} ${WTF_HEADERS} ${WTF_SOURCES})
+TARGET_LINK_LIBRARIES(${WTF_LIBRARY_NAME} ${WTF_LIBRARIES})
+
+IF (WTF_LINK_FLAGS)
+    ADD_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} LINK_FLAGS "${WTF_LINK_FLAGS}")
+ENDIF ()
+
+IF (SHARED_CORE)
+    SET_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
+    INSTALL(TARGETS ${WTF_LIBRARY_NAME} DESTINATION lib)
+ENDIF ()
diff --git a/wtf/CMakeListsEfl.txt b/wtf/CMakeListsEfl.txt
new file mode 100644 (file)
index 0000000..e5d8bd7
--- /dev/null
@@ -0,0 +1,46 @@
+IF (ENABLE_FAST_MALLOC)
+  LIST(APPEND WTF_SOURCES
+    TCSystemAlloc.cpp
+  )
+ELSE ()
+  ADD_DEFINITIONS(-DUSE_SYSTEM_MALLOC=1)
+ENDIF()
+
+LIST(APPEND WTF_SOURCES
+    efl/MainThreadEfl.cpp
+
+    ThreadIdentifierDataPthreads.cpp
+    ThreadingPthreads.cpp
+
+    unicode/icu/CollatorICU.cpp
+)
+
+IF (ENABLE_GLIB_SUPPORT)
+  LIST(APPEND WTF_SOURCES
+    gobject/GOwnPtr.cpp
+    gobject/GRefPtr.cpp
+  )
+
+  LIST(APPEND WTF_INCLUDE_DIRECTORIES
+    ${Glib_INCLUDE_DIRS}
+    ${JAVASCRIPTCORE_DIR}/wtf/gobject
+  )
+
+  LIST(APPEND WTF_LIBRARIES
+    ${Glib_LIBRARIES}
+  )
+ENDIF ()
+
+LIST(APPEND WTF_LIBRARIES
+    pthread
+    ${ICU_LIBRARIES}
+)
+
+LIST(APPEND WTF_LINK_FLAGS
+    ${ECORE_LDFLAGS}
+)
+
+LIST(APPEND WTF_INCLUDE_DIRECTORIES
+    ${ECORE_INCLUDE_DIRS}
+    ${JAVASCRIPTCORE_DIR}/wtf/unicode/
+)
diff --git a/wtf/CMakeListsWinCE.txt b/wtf/CMakeListsWinCE.txt
new file mode 100644 (file)
index 0000000..9c558eb
--- /dev/null
@@ -0,0 +1,27 @@
+LIST(APPEND WTF_HEADERS
+    unicode/wince/UnicodeWinCE.h
+
+    ${3RDPARTY_DIR}/ce-compat/ce_time.h
+    ${3RDPARTY_DIR}/ce-compat/ce_unicode.h
+)
+
+LIST(APPEND WTF_SOURCES
+    NullPtr.cpp
+    OSAllocatorWin.cpp
+    TCSystemAlloc.cpp
+    ThreadingWin.cpp
+    ThreadSpecificWin.cpp
+
+    unicode/CollatorDefault.cpp
+    unicode/wince/UnicodeWinCE.cpp
+
+    win/MainThreadWin.cpp
+    win/OwnPtrWin.cpp
+
+    ${3RDPARTY_DIR}/ce-compat/ce_time.c
+    ${3RDPARTY_DIR}/ce-compat/ce_unicode.cpp
+)
+
+LIST(APPEND WTF_LIBRARIES
+    mmtimer
+)
index cfd1d2008e066c5102daddfcc29f8a7c8d3ed217..40fe56a7bb75442efae4d589cf4970fcffee56f9 100644 (file)
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef Complex_h
-#define Complex_h
+#ifndef WTF_Complex_h
+#define WTF_Complex_h
 
 #include <complex>
 #include <wtf/MathExtras.h>
 
-namespace WebCore {
+namespace WTF {
 
 typedef std::complex<double> Complex;
 
@@ -41,6 +41,9 @@ inline Complex complexFromMagnitudePhase(double magnitude, double phase)
     return Complex(magnitude * cos(phase), magnitude * sin(phase));
 }
 
-} // namespace WebCore
+} // namespace WTF
 
-#endif // Complex_h
+using WTF::Complex;
+using WTF::complexFromMagnitudePhase;
+
+#endif // WTF_Complex_h
index 831616150ac243601aecc8ef8051b2cbd9ec6290..3931755bb1b8a99cfe9b81b2e438c7ecc81fc7b7 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2010 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
 #ifndef CrossThreadRefCounted_h
 #define CrossThreadRefCounted_h
 
-#include <wtf/Noncopyable.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/Threading.h>
+#include "PassRefPtr.h"
+#include "RefCounted.h"
+#include "Threading.h"
 
 #include <wtf/iphone/WebCoreThread.h>
 
 namespace WTF {
 
-    // Used to allowing sharing data across classes and threads (like ThreadedSafeShared).
+    // Used to allowing sharing data across classes and threads (like ThreadSafeRefCounted).
     //
-    // Why not just use ThreadSafeShared?
-    // ThreadSafeShared can have a significant perf impact when used in low level classes
+    // Why not just use ThreadSafeRefCounted?
+    // ThreadSafeRefCounted can have a significant perf impact when used in low level classes
     // (like UString) that get ref/deref'ed a lot. This class has the benefit of doing fast ref
     // counts like RefPtr whenever possible, but it has the downside that you need to copy it
     // to use it on another thread.
@@ -53,7 +53,8 @@ namespace WTF {
     // with respect to the original and any other copies.  The underlying m_data is jointly
     // owned by the original instance and all copies.
     template<class T>
-    class CrossThreadRefCounted : public Noncopyable {
+    class CrossThreadRefCounted {
+        WTF_MAKE_NONCOPYABLE(CrossThreadRefCounted);
     public:
         static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
         {
@@ -73,13 +74,16 @@ namespace WTF {
         }
 
     private:
-        CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter)
+        CrossThreadRefCounted(T* data, ThreadSafeRefCountedBase* threadedCounter)
             : m_threadSafeRefCounter(threadedCounter)
             , m_data(data)
 #ifndef NDEBUG
             , m_threadId(0)
 #endif
         {
+            // We use RefCountedBase in an unusual way here, so get rid of the requirement
+            // that adoptRef be called on it.
+            m_refCounter.relaxAdoptionRequirement();
         }
 
         ~CrossThreadRefCounted()
@@ -97,7 +101,7 @@ namespace WTF {
 #endif
 
         RefCountedBase m_refCounter;
-        ThreadSafeSharedBase* m_threadSafeRefCounter;
+        ThreadSafeRefCountedBase* m_threadSafeRefCounter;
         T* m_data;
 #ifndef NDEBUG
         ThreadIdentifier m_threadId;
@@ -157,7 +161,7 @@ namespace WTF {
         if (m_threadSafeRefCounter)
             m_threadSafeRefCounter->ref();
         else
-            m_threadSafeRefCounter = new ThreadSafeSharedBase(2);
+            m_threadSafeRefCounter = new ThreadSafeRefCountedBase(2);
 
         return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter));
     }
diff --git a/wtf/CryptographicallyRandomNumber.cpp b/wtf/CryptographicallyRandomNumber.cpp
new file mode 100644 (file)
index 0000000..ef097ab
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Arc4 random number generator for OpenBSD.
+ *
+ * This code is derived from section 17.1 of Applied Cryptography,
+ * second edition, which describes a stream cipher allegedly
+ * compatible with RSA Labs "RC4" cipher (the actual description of
+ * which is a trade secret).  The same algorithm is used as a stream
+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
+ *
+ * RC4 is a registered trademark of RSA Laboratories.
+ */
+
+#include "config.h"
+#include "CryptographicallyRandomNumber.h"
+
+#include "MainThread.h"
+#include "OSRandomSource.h"
+#include "StdLibExtras.h"
+#include "ThreadingPrimitives.h"
+
+namespace WTF {
+
+#if USE(OS_RANDOMNESS)
+
+namespace {
+
+class ARC4Stream {
+public:
+    ARC4Stream();
+
+    uint8_t i;
+    uint8_t j;
+    uint8_t s[256];
+};
+
+class ARC4RandomNumberGenerator {
+public:
+    ARC4RandomNumberGenerator();
+
+    uint32_t randomNumber();
+    void randomValues(void* buffer, size_t length);
+
+private:
+    inline void addRandomData(unsigned char *data, int length);
+    void stir();
+    void stirIfNeeded();
+    inline uint8_t getByte();
+    inline uint32_t getWord();
+
+    ARC4Stream m_stream;
+    int m_count;
+#if ENABLE(WTF_MULTIPLE_THREADS)
+    Mutex m_mutex;
+#endif
+};
+
+ARC4Stream::ARC4Stream()
+{
+    for (int n = 0; n < 256; n++)
+        s[n] = n;
+    i = 0;
+    j = 0;
+}
+
+ARC4RandomNumberGenerator::ARC4RandomNumberGenerator()
+    : m_count(0)
+{
+}
+
+void ARC4RandomNumberGenerator::addRandomData(unsigned char* data, int length)
+{
+    m_stream.i--;
+    for (int n = 0; n < 256; n++) {
+        m_stream.i++;
+        uint8_t si = m_stream.s[m_stream.i];
+        m_stream.j += si + data[n % length];
+        m_stream.s[m_stream.i] = m_stream.s[m_stream.j];
+        m_stream.s[m_stream.j] = si;
+    }
+    m_stream.j = m_stream.i;
+}
+
+void ARC4RandomNumberGenerator::stir()
+{
+    unsigned char randomness[128];
+    size_t length = sizeof(randomness);
+    cryptographicallyRandomValuesFromOS(randomness, length);
+    addRandomData(randomness, length);
+
+    // Discard early keystream, as per recommendations in:
+    // http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
+    for (int i = 0; i < 256; i++)
+        getByte();
+    m_count = 1600000;
+}
+
+void ARC4RandomNumberGenerator::stirIfNeeded()
+{
+    if (m_count <= 0)
+        stir();
+}
+
+uint8_t ARC4RandomNumberGenerator::getByte()
+{
+    m_stream.i++;
+    uint8_t si = m_stream.s[m_stream.i];
+    m_stream.j += si;
+    uint8_t sj = m_stream.s[m_stream.j];
+    m_stream.s[m_stream.i] = sj;
+    m_stream.s[m_stream.j] = si;
+    return (m_stream.s[(si + sj) & 0xff]);
+}
+
+uint32_t ARC4RandomNumberGenerator::getWord()
+{
+    uint32_t val;
+    val = getByte() << 24;
+    val |= getByte() << 16;
+    val |= getByte() << 8;
+    val |= getByte();
+    return val;
+}
+
+uint32_t ARC4RandomNumberGenerator::randomNumber()
+{
+#if ENABLE(WTF_MULTIPLE_THREADS)
+    MutexLocker locker(m_mutex);
+#else
+    ASSERT(isMainThread());
+#endif
+
+    m_count -= 4;
+    stirIfNeeded();
+    return getWord();
+}
+
+void ARC4RandomNumberGenerator::randomValues(void* buffer, size_t length)
+{
+#if ENABLE(WTF_MULTIPLE_THREADS)
+    MutexLocker locker(m_mutex);
+#else
+    ASSERT(isMainThread());
+#endif
+
+    unsigned char* result = reinterpret_cast<unsigned char*>(buffer);
+    stirIfNeeded();
+    while (length--) {
+        m_count--;
+        stirIfNeeded();
+        result[length] = getByte();
+    }
+}
+
+ARC4RandomNumberGenerator& sharedRandomNumberGenerator()
+{
+    DEFINE_STATIC_LOCAL(ARC4RandomNumberGenerator, randomNumberGenerator, ());
+    return randomNumberGenerator;
+}
+
+}
+
+uint32_t cryptographicallyRandomNumber()
+{
+    return sharedRandomNumberGenerator().randomNumber();
+}
+
+void cryptographicallyRandomValues(void* buffer, size_t length)
+{
+    sharedRandomNumberGenerator().randomValues(buffer, length);
+}
+
+#endif
+
+}
diff --git a/wtf/CryptographicallyRandomNumber.h b/wtf/CryptographicallyRandomNumber.h
new file mode 100644 (file)
index 0000000..348242e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 COMPUTER, 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 COMPUTER, 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 WTF_CryptographicallyRandomNumber_h
+#define WTF_CryptographicallyRandomNumber_h
+
+#include <stdint.h>
+
+namespace WTF {
+
+#if USE(OS_RANDOMNESS)
+uint32_t cryptographicallyRandomNumber();
+void cryptographicallyRandomValues(void* buffer, size_t length);
+#endif
+
+}
+
+#if USE(OS_RANDOMNESS)
+using WTF::cryptographicallyRandomNumber;
+using WTF::cryptographicallyRandomValues;
+#endif
+
+#endif
index 08fffa288b0b8c65c5bb2375c5b5e5cf6ed9c579..42052276085e8209ec83e91e1160dca73cbb1d8f 100644 (file)
@@ -35,7 +35,7 @@
 
 #if OS(WINDOWS)
 
-// Windows is first since we want to use hires timers, despite PLATFORM(CF)
+// Windows is first since we want to use hires timers, despite USE(CF)
 // being defined.
 // If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod.
 #undef WIN32_LEAN_AND_MEAN
@@ -163,7 +163,6 @@ double currentTime()
     // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals.
     // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter
     // by itself, adding the delta to the saved ftime.  We periodically re-sync to correct for drift.
-    static bool started;
     static double syncLowResUTCTime;
     static double syncHighResUpTime;
     static double lastUTCTime;
index dcb1f6c69d9b3f15ece01f15c5d1bf9c625c7fc0..5fcb63a81fdf203e9dbb9825699deec8617e0c3b 100644 (file)
 
 namespace WTF {
 
-    // Returns the current UTC time in seconds, counted from January 1, 1970.
-    // Precision varies depending on platform but is usually as good or better 
-    // than a millisecond.
-    double currentTime();
+// Returns the current UTC time in seconds, counted from January 1, 1970.
+// Precision varies depending on platform but is usually as good or better
+// than a millisecond.
+double currentTime();
 
-    // Same thing, in milliseconds.
-    inline double currentTimeMS()
-    {
-        return currentTime() * 1000.0; 
-    }
+// Same thing, in milliseconds.
+inline double currentTimeMS()
+{
+    return currentTime() * 1000.0;
+}
 
-    inline void getLocalTime(const time_t* localTime, struct tm* localTM)
-    {
-    #if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) || OS(WINCE)
-        *localTM = *localtime(localTime);
-    #elif COMPILER(MSVC)
-        localtime_s(localTM, localTime);
-    #else
-        localtime_r(localTime, localTM);
-    #endif
-    }
+inline void getLocalTime(const time_t* localTime, struct tm* localTM)
+{
+#if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) || OS(WINCE)
+    *localTM = *localtime(localTime);
+#elif COMPILER(MSVC)
+    localtime_s(localTM, localTime);
+#else
+    localtime_r(localTime, localTM);
+#endif
+}
 
 } // namespace WTF
 
 using WTF::currentTime;
+using WTF::currentTimeMS;
 using WTF::getLocalTime;
 
 #endif // CurrentTime_h
index b9a0207a4c9216a4af333d267dd8f3fe5567a86d..70c0cf47f5f79cbfc331f7a17fa97e9a7cbc67dc 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
  * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ * Copyright (C) 2010 &yet, LLC. (nate@andyet.net)
  *
  * The Original Code is Mozilla Communicator client code, released
  * March 31, 1998.
 #include "Assertions.h"
 #include "ASCIICType.h"
 #include "CurrentTime.h"
+#if USE(JSC)
+#include "JSObject.h"
+#endif
 #include "MathExtras.h"
+#if USE(JSC)
+#include "ScopeChain.h"
+#endif
+#include "StdLibExtras.h"
 #include "StringExtras.h"
 
 #include <algorithm>
@@ -377,7 +385,7 @@ int equivalentYearForDST(int year)
     return year;
 }
 
-static int32_t calculateUTCOffset()
+int32_t calculateUTCOffset()
 {
 #if PLATFORM(BREWMP)
     time_t localTime = static_cast<time_t>(currentTime());
@@ -447,7 +455,7 @@ static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset
 }
 
 // Get the DST offset, given a time in UTC
-static double calculateDSTOffset(double ms, double utcOffset)
+double calculateDSTOffset(double ms, double utcOffset)
 {
     // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will return historically accurate
     // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
@@ -479,7 +487,7 @@ void initializeDates()
     equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
 }
 
-static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second)
+static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, double second)
 {
     double days = (day - 32075)
         + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4)
@@ -557,6 +565,162 @@ static bool parseLong(const char* string, char** stopPosition, int base, long* r
     return true;
 }
 
+double parseES5DateFromNullTerminatedCharacters(const char* dateString)
+{
+    // This parses a date of the form defined in ECMA-262-5, section 15.9.1.15
+    // (similar to RFC 3339 / ISO 8601: YYYY-MM-DDTHH:mm:ss[.sss]Z).
+    // In most cases it is intentionally strict (e.g. correct field widths, no stray whitespace).
+    
+    static const long daysPerMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+    
+    const char* currentPosition = dateString;
+    char* postParsePosition;
+    
+    // This is a bit more lenient on the year string than ES5 specifies:
+    // instead of restricting to 4 digits (or 6 digits with mandatory +/-),
+    // it accepts any integer value. Consider this an implementation fallback.
+    long year;
+    if (!parseLong(currentPosition, &postParsePosition, 10, &year))
+        return NaN;
+    if (*postParsePosition != '-')
+        return NaN;
+    currentPosition = postParsePosition + 1;
+    
+    long month;
+    if (!isASCIIDigit(*currentPosition))
+        return NaN;
+    if (!parseLong(currentPosition, &postParsePosition, 10, &month))
+        return NaN;
+    if (*postParsePosition != '-' || (postParsePosition - currentPosition) != 2)
+        return NaN;
+    currentPosition = postParsePosition + 1;
+    
+    long day;
+    if (!isASCIIDigit(*currentPosition))
+        return NaN;
+    if (!parseLong(currentPosition, &postParsePosition, 10, &day))
+        return NaN;
+    if (*postParsePosition != 'T' || (postParsePosition - currentPosition) != 2)
+        return NaN;
+    currentPosition = postParsePosition + 1;
+    
+    long hours;
+    if (!isASCIIDigit(*currentPosition))
+        return NaN;
+    if (!parseLong(currentPosition, &postParsePosition, 10, &hours))
+        return NaN;
+    if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2)
+        return NaN;
+    currentPosition = postParsePosition + 1;
+    
+    long minutes;
+    if (!isASCIIDigit(*currentPosition))
+        return NaN;
+    if (!parseLong(currentPosition, &postParsePosition, 10, &minutes))
+        return NaN;
+    if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2)
+        return NaN;
+    currentPosition = postParsePosition + 1;
+    
+    long intSeconds;
+    if (!isASCIIDigit(*currentPosition))
+        return NaN;
+    if (!parseLong(currentPosition, &postParsePosition, 10, &intSeconds))
+        return NaN;
+    if ((postParsePosition - currentPosition) != 2)
+        return NaN;
+    
+    double seconds = intSeconds;
+    if (*postParsePosition == '.') {
+        currentPosition = postParsePosition + 1;
+        
+        // In ECMA-262-5 it's a bit unclear if '.' can be present without milliseconds, but
+        // a reasonable interpretation guided by the given examples and RFC 3339 says "no".
+        // We check the next character to avoid reading +/- timezone hours after an invalid decimal.
+        if (!isASCIIDigit(*currentPosition))
+            return NaN;
+        
+        // We are more lenient than ES5 by accepting more or less than 3 fraction digits.
+        long fracSeconds;
+        if (!parseLong(currentPosition, &postParsePosition, 10, &fracSeconds))
+            return NaN;
+        
+        long numFracDigits = postParsePosition - currentPosition;
+        seconds += fracSeconds * pow(10.0, static_cast<double>(-numFracDigits));
+    }
+    currentPosition = postParsePosition;
+    
+    // A few of these checks could be done inline above, but since many of them are interrelated
+    // we would be sacrificing readability to "optimize" the (presumably less common) failure path.
+    if (month < 1 || month > 12)
+        return NaN;
+    if (day < 1 || day > daysPerMonth[month - 1])
+        return NaN;
+    if (month == 2 && day > 28 && !isLeapYear(year))
+        return NaN;
+    if (hours < 0 || hours > 24)
+        return NaN;
+    if (hours == 24 && (minutes || seconds))
+        return NaN;
+    if (minutes < 0 || minutes > 59)
+        return NaN;
+    if (seconds < 0 || seconds >= 61)
+        return NaN;
+    if (seconds > 60) {
+        // Discard leap seconds by clamping to the end of a minute.
+        seconds = 60;
+    }
+    
+    long timeZoneSeconds = 0;
+    if (*currentPosition != 'Z') {
+        bool tzNegative;
+        if (*currentPosition == '-')
+            tzNegative = true;
+        else if (*currentPosition == '+')
+            tzNegative = false;
+        else
+            return NaN;
+        currentPosition += 1;
+        
+        long tzHours;
+        long tzHoursAbs;
+        long tzMinutes;
+        
+        if (!isASCIIDigit(*currentPosition))
+            return NaN;
+        if (!parseLong(currentPosition, &postParsePosition, 10, &tzHours))
+            return NaN;
+        if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2)
+            return NaN;
+        tzHoursAbs = abs(tzHours);
+        currentPosition = postParsePosition + 1;
+        
+        if (!isASCIIDigit(*currentPosition))
+            return NaN;
+        if (!parseLong(currentPosition, &postParsePosition, 10, &tzMinutes))
+            return NaN;
+        if ((postParsePosition - currentPosition) != 2)
+            return NaN;
+        currentPosition = postParsePosition;
+        
+        if (tzHoursAbs > 24)
+            return NaN;
+        if (tzMinutes < 0 || tzMinutes > 59)
+            return NaN;
+        
+        timeZoneSeconds = 60 * (tzMinutes + (60 * tzHoursAbs));
+        if (tzNegative)
+            timeZoneSeconds = -timeZoneSeconds;
+    } else {
+        currentPosition += 1;
+    }
+    if (*currentPosition)
+        return NaN;
+    
+    double dateSeconds = ymdhmsToSeconds(year, month, day, hours, minutes, seconds) - timeZoneSeconds;
+    return dateSeconds * msPerSecond;
+}
+
 // Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore.
 static double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset)
 {
@@ -762,6 +926,16 @@ static double parseDateFromNullTerminatedCharacters(const char* dateString, bool
             }
         }
     }
+    
+    // The year may be after the time but before the time zone, but don't
+    // confuse a time zone specificed as an offset from UTC (e.g. +0100) with a
+    // four-digit year.
+    if (year <= 0 && *dateString != '+' && *dateString != '-') {
+       if (!parseLong(dateString, &newPosStr, 10, &year))
+          year = 0;
+       dateString = newPosStr;
+       skipSpacesAndComments(dateString);
+    }
 
     // Don't fail if the time zone is missing. 
     // Some websites omit the time zone (4275206).
@@ -793,7 +967,7 @@ static double parseDateFromNullTerminatedCharacters(const char* dateString, bool
             }
             haveTZ = true;
         } else {
-            for (int i = 0; i < int(sizeof(known_zones) / sizeof(KnownZone)); i++) {
+            for (size_t i = 0; i < WTF_ARRAY_LENGTH(known_zones); ++i) {
                 if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) {
                     offset = known_zones[i].tzOffset;
                     dateString += strlen(known_zones[i].tzName);
@@ -971,7 +1145,7 @@ void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, Gregori
     tm.year     =  year - 1900;
     tm.isDST    =  dstOff != 0.0;
     tm.utcOffset = static_cast<long>((dstOff + utcOff) / WTF::msPerSecond);
-    tm.timeZone = NULL;
+    tm.timeZone = nullptr;
 }
 
 double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString)
index 033d25e2206688c5f0acfcc0c35d4b485819a88b..2ac284e7d8e15985d62e3342a95f87cdfae57376 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Research In Motion Limited. All rights reserved.
  *
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
 #define DateMath_h
 
 #include <math.h>
+#include <stdint.h>
 #include <string.h>
 #include <time.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/PassOwnArrayPtr.h>
 #include <wtf/UnusedParam.h>
 
 namespace WTF {
 void initializeDates();
 int equivalentYearForDST(int year);
 
-// Not really math related, but this is currently the only shared place to put these.  
+// Not really math related, but this is currently the only shared place to put these.
+double parseES5DateFromNullTerminatedCharacters(const char* dateString);
 double parseDateFromNullTerminatedCharacters(const char* dateString);
 double timeClip(double);
 
@@ -83,17 +88,26 @@ int dayInYear(double ms, int year);
 int monthFromDayInYear(int dayInYear, bool leapYear);
 int dayInMonthFromDayInYear(int dayInYear, bool leapYear);
 
+// Returns offset milliseconds for UTC and DST.
+int32_t calculateUTCOffset();
+double calculateDSTOffset(double ms, double utcOffset);
+
 } // namespace WTF
 
+using WTF::adoptArrayPtr;
 using WTF::dateToDaysFrom1970;
 using WTF::dayInMonthFromDayInYear;
 using WTF::dayInYear;
 using WTF::minutesPerHour;
 using WTF::monthFromDayInYear;
 using WTF::msPerDay;
+using WTF::msPerMinute;
 using WTF::msPerSecond;
 using WTF::msToYear;
 using WTF::secondsPerMinute;
+using WTF::parseDateFromNullTerminatedCharacters;
+using WTF::calculateUTCOffset;
+using WTF::calculateDSTOffset;
 
 #if USE(JSC)
 namespace JSC {
@@ -107,7 +121,9 @@ double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString)
 
 // Intentionally overridding the default tm of the system.
 // The members of tm differ on various operating systems.
-struct GregorianDateTime : Noncopyable {
+struct GregorianDateTime {
+    WTF_MAKE_NONCOPYABLE(GregorianDateTime);
+public:
     GregorianDateTime()
         : second(0)
         , minute(0)
@@ -119,13 +135,7 @@ struct GregorianDateTime : Noncopyable {
         , year(0)
         , isDST(0)
         , utcOffset(0)
-        , timeZone(0)
-    {
-    }
-
-    ~GregorianDateTime()
     {
-        delete [] timeZone;
     }
 
     GregorianDateTime(ExecState* exec, const tm& inTm)
@@ -148,10 +158,10 @@ struct GregorianDateTime : Noncopyable {
 
 #if HAVE(TM_ZONE)
         int inZoneSize = strlen(inTm.tm_zone) + 1;
-        timeZone = new char[inZoneSize];
-        strncpy(timeZone, inTm.tm_zone, inZoneSize);
+        timeZone = adoptArrayPtr(new char[inZoneSize]);
+        strncpy(timeZone.get(), inTm.tm_zone, inZoneSize);
 #else
-        timeZone = 0;
+        timeZone = nullptr;
 #endif
     }
 
@@ -174,7 +184,7 @@ struct GregorianDateTime : Noncopyable {
         ret.tm_gmtoff = static_cast<long>(utcOffset);
 #endif
 #if HAVE(TM_ZONE)
-        ret.tm_zone = timeZone;
+        ret.tm_zone = timeZone.get();
 #endif
 
         return ret;
@@ -193,11 +203,11 @@ struct GregorianDateTime : Noncopyable {
         isDST = rhs.isDST;
         utcOffset = rhs.utcOffset;
         if (rhs.timeZone) {
-            int inZoneSize = strlen(rhs.timeZone) + 1;
-            timeZone = new char[inZoneSize];
-            strncpy(timeZone, rhs.timeZone, inZoneSize);
+            int inZoneSize = strlen(rhs.timeZone.get()) + 1;
+            timeZone = adoptArrayPtr(new char[inZoneSize]);
+            strncpy(timeZone.get(), rhs.timeZone.get(), inZoneSize);
         } else
-            timeZone = 0;
+            timeZone = nullptr;
     }
 
     int second;
@@ -210,7 +220,7 @@ struct GregorianDateTime : Noncopyable {
     int year;
     int isDST;
     int utcOffset;
-    char* timeZone;
+    OwnArrayPtr<char> timeZone;
 };
 
 static inline int gmtoffset(const GregorianDateTime& t)
diff --git a/wtf/DecimalNumber.cpp b/wtf/DecimalNumber.cpp
new file mode 100644 (file)
index 0000000..70304e2
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2010 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. 
+ */
+
+#include "config.h"
+#include "DecimalNumber.h"
+#include <math.h>
+#include <wtf/MathExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+unsigned DecimalNumber::bufferLengthForStringDecimal() const
+{
+    unsigned length = 0;
+    // if the exponent is negative the number decimal representation is of the form:
+    // [<sign>]0.[<zeros>]<significand>
+    if (m_exponent < 0) {
+        if (m_sign)
+            ++length;
+        length += 2; // for "0."
+        length += -m_exponent - 1;
+        length += m_precision;
+        return length;
+    }
+
+    unsigned digitsBeforeDecimalPoint = m_exponent + 1;
+
+    // If the precision is <= than the number of digits to get up to the decimal
+    // point, then there is no fractional part, number is of the form:
+    // [<sign>]<significand>[<zeros>]
+    if (m_precision <= digitsBeforeDecimalPoint) {
+        if (m_sign)
+            ++length;
+        length += m_precision;
+        length += digitsBeforeDecimalPoint - m_precision;
+        return length;
+    }
+
+    // If we get here, number starts before the decimal point, and ends after it,
+    // as such is of the form:
+    // [<sign>]<significand-begin>.<significand-end>
+    if (m_sign)
+        ++length;
+    length += digitsBeforeDecimalPoint;
+    ++length; // for decimal point
+    length += m_precision - digitsBeforeDecimalPoint;
+
+    return length;
+}
+
+unsigned DecimalNumber::bufferLengthForStringExponential() const
+{
+    unsigned length = 0;
+    if (m_sign)
+        ++length;
+
+    // Add the significand
+    ++length;
+
+    if (m_precision > 1) {
+        ++length; // for decimal point
+        length += m_precision - 1;
+    }
+
+    // Add "e+" or "e-"
+    length += 2;
+
+    int exponent = (m_exponent >= 0) ? m_exponent : -m_exponent;
+
+    // Add the exponent
+    if (exponent >= 100)
+        ++length;
+    if (exponent >= 10)
+        ++length;
+    ++length;
+
+    return length;
+}
+
+unsigned DecimalNumber::toStringDecimal(UChar* buffer, unsigned bufferLength) const
+{
+    ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringDecimal());
+
+    // Should always be at least one digit to add to the string!
+    ASSERT(m_precision);
+    UChar* next = buffer;
+
+    // if the exponent is negative the number decimal representation is of the form:
+    // [<sign>]0.[<zeros>]<significand>
+    if (m_exponent < 0) {
+        unsigned zeros = -m_exponent - 1;
+
+        if (m_sign)
+            *next++ = '-';
+        *next++ = '0';
+        *next++ = '.';
+        for (unsigned i = 0; i < zeros; ++i)
+            *next++ = '0';
+        for (unsigned i = 0; i < m_precision; ++i)
+            *next++ = m_significand[i];
+
+        return next - buffer;
+    }
+
+    unsigned digitsBeforeDecimalPoint = m_exponent + 1;
+
+    // If the precision is <= than the number of digits to get up to the decimal
+    // point, then there is no fractional part, number is of the form:
+    // [<sign>]<significand>[<zeros>]
+    if (m_precision <= digitsBeforeDecimalPoint) {
+        if (m_sign)
+            *next++ = '-';
+        for (unsigned i = 0; i < m_precision; ++i)
+            *next++ = m_significand[i];
+        for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i)
+            *next++ = '0';
+
+        return next - buffer;
+    }
+
+    // If we get here, number starts before the decimal point, and ends after it,
+    // as such is of the form:
+    // [<sign>]<significand-begin>.<significand-end>
+
+    if (m_sign)
+        *next++ = '-';
+    for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i)
+        *next++ = m_significand[i];
+    *next++ = '.';
+    for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i)
+        *next++ = m_significand[i];
+
+    return next - buffer;
+}
+
+unsigned DecimalNumber::toStringExponential(UChar* buffer, unsigned bufferLength) const
+{
+    ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringExponential());
+
+    // Should always be at least one digit to add to the string!
+    ASSERT(m_precision);
+    UChar* next = buffer;
+
+    // Add the sign
+    if (m_sign)
+        *next++ = '-';
+
+    // Add the significand
+    *next++ = m_significand[0];
+    if (m_precision > 1) {
+        *next++ = '.';
+        for (unsigned i = 1; i < m_precision; ++i)
+            *next++ = m_significand[i];
+    }
+
+    // Add "e+" or "e-"
+    *next++ = 'e';
+    int exponent;
+    if (m_exponent >= 0) {
+        *next++ = '+';
+        exponent = m_exponent;
+    } else {
+        *next++ = '-';
+        exponent = -m_exponent;
+    }
+
+    // Add the exponent
+    if (exponent >= 100)
+        *next++ = '0' + exponent / 100;
+    if (exponent >= 10)
+        *next++ = '0' + (exponent % 100) / 10;
+    *next++ = '0' + exponent % 10;
+
+    return next - buffer;
+}
+
+} // namespace WTF
diff --git a/wtf/DecimalNumber.h b/wtf/DecimalNumber.h
new file mode 100644 (file)
index 0000000..c42f00b
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2010 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 DecimalNumber_h
+#define DecimalNumber_h
+
+#include <math.h>
+#include <wtf/dtoa.h>
+#include <wtf/MathExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+enum RoundingSignificantFiguresType { RoundingSignificantFigures };
+enum RoundingDecimalPlacesType { RoundingDecimalPlaces };
+
+class DecimalNumber {
+public:
+    DecimalNumber(double d)
+    {
+        ASSERT(!isnan(d) && !isinf(d));
+        dtoa(m_significand, d, m_sign, m_exponent, m_precision);
+
+        ASSERT(m_precision);
+        // Zero should always have exponent 0.
+        ASSERT(m_significand[0] != '0' || !m_exponent);
+        // No values other than zero should have a leading zero.
+        ASSERT(m_significand[0] != '0' || m_precision == 1);
+        // No values other than zero should have trailing zeros.
+        ASSERT(m_significand[0] == '0' || m_significand[m_precision - 1] != '0');
+    }
+
+    DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures)
+    {
+        ASSERT(!isnan(d) && !isinf(d));
+        dtoaRoundSF(m_significand, d, significantFigures, m_sign, m_exponent, m_precision);
+
+        ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer));
+        while (m_precision < significantFigures)
+            m_significand[m_precision++] = '0';
+
+        ASSERT(m_precision);
+        // Zero should always have exponent 0.
+        ASSERT(m_significand[0] != '0' || !m_exponent);
+    }
+
+    DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces)
+    {
+        ASSERT(!isnan(d) && !isinf(d));
+        dtoaRoundDP(m_significand, d, decimalPlaces, m_sign, m_exponent, m_precision);
+
+        unsigned significantFigures = 1 + m_exponent + decimalPlaces;
+        ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer));
+        while (m_precision < significantFigures)
+            m_significand[m_precision++] = '0';
+
+        ASSERT(m_precision);
+        // Zero should always have exponent 0.
+        ASSERT(m_significand[0] != '0' || !m_exponent);
+    }
+
+    unsigned bufferLengthForStringDecimal() const;
+    unsigned bufferLengthForStringExponential() const;
+
+    unsigned toStringDecimal(UChar* buffer, unsigned bufferLength) const;
+    unsigned toStringExponential(UChar* buffer, unsigned bufferLength) const;
+
+    bool sign() const { return m_sign; }
+    int exponent() const { return m_exponent; }
+    const char* significand() const { return m_significand; } // significand contains precision characters, is not null-terminated.
+    unsigned precision() const { return m_precision; }
+
+private:
+    bool m_sign;
+    int m_exponent;
+    DtoaBuffer m_significand;
+    unsigned m_precision;
+};
+
+} // namespace WTF
+
+using WTF::DecimalNumber;
+using WTF::RoundingSignificantFigures;
+using WTF::RoundingDecimalPlaces;
+
+#endif // DecimalNumber_h
diff --git a/wtf/Decoder.h b/wtf/Decoder.h
new file mode 100644 (file)
index 0000000..341d58d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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 Decoder_h
+#define Decoder_h
+
+#include <wtf/Vector.h>
+
+namespace WTF {
+
+class String;
+
+class Decoder {
+protected:
+    Decoder() { }
+    virtual ~Decoder() { }
+    
+public:
+    virtual bool decodeBytes(Vector<uint8_t>&) = 0;
+
+    virtual bool decodeBool(bool&) = 0;
+    virtual bool decodeUInt32(uint32_t&) = 0;
+    virtual bool decodeUInt64(uint64_t&) = 0;
+    virtual bool decodeInt32(int32_t&) = 0;
+    virtual bool decodeInt64(int64_t&) = 0;
+    virtual bool decodeFloat(float&) = 0;
+    virtual bool decodeDouble(double&) = 0;
+    virtual bool decodeString(String&) = 0;
+};
+
+} // namespace WTF
+
+using WTF::Decoder;
+
+#endif // Decoder_h
index 3c3d378fc5896fedf28d1cf4b2bd643a238cd18f..8e42335f8de19014c97659c88a4d2fb9fe237ee8 100644 (file)
 // FIXME: Could move what Vector and Deque share into a separate file.
 // Deque doesn't actually use Vector.
 
+#include "PassTraits.h"
 #include "Vector.h"
 
 namespace WTF {
 
-    template<typename T> class DequeIteratorBase;
-    template<typename T> class DequeIterator;
-    template<typename T> class DequeConstIterator;
-    template<typename T> class DequeReverseIterator;
-    template<typename T> class DequeConstReverseIterator;
+    template<typename T, size_t inlineCapacity> class DequeIteratorBase;
+    template<typename T, size_t inlineCapacity> class DequeIterator;
+    template<typename T, size_t inlineCapacity> class DequeConstIterator;
+    template<typename T, size_t inlineCapacity> class DequeReverseIterator;
+    template<typename T, size_t inlineCapacity> class DequeConstReverseIterator;
 
-    template<typename T>
-    class Deque : public FastAllocBase {
+    template<typename T, size_t inlineCapacity = 0>
+    class Deque {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
-        typedef DequeIterator<T> iterator;
-        typedef DequeConstIterator<T> const_iterator;
-        typedef DequeReverseIterator<T> reverse_iterator;
-        typedef DequeConstReverseIterator<T> const_reverse_iterator;
+        typedef DequeIterator<T, inlineCapacity> iterator;
+        typedef DequeConstIterator<T, inlineCapacity> const_iterator;
+        typedef DequeReverseIterator<T, inlineCapacity> reverse_iterator;
+        typedef DequeConstReverseIterator<T, inlineCapacity> const_reverse_iterator;
+        typedef PassTraits<T> Pass;
+        typedef typename PassTraits<T>::PassType PassType;
 
         Deque();
-        Deque(const Deque<T>&);
-        Deque& operator=(const Deque<T>&);
+        Deque(const Deque<T, inlineCapacity>&);
+        Deque& operator=(const Deque<T, inlineCapacity>&);
         ~Deque();
 
-        void swap(Deque<T>&);
+        void swap(Deque<T, inlineCapacity>&);
 
         size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; }
         bool isEmpty() const { return m_start == m_end; }
@@ -72,6 +76,7 @@ namespace WTF {
 
         T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
         const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; }
+        PassType takeFirst();
 
         template<typename U> void append(const U&);
         template<typename U> void prepend(const U&);
@@ -85,11 +90,11 @@ namespace WTF {
         iterator findIf(Predicate&);
 
     private:
-        friend class DequeIteratorBase<T>;
+        friend class DequeIteratorBase<T, inlineCapacity>;
 
-        typedef VectorBuffer<T, 0> Buffer;
+        typedef VectorBuffer<T, inlineCapacity> Buffer;
         typedef VectorTypeOperations<T> TypeOperations;
-        typedef DequeIteratorBase<T> IteratorBase;
+        typedef DequeIteratorBase<T, inlineCapacity> IteratorBase;
 
         void remove(size_t position);
         void invalidateIterators();
@@ -107,14 +112,14 @@ namespace WTF {
 #endif
     };
 
-    template<typename T>
+    template<typename T, size_t inlineCapacity = 0>
     class DequeIteratorBase {
     private:
-        typedef DequeIteratorBase<T> Base;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
 
     protected:
         DequeIteratorBase();
-        DequeIteratorBase(const Deque<T>*, size_t);
+        DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t);
         DequeIteratorBase(const Base&);
         Base& operator=(const Base&);
         ~DequeIteratorBase();
@@ -135,10 +140,10 @@ namespace WTF {
         void checkValidity() const;
         void checkValidity(const Base&) const;
 
-        Deque<T>* m_deque;
+        Deque<T, inlineCapacity>* m_deque;
         size_t m_index;
 
-        friend class Deque<T>;
+        friend class Deque<T, inlineCapacity>;
 
 #ifndef NDEBUG
         mutable DequeIteratorBase* m_next;
@@ -146,14 +151,14 @@ namespace WTF {
 #endif
     };
 
-    template<typename T>
-    class DequeIterator : public DequeIteratorBase<T> {
+    template<typename T, size_t inlineCapacity = 0>
+    class DequeIterator : public DequeIteratorBase<T, inlineCapacity> {
     private:
-        typedef DequeIteratorBase<T> Base;
-        typedef DequeIterator<T> Iterator;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
+        typedef DequeIterator<T, inlineCapacity> Iterator;
 
     public:
-        DequeIterator(Deque<T>* deque, size_t index) : Base(deque, index) { }
+        DequeIterator(Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { }
 
         DequeIterator(const Iterator& other) : Base(other) { }
         DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
@@ -170,15 +175,15 @@ namespace WTF {
         // postfix -- intentionally omitted
     };
 
-    template<typename T>
-    class DequeConstIterator : public DequeIteratorBase<T> {
+    template<typename T, size_t inlineCapacity = 0>
+    class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity> {
     private:
-        typedef DequeIteratorBase<T> Base;
-        typedef DequeConstIterator<T> Iterator;
-        typedef DequeIterator<T> NonConstIterator;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
+        typedef DequeConstIterator<T, inlineCapacity> Iterator;
+        typedef DequeIterator<T, inlineCapacity> NonConstIterator;
 
     public:
-        DequeConstIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { }
+        DequeConstIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { }
 
         DequeConstIterator(const Iterator& other) : Base(other) { }
         DequeConstIterator(const NonConstIterator& other) : Base(other) { }
@@ -197,14 +202,14 @@ namespace WTF {
         // postfix -- intentionally omitted
     };
 
-    template<typename T>
-    class DequeReverseIterator : public DequeIteratorBase<T> {
+    template<typename T, size_t inlineCapacity = 0>
+    class DequeReverseIterator : public DequeIteratorBase<T, inlineCapacity> {
     private:
-        typedef DequeIteratorBase<T> Base;
-        typedef DequeReverseIterator<T> Iterator;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
+        typedef DequeReverseIterator<T, inlineCapacity> Iterator;
 
     public:
-        DequeReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { }
+        DequeReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { }
 
         DequeReverseIterator(const Iterator& other) : Base(other) { }
         DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; }
@@ -221,15 +226,15 @@ namespace WTF {
         // postfix -- intentionally omitted
     };
 
-    template<typename T>
-    class DequeConstReverseIterator : public DequeIteratorBase<T> {
+    template<typename T, size_t inlineCapacity = 0>
+    class DequeConstReverseIterator : public DequeIteratorBase<T, inlineCapacity> {
     private:
-        typedef DequeIteratorBase<T> Base;
-        typedef DequeConstReverseIterator<T> Iterator;
-        typedef DequeReverseIterator<T> NonConstIterator;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
+        typedef DequeConstReverseIterator<T, inlineCapacity> Iterator;
+        typedef DequeReverseIterator<T, inlineCapacity> NonConstIterator;
 
     public:
-        DequeConstReverseIterator(const Deque<T>* deque, size_t index) : Base(deque, index) { }
+        DequeConstReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { }
 
         DequeConstReverseIterator(const Iterator& other) : Base(other) { }
         DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { }
@@ -249,13 +254,17 @@ namespace WTF {
     };
 
 #ifdef NDEBUG
-    template<typename T> inline void Deque<T>::checkValidity() const { }
-    template<typename T> inline void Deque<T>::checkIndexValidity(size_t) const { }
-    template<typename T> inline void Deque<T>::invalidateIterators() { }
+    template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkValidity() const { }
+    template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkIndexValidity(size_t) const { }
+    template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::invalidateIterators() { }
 #else
-    template<typename T>
-    void Deque<T>::checkValidity() const
+    template<typename T, size_t inlineCapacity>
+    void Deque<T, inlineCapacity>::checkValidity() const
     {
+        // In this implementation a capacity of 1 would confuse append() and
+        // other places that assume the index after capacity - 1 is 0.
+        ASSERT(m_buffer.capacity() != 1);
+
         if (!m_buffer.capacity()) {
             ASSERT(!m_start);
             ASSERT(!m_end);
@@ -265,8 +274,8 @@ namespace WTF {
         }
     }
 
-    template<typename T>
-    void Deque<T>::checkIndexValidity(size_t index) const
+    template<typename T, size_t inlineCapacity>
+    void Deque<T, inlineCapacity>::checkIndexValidity(size_t index) const
     {
         ASSERT(index <= m_buffer.capacity());
         if (m_start <= m_end) {
@@ -277,8 +286,8 @@ namespace WTF {
         }
     }
 
-    template<typename T>
-    void Deque<T>::invalidateIterators()
+    template<typename T, size_t inlineCapacity>
+    void Deque<T, inlineCapacity>::invalidateIterators()
     {
         IteratorBase* next;
         for (IteratorBase* p = m_iterators; p; p = next) {
@@ -291,8 +300,8 @@ namespace WTF {
     }
 #endif
 
-    template<typename T>
-    inline Deque<T>::Deque()
+    template<typename T, size_t inlineCapacity>
+    inline Deque<T, inlineCapacity>::Deque()
         : m_start(0)
         , m_end(0)
 #ifndef NDEBUG
@@ -302,8 +311,8 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
-    inline Deque<T>::Deque(const Deque<T>& other)
+    template<typename T, size_t inlineCapacity>
+    inline Deque<T, inlineCapacity>::Deque(const Deque<T, inlineCapacity>& other)
         : m_start(other.m_start)
         , m_end(other.m_end)
         , m_buffer(other.m_buffer.capacity())
@@ -320,25 +329,27 @@ namespace WTF {
         }
     }
 
-    template<typename T>
-    void deleteAllValues(const Deque<T>& collection)
+    template<typename T, size_t inlineCapacity>
+    void deleteAllValues(const Deque<T, inlineCapacity>& collection)
     {
-        typedef typename Deque<T>::const_iterator iterator;
+        typedef typename Deque<T, inlineCapacity>::const_iterator iterator;
         iterator end = collection.end();
         for (iterator it = collection.begin(); it != end; ++it)
             delete *it;
     }
 
-    template<typename T>
-    inline Deque<T>& Deque<T>::operator=(const Deque<T>& other)
+    template<typename T, size_t inlineCapacity>
+    inline Deque<T, inlineCapacity>& Deque<T, inlineCapacity>::operator=(const Deque<T, inlineCapacity>& other)
     {
+        // FIXME: This is inefficient if we're using an inline buffer and T is
+        // expensive to copy since it will copy the buffer twice instead of once.
         Deque<T> copy(other);
         swap(copy);
         return *this;
     }
 
-    template<typename T>
-    inline void Deque<T>::destroyAll()
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::destroyAll()
     {
         if (m_start <= m_end)
             TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end);
@@ -348,16 +359,16 @@ namespace WTF {
         }
     }
 
-    template<typename T>
-    inline Deque<T>::~Deque()
+    template<typename T, size_t inlineCapacity>
+    inline Deque<T, inlineCapacity>::~Deque()
     {
         checkValidity();
         invalidateIterators();
         destroyAll();
     }
 
-    template<typename T>
-    inline void Deque<T>::swap(Deque<T>& other)
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::swap(Deque<T, inlineCapacity>& other)
     {
         checkValidity();
         other.checkValidity();
@@ -369,8 +380,8 @@ namespace WTF {
         other.checkValidity();
     }
 
-    template<typename T>
-    inline void Deque<T>::clear()
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::clear()
     {
         checkValidity();
         invalidateIterators();
@@ -380,9 +391,9 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
+    template<typename T, size_t inlineCapacity>
     template<typename Predicate>
-    inline DequeIterator<T> Deque<T>::findIf(Predicate& predicate)
+    inline DequeIterator<T, inlineCapacity> Deque<T, inlineCapacity>::findIf(Predicate& predicate)
     {
         iterator end_iterator = end();
         for (iterator it = begin(); it != end_iterator; ++it) {
@@ -392,8 +403,8 @@ namespace WTF {
         return end_iterator;
     }
 
-    template<typename T>
-    inline void Deque<T>::expandCapacityIfNeeded()
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::expandCapacityIfNeeded()
     {
         if (m_start) {
             if (m_end + 1 != m_start)
@@ -407,8 +418,8 @@ namespace WTF {
         expandCapacity();
     }
 
-    template<typename T>
-    void Deque<T>::expandCapacity()
+    template<typename T, size_t inlineCapacity>
+    void Deque<T, inlineCapacity>::expandCapacity()
     {
         checkValidity();
         size_t oldCapacity = m_buffer.capacity();
@@ -427,8 +438,16 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T> template<typename U>
-    inline void Deque<T>::append(const U& value)
+    template<typename T, size_t inlineCapacity>
+    inline typename Deque<T, inlineCapacity>::PassType Deque<T, inlineCapacity>::takeFirst()
+    {
+        T oldFirst = Pass::transfer(first());
+        removeFirst();
+        return Pass::transfer(oldFirst);
+    }
+
+    template<typename T, size_t inlineCapacity> template<typename U>
+    inline void Deque<T, inlineCapacity>::append(const U& value)
     {
         checkValidity();
         expandCapacityIfNeeded();
@@ -440,8 +459,8 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T> template<typename U>
-    inline void Deque<T>::prepend(const U& value)
+    template<typename T, size_t inlineCapacity> template<typename U>
+    inline void Deque<T, inlineCapacity>::prepend(const U& value)
     {
         checkValidity();
         expandCapacityIfNeeded();
@@ -453,8 +472,8 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
-    inline void Deque<T>::removeFirst()
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::removeFirst()
     {
         checkValidity();
         invalidateIterators();
@@ -467,22 +486,22 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
-    inline void Deque<T>::remove(iterator& it)
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::remove(iterator& it)
     {
         it.checkValidity();
         remove(it.m_index);
     }
 
-    template<typename T>
-    inline void Deque<T>::remove(const_iterator& it)
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::remove(const_iterator& it)
     {
         it.checkValidity();
         remove(it.m_index);
     }
 
-    template<typename T>
-    inline void Deque<T>::remove(size_t position)
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::remove(size_t position)
     {
         if (position == m_end)
             return;
@@ -505,28 +524,28 @@ namespace WTF {
     }
 
 #ifdef NDEBUG
-    template<typename T> inline void DequeIteratorBase<T>::checkValidity() const { }
-    template<typename T> inline void DequeIteratorBase<T>::checkValidity(const DequeIteratorBase<T>&) const { }
-    template<typename T> inline void DequeIteratorBase<T>::addToIteratorsList() { }
-    template<typename T> inline void DequeIteratorBase<T>::removeFromIteratorsList() { }
+    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity() const { }
+    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity(const DequeIteratorBase<T, inlineCapacity>&) const { }
+    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() { }
+    template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() { }
 #else
-    template<typename T>
-    void DequeIteratorBase<T>::checkValidity() const
+    template<typename T, size_t inlineCapacity>
+    void DequeIteratorBase<T, inlineCapacity>::checkValidity() const
     {
         ASSERT(m_deque);
         m_deque->checkIndexValidity(m_index);
     }
 
-    template<typename T>
-    void DequeIteratorBase<T>::checkValidity(const Base& other) const
+    template<typename T, size_t inlineCapacity>
+    void DequeIteratorBase<T, inlineCapacity>::checkValidity(const Base& other) const
     {
         checkValidity();
         other.checkValidity();
         ASSERT(m_deque == other.m_deque);
     }
 
-    template<typename T>
-    void DequeIteratorBase<T>::addToIteratorsList()
+    template<typename T, size_t inlineCapacity>
+    void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList()
     {
         if (!m_deque)
             m_next = 0;
@@ -539,8 +558,8 @@ namespace WTF {
         m_previous = 0;
     }
 
-    template<typename T>
-    void DequeIteratorBase<T>::removeFromIteratorsList()
+    template<typename T, size_t inlineCapacity>
+    void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList()
     {
         if (!m_deque) {
             ASSERT(!m_next);
@@ -564,23 +583,23 @@ namespace WTF {
     }
 #endif
 
-    template<typename T>
-    inline DequeIteratorBase<T>::DequeIteratorBase()
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase()
         : m_deque(0)
     {
     }
 
-    template<typename T>
-    inline DequeIteratorBase<T>::DequeIteratorBase(const Deque<T>* deque, size_t index)
-        : m_deque(const_cast<Deque<T>*>(deque))
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Deque<T, inlineCapacity>* deque, size_t index)
+        : m_deque(const_cast<Deque<T, inlineCapacity>*>(deque))
         , m_index(index)
     {
         addToIteratorsList();
         checkValidity();
     }
 
-    template<typename T>
-    inline DequeIteratorBase<T>::DequeIteratorBase(const Base& other)
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Base& other)
         : m_deque(other.m_deque)
         , m_index(other.m_index)
     {
@@ -588,8 +607,8 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
-    inline DequeIteratorBase<T>& DequeIteratorBase<T>::operator=(const Base& other)
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>& DequeIteratorBase<T, inlineCapacity>::operator=(const Base& other)
     {
         checkValidity();
         other.checkValidity();
@@ -602,8 +621,8 @@ namespace WTF {
         return *this;
     }
 
-    template<typename T>
-    inline DequeIteratorBase<T>::~DequeIteratorBase()
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase()
     {
 #ifndef NDEBUG
         removeFromIteratorsList();
@@ -611,15 +630,15 @@ namespace WTF {
 #endif
     }
 
-    template<typename T>
-    inline bool DequeIteratorBase<T>::isEqual(const Base& other) const
+    template<typename T, size_t inlineCapacity>
+    inline bool DequeIteratorBase<T, inlineCapacity>::isEqual(const Base& other) const
     {
         checkValidity(other);
         return m_index == other.m_index;
     }
 
-    template<typename T>
-    inline void DequeIteratorBase<T>::increment()
+    template<typename T, size_t inlineCapacity>
+    inline void DequeIteratorBase<T, inlineCapacity>::increment()
     {
         checkValidity();
         ASSERT(m_index != m_deque->m_end);
@@ -631,8 +650,8 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
-    inline void DequeIteratorBase<T>::decrement()
+    template<typename T, size_t inlineCapacity>
+    inline void DequeIteratorBase<T, inlineCapacity>::decrement()
     {
         checkValidity();
         ASSERT(m_index != m_deque->m_start);
@@ -644,16 +663,16 @@ namespace WTF {
         checkValidity();
     }
 
-    template<typename T>
-    inline T* DequeIteratorBase<T>::after() const
+    template<typename T, size_t inlineCapacity>
+    inline T* DequeIteratorBase<T, inlineCapacity>::after() const
     {
         checkValidity();
         ASSERT(m_index != m_deque->m_end);
         return &m_deque->m_buffer.buffer()[m_index];
     }
 
-    template<typename T>
-    inline T* DequeIteratorBase<T>::before() const
+    template<typename T, size_t inlineCapacity>
+    inline T* DequeIteratorBase<T, inlineCapacity>::before() const
     {
         checkValidity();
         ASSERT(m_index != m_deque->m_start);
diff --git a/wtf/DoublyLinkedList.h b/wtf/DoublyLinkedList.h
new file mode 100644 (file)
index 0000000..9351263
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 DoublyLinkedList_h
+#define DoublyLinkedList_h
+
+namespace WTF {
+
+template <typename Node> class DoublyLinkedList {
+public:
+    DoublyLinkedList();
+    
+    bool isEmpty();
+
+    Node* head();
+
+    void append(Node*);
+    void remove(Node*);
+
+private:
+    Node* m_head;
+    Node* m_tail;
+};
+
+template <typename Node> inline DoublyLinkedList<Node>::DoublyLinkedList()
+    : m_head(0)
+    , m_tail(0)
+{
+}
+
+template <typename Node> inline bool DoublyLinkedList<Node>::isEmpty()
+{
+    return !m_head;
+}
+
+template <typename Node> inline Node* DoublyLinkedList<Node>::head()
+{
+    return m_head;
+}
+
+template <typename Node> inline void DoublyLinkedList<Node>::append(Node* node)
+{
+    if (!m_tail) {
+        ASSERT(!m_head);
+        m_head = node;
+        m_tail = node;
+        node->setPrev(0);
+        node->setNext(0);
+        return;
+    }
+
+    ASSERT(m_head);
+    m_tail->setNext(node);
+    node->setPrev(m_tail);
+    node->setNext(0);
+    m_tail = node;
+}
+
+template <typename Node> inline void DoublyLinkedList<Node>::remove(Node* node)
+{
+    if (node->prev()) {
+        ASSERT(node != m_head);
+        node->prev()->setNext(node->next());
+    } else {
+        ASSERT(node == m_head);
+        m_head = node->next();
+    }
+
+    if (node->next()) {
+        ASSERT(node != m_tail);
+        node->next()->setPrev(node->prev());
+    } else {
+        ASSERT(node == m_tail);
+        m_tail = node->prev();
+    }
+}
+
+} // namespace WTF
+
+using WTF::DoublyLinkedList;
+
+#endif
diff --git a/wtf/DynamicAnnotations.cpp b/wtf/DynamicAnnotations.cpp
new file mode 100644 (file)
index 0000000..b7d4b41
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#include "config.h"
+
+#include "DynamicAnnotations.h"
+
+#if USE(DYNAMIC_ANNOTATIONS)
+void WTFAnnotateBenignRaceSized(const char*, int, const volatile void*, long, const char*) { }
+void WTFAnnotateHappensBefore(const char*, int, const volatile void*) { }
+void WTFAnnotateHappensAfter(const char*, int, const volatile void*) { }
+#endif // USE(DYNAMIC_ANNOTATIONS)
diff --git a/wtf/DynamicAnnotations.h b/wtf/DynamicAnnotations.h
new file mode 100644 (file)
index 0000000..38acce3
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 WTF_DynamicAnnotations_h
+#define WTF_DynamicAnnotations_h
+
+/* This file defines dynamic annotations for use with dynamic analysis
+ * tool such as ThreadSanitizer, Valgrind, etc.
+ *
+ * Dynamic annotation is a source code annotation that affects
+ * the generated code (that is, the annotation is not a comment).
+ * Each such annotation is attached to a particular
+ * instruction and/or to a particular object (address) in the program.
+ *
+ * By using dynamic annotations a developer can give more details to the dynamic
+ * analysis tool to improve its precision.
+ *
+ * In C/C++ program the annotations are represented as C macros.
+ * With the default build flags, these macros are empty, hence don't affect
+ * performance of a compiled binary.
+ * If dynamic annotations are enabled, they just call no-op functions.
+ * The dynamic analysis tools can intercept these functions and replace them
+ * with their own implementations.
+ *
+ * See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations for more information.
+ */
+
+#if USE(DYNAMIC_ANNOTATIONS)
+/* Tell data race detector that we're not interested in reports on the given address range. */
+#define WTF_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) WTFAnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
+#define WTF_ANNOTATE_BENIGN_RACE(pointer, description) WTFAnnotateBenignRaceSized(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+/* Annotations for user-defined synchronization mechanisms.
+ * These annotations can be used to define happens-before arcs in user-defined
+ * synchronization mechanisms: the race detector will infer an arc from
+ * the former to the latter when they share the same argument pointer.
+ *
+ * The most common case requiring annotations is atomic reference counting:
+ * bool deref() {
+ *     ANNOTATE_HAPPENS_BEFORE(&m_refCount);
+ *     if (!atomicDecrement(&m_refCount)) {
+ *         // m_refCount is now 0
+ *         ANNOTATE_HAPPENS_AFTER(&m_refCount);
+ *         // "return true; happens-after each atomicDecrement of m_refCount"
+ *         return true;
+ *     }
+ *     return false;
+ * }
+ */
+#define WTF_ANNOTATE_HAPPENS_BEFORE(address) WTFAnnotateHappensBefore(__FILE__, __LINE__, address)
+#define WTF_ANNOTATE_HAPPENS_AFTER(address) WTFAnnotateHappensAfter(__FILE__, __LINE__, address)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Don't use these directly, use the above macros instead. */
+void WTFAnnotateBenignRaceSized(const char* file, int line, const volatile void* memory, long size, const char* description);
+void WTFAnnotateHappensBefore(const char* file, int line, const volatile void* address);
+void WTFAnnotateHappensAfter(const char* file, int line, const volatile void* address);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#else // USE(DYNAMIC_ANNOTATIONS)
+/* These macros are empty when dynamic annotations are not enabled so you can
+ * use them without affecting the performance of release binaries. */
+#define WTF_ANNOTATE_BENIGN_RACE_SIZED(address, size, description)
+#define WTF_ANNOTATE_BENIGN_RACE(pointer, description)
+#define WTF_ANNOTATE_HAPPENS_BEFORE(address)
+#define WTF_ANNOTATE_HAPPENS_AFTER(address)
+#endif // USE(DYNAMIC_ANNOTATIONS)
+
+#endif // WTF_DynamicAnnotations_h
diff --git a/wtf/Encoder.h b/wtf/Encoder.h
new file mode 100644 (file)
index 0000000..109b0db
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 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 Encoder_h
+#define Encoder_h
+
+#include <stdint.h>
+
+namespace WTF {
+
+class String;
+
+class Encoder {
+protected:
+    Encoder() { }
+    virtual ~Encoder() { }
+    
+public:
+    virtual void encodeBytes(const uint8_t*, size_t) = 0;
+
+    virtual void encodeBool(bool) = 0;
+    virtual void encodeUInt32(uint32_t) = 0;
+    virtual void encodeUInt64(uint64_t) = 0;
+    virtual void encodeInt32(int32_t) = 0;
+    virtual void encodeInt64(int64_t) = 0;
+    virtual void encodeFloat(float) = 0;
+    virtual void encodeDouble(double) = 0;
+    virtual void encodeString(const String&) = 0;
+};
+
+} // namespace WTF
+
+using WTF::Encoder;
+
+#endif // Encoder_h
diff --git a/wtf/ExportMacros.h b/wtf/ExportMacros.h
new file mode 100644 (file)
index 0000000..3fadd37
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 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 COMPUTER, 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 COMPUTER, 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. 
+ *
+ * This file handles shared library symbol export decorations. It is recommended
+ * that all WebKit projects use these definitions so that symbol exports work
+ * properly on all platforms and compilers that WebKit builds under.
+ */
+
+#ifndef ExportMacros_h
+#define ExportMacros_h
+
+#include "Platform.h"
+
+#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC)
+#define WTF_EXPORT __declspec(dllexport)
+#define WTF_IMPORT __declspec(dllimport)
+#elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__)
+#define WTF_EXPORT __attribute__((visibility("default")))
+#define WTF_IMPORT WTF_EXPORT
+#else
+#define WTF_EXPORT
+#define WTF_IMPORT
+#endif
+
+#endif /* ExportMacros_h */
index 81b1de070e207fe2effa60bfe78cff20e3091351..e4899aba3f71911687cceeafd3f2ee73217bb1af 100644 (file)
@@ -32,8 +32,8 @@
 // Provides customizable overrides of fastMalloc/fastFree and operator new/delete
 //
 // Provided functionality:
+//    Macro: WTF_MAKE_FAST_ALLOCATED
 //    namespace WTF {
-//        class FastAllocBase;
 //
 //        T*    fastNew<T>();
 //        T*    fastNew<T>(arg);
 // FastDelete assumes that the underlying
 //
 // Example usage:
-//    class Widget : public FastAllocBase { ... };
+//    class Widget {
+//        WTF_MAKE_FAST_ALLOCATED
+//    ...
+//    };
+//
+//    struct Data {
+//        WTF_MAKE_FAST_ALLOCATED
+//    public:
+//    ...
+//    };
 //
 //    char* charPtr = fastNew<char>();
 //    fastDelete(charPtr);
 #include "FastMalloc.h"
 #include "TypeTraits.h"
 
-namespace WTF {
+#define WTF_MAKE_FAST_ALLOCATED \
+public: \
+    void* operator new(size_t, void* p) { return p; } \
+    void* operator new[](size_t, void* p) { return p; } \
+    \
+    void* operator new(size_t size) \
+    { \
+        void* p = ::WTF::fastMalloc(size); \
+         ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \
+        return p; \
+    } \
+    \
+    void operator delete(void* p) \
+    { \
+        ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \
+        ::WTF::fastFree(p); \
+    } \
+    \
+    void* operator new[](size_t size) \
+    { \
+        void* p = ::WTF::fastMalloc(size); \
+        ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \
+        return p; \
+    } \
+    \
+    void operator delete[](void* p) \
+    { \
+         ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \
+         ::WTF::fastFree(p); \
+    } \
+private: \
+typedef int ThisIsHereToForceASemicolonAfterThisMacro
 
-    class FastAllocBase {
-    public:
-        // Placement operator new.
-        void* operator new(size_t, void* p) { return p; }
-        void* operator new[](size_t, void* p) { return p; }
-
-        void* operator new(size_t size)
-        {
-            void* p = fastMalloc(size);
-            fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew);
-            return p;
-        }
-
-        void operator delete(void* p)
-        {
-            fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew);
-            fastFree(p);
-        }
-
-        void* operator new[](size_t size)
-        {
-            void* p = fastMalloc(size);
-            fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray);
-            return p;
-        }
-
-        void operator delete[](void* p)
-        {
-            fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray);
-            fastFree(p);
-        }
-    };
+namespace WTF {
 
     // fastNew / fastDelete
 
@@ -407,7 +416,6 @@ namespace WTF {
 
 } // namespace WTF
 
-using WTF::FastAllocBase;
 using WTF::fastDeleteSkippingDestructor;
 
 #endif // FastAllocBase_h
index 33e3d56cc35d760789dfdbc64a150e9a2a2e2152..c42c3c485ed4ef1c0159f931d515527b10862769 100644 (file)
@@ -1,6 +1,6 @@
 // Copyright (c) 2005, 2007, Google Inc.
 // All rights reserved.
-// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011 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
 
 #include "Assertions.h"
 #include <limits>
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
 #include <pthread.h>
 #endif
-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
-#include <System/pthread_machdep.h>
-#endif
+#include <wtf/StdLibExtras.h>
 
 #ifndef NO_TCMALLOC_SAMPLES
 #ifdef WTF_CHANGES
 #endif
 
 // Use a background thread to periodically scavenge memory to release back to the system
-// https://bugs.webkit.org/show_bug.cgi?id=27900: don't turn this on for Tiger until we have figured out why it caused a crash.
 #define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0
 
 #ifndef NDEBUG
 namespace WTF {
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
 static pthread_key_t isForbiddenKey;
 static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT;
 static void initializeIsForbiddenKey()
@@ -150,7 +147,7 @@ void fastMallocAllow()
 {
     staticIsForbidden = false;
 }
-#endif // ENABLE(JSC_MULTIPLE_THREADS)
+#endif // ENABLE(WTF_MULTIPLE_THREADS)
 
 } // namespace WTF
 #endif // NDEBUG
@@ -159,10 +156,13 @@ void fastMallocAllow()
 
 namespace WTF {
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
 
 namespace Internal {
-
+#if !ENABLE(WTF_MALLOC_VALIDATION)
+void fastMallocMatchFailed(void*);
+#else
+COMPILE_ASSERT(((sizeof(ValidationHeader) % sizeof(AllocAlignmentInteger)) == 0), ValidationHeader_must_produce_correct_alignment);
+#endif
 void fastMallocMatchFailed(void*)
 {
     CRASH();
@@ -170,7 +170,6 @@ void fastMallocMatchFailed(void*)
 
 } // namespace Internal
 
-#endif
 
 void* fastZeroedMalloc(size_t n) 
 {
@@ -181,15 +180,12 @@ void* fastZeroedMalloc(size_t n)
 
 char* fastStrDup(const char* src)
 {
-    int len = strlen(src) + 1;
+    size_t len = strlen(src) + 1;
     char* dup = static_cast<char*>(fastMalloc(len));
-
-    if (dup)
-        memcpy(dup, src, len);
-
+    memcpy(dup, src, len);
     return dup;
 }
-    
+
 TryMallocReturnValue tryFastZeroedMalloc(size_t n) 
 {
     void* result;
@@ -209,7 +205,7 @@ TryMallocReturnValue tryFastZeroedMalloc(size_t n)
 
 #if OS(DARWIN)
 #include <malloc/malloc.h>
-#elif COMPILER(MSVC)
+#elif OS(WINDOWS)
 #include <malloc.h>
 #endif
 
@@ -219,17 +215,20 @@ TryMallocReturnValue tryFastMalloc(size_t n)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n)  // If overflow would occur...
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n)  // If overflow would occur...
         return 0;
 
-    void* result = malloc(n + sizeof(AllocAlignmentInteger));
+    void* result = malloc(n + Internal::ValidationBufferSize);
     if (!result)
         return 0;
-
-    *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
-    result = static_cast<AllocAlignmentInteger*>(result) + 1;
-
+    Internal::ValidationHeader* header = static_cast<Internal::ValidationHeader*>(result);
+    header->m_size = n;
+    header->m_type = Internal::AllocTypeMalloc;
+    header->m_prefix = static_cast<unsigned>(Internal::ValidationPrefix);
+    result = header + 1;
+    *Internal::fastMallocValidationSuffix(result) = Internal::ValidationSuffix;
+    fastMallocValidate(result);
     return result;
 #else
     return malloc(n);
@@ -240,10 +239,11 @@ void* fastMalloc(size_t n)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     TryMallocReturnValue returnValue = tryFastMalloc(n);
     void* result;
-    returnValue.getValue(result);
+    if (!returnValue.getValue(result))
+        CRASH();
 #else
     void* result = malloc(n);
 #endif
@@ -265,19 +265,17 @@ TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     size_t totalBytes = n_elements * element_size;
-    if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements || (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes))
+    if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements)
         return 0;
 
-    totalBytes += sizeof(AllocAlignmentInteger);
-    void* result = malloc(totalBytes);
-    if (!result)
+    TryMallocReturnValue returnValue = tryFastMalloc(totalBytes);
+    void* result;
+    if (!returnValue.getValue(result))
         return 0;
-
     memset(result, 0, totalBytes);
-    *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
-    result = static_cast<AllocAlignmentInteger*>(result) + 1;
+    fastMallocValidate(result);
     return result;
 #else
     return calloc(n_elements, element_size);
@@ -288,10 +286,11 @@ void* fastCalloc(size_t n_elements, size_t element_size)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     TryMallocReturnValue returnValue = tryFastCalloc(n_elements, element_size);
     void* result;
-    returnValue.getValue(result);
+    if (!returnValue.getValue(result))
+        CRASH();
 #else
     void* result = calloc(n_elements, element_size);
 #endif
@@ -313,13 +312,13 @@ void fastFree(void* p)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     if (!p)
         return;
-
-    AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p);
-    if (*header != Internal::AllocTypeMalloc)
-        Internal::fastMallocMatchFailed(p);
+    
+    fastMallocMatchValidateFree(p, Internal::AllocTypeMalloc);
+    Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p);
+    memset(p, 0xCC, header->m_size);
     free(header);
 #else
     free(p);
@@ -330,20 +329,18 @@ TryMallocReturnValue tryFastRealloc(void* p, size_t n)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     if (p) {
-        if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= n)  // If overflow would occur...
+        if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n)  // If overflow would occur...
             return 0;
-        AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(p);
-        if (*header != Internal::AllocTypeMalloc)
-            Internal::fastMallocMatchFailed(p);
-        void* result = realloc(header, n + sizeof(AllocAlignmentInteger));
+        fastMallocValidate(p);
+        Internal::ValidationHeader* result = static_cast<Internal::ValidationHeader*>(realloc(Internal::fastMallocValidationHeader(p), n + Internal::ValidationBufferSize));
         if (!result)
             return 0;
-
-        // This should not be needed because the value is already there:
-        // *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
-        result = static_cast<AllocAlignmentInteger*>(result) + 1;
+        result->m_size = n;
+        result = result + 1;
+        *fastMallocValidationSuffix(result) = Internal::ValidationSuffix;
+        fastMallocValidate(result);
         return result;
     } else {
         return fastMalloc(n);
@@ -357,10 +354,11 @@ void* fastRealloc(void* p, size_t n)
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     TryMallocReturnValue returnValue = tryFastRealloc(p, n);
     void* result;
-    returnValue.getValue(result);
+    if (!returnValue.getValue(result))
+        CRASH();
 #else
     void* result = realloc(p, n);
 #endif
@@ -380,9 +378,12 @@ FastMallocStatistics fastMallocStatistics()
 
 size_t fastMallocSize(const void* p)
 {
-#if OS(DARWIN)
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    return Internal::fastMallocValidationHeader(const_cast<void*>(p))->m_size;
+#elif OS(DARWIN)
     return malloc_size(p);
-#elif COMPILER(MSVC)
+#elif OS(WINDOWS) && !PLATFORM(BREWMP)
+    // Brew MP uses its own memory allocator, so _msize does not work on the Brew MP simulator.
     return _msize(const_cast<void*>(p));
 #else
     return 1;
@@ -414,16 +415,18 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
 #include "TCSpinLock.h"
 #include "TCSystemAlloc.h"
 #include <algorithm>
-#include <errno.h>
 #include <limits>
 #include <pthread.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
 #if OS(UNIX)
 #include <unistd.h>
 #endif
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
@@ -437,10 +440,22 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
 #include <wtf/HashSet.h>
 #include <wtf/Vector.h>
 #endif
+
+#if HAVE(HEADER_DETECTION_H)
+#include "HeaderDetection.h"
+#endif
+
 #if HAVE(DISPATCH_H)
 #include <dispatch/dispatch.h>
 #endif
 
+#if HAVE(PTHREAD_MACHDEP_H)
+#include <System/pthread_machdep.h>
+
+#if defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0)
+#define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 1
+#endif
+#endif
 
 #ifndef PRIuS
 #define PRIuS "zu"
@@ -450,13 +465,13 @@ extern "C" const int jscore_fastmalloc_introspection = 0;
 // call to the function on Mac OS X, and it's used in performance-critical code. So we
 // use a function pointer. But that's not necessarily faster on other platforms, and we had
 // problems with this technique on Windows, so we'll do this only on Mac OS X.
-#if USE(PTHREAD_GETSPECIFIC_DIRECT)
-#define pthread_getspecific(key) _pthread_getspecific_direct(key)
-#define pthread_setspecific(key, val) _pthread_setspecific_direct(key, (val))
-#else
 #if OS(DARWIN)
+#if !USE(PTHREAD_GETSPECIFIC_DIRECT)
 static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific;
 #define pthread_getspecific(key) pthread_getspecific_function_pointer(key)
+#else
+#define pthread_getspecific(key) _pthread_getspecific_direct(key)
+#define pthread_setspecific(key, val) _pthread_setspecific_direct(key, (val))
 #endif
 #endif
 
@@ -1019,7 +1034,7 @@ class PageHeapAllocator {
         if (!new_allocation)
           CRASH();
 
-        *(void**)new_allocation = allocated_regions_;
+        *reinterpret_cast_ptr<void**>(new_allocation) = allocated_regions_;
         allocated_regions_ = new_allocation;
         free_area_ = new_allocation + kAlignedSize;
         free_avail_ = kAllocIncrement - kAlignedSize;
@@ -1044,11 +1059,8 @@ class PageHeapAllocator {
   template <class Recorder>
   void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader)
   {
-      vm_address_t adminAllocation = reinterpret_cast<vm_address_t>(allocated_regions_);
-      while (adminAllocation) {
-          recorder.recordRegion(adminAllocation, kAllocIncrement);
-          adminAllocation = *reader(reinterpret_cast<vm_address_t*>(adminAllocation));
-      }
+      for (void* adminAllocation = allocated_regions_; adminAllocation; adminAllocation = reader.nextEntryInLinkedList(reinterpret_cast<void**>(adminAllocation)))
+          recorder.recordRegion(reinterpret_cast<vm_address_t>(adminAllocation), kAllocIncrement);
   }
 #endif
 };
@@ -1286,6 +1298,8 @@ static const size_t kMinimumFreeCommittedPageCount = kMinSpanListsWithSpans * ((
 
 #endif
 
+static SpinLock pageheap_lock = SPINLOCK_INITIALIZER;
+
 class TCMalloc_PageHeap {
  public:
   void init();
@@ -1343,7 +1357,7 @@ class TCMalloc_PageHeap {
   }
 
   bool Check();
-  bool CheckList(Span* list, Length min_pages, Length max_pages);
+  bool CheckList(Span* list, Length min_pages, Length max_pages, bool decommitted);
 
   // Release all pages on the free list for reuse by the OS:
   void ReleaseFreePages();
@@ -1438,7 +1452,22 @@ class TCMalloc_PageHeap {
   void scavenge();
   ALWAYS_INLINE bool shouldScavenge() const;
 
-#if !HAVE(DISPATCH_H)
+#if HAVE(DISPATCH_H) || OS(WINDOWS)
+  void periodicScavenge();
+  ALWAYS_INLINE bool isScavengerSuspended();
+  ALWAYS_INLINE void scheduleScavenger();
+  ALWAYS_INLINE void rescheduleScavenger();
+  ALWAYS_INLINE void suspendScavenger();
+#endif
+
+#if HAVE(DISPATCH_H)
+  dispatch_queue_t m_scavengeQueue;
+  dispatch_source_t m_scavengeTimer;
+  bool m_scavengingSuspended;
+#elif OS(WINDOWS)
+  static void CALLBACK scavengerTimerFired(void*, BOOLEAN);
+  HANDLE m_scavengeQueueTimer;
+#else 
   static NO_RETURN_WITH_VALUE void* runScavengerThread(void*);
   NO_RETURN void scavengerThread();
 
@@ -1448,12 +1477,6 @@ class TCMalloc_PageHeap {
 
   pthread_mutex_t m_scavengeMutex;
   pthread_cond_t m_scavengeCondition;
-#else // !HAVE(DISPATCH_H)
-  void periodicScavenge();
-
-  dispatch_queue_t m_scavengeQueue;
-  dispatch_source_t m_scavengeTimer;
-  bool m_scavengingScheduled;
 #endif
 
 #endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
@@ -1489,50 +1512,122 @@ void TCMalloc_PageHeap::init()
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 
-#if !HAVE(DISPATCH_H)
+#if HAVE(DISPATCH_H)
 
 void TCMalloc_PageHeap::initializeScavenger()
 {
-  pthread_mutex_init(&m_scavengeMutex, 0);
-  pthread_cond_init(&m_scavengeCondition, 0);
-  m_scavengeThreadActive = true;
-  pthread_t thread;
-  pthread_create(&thread, 0, runScavengerThread, this);
+    m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL);
+    m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue);
+    dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeDelayInSeconds * NSEC_PER_SEC);
+    dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC);
+    dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); });
+    m_scavengingSuspended = true;
 }
 
-void* TCMalloc_PageHeap::runScavengerThread(void* context)
+ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended()
 {
-  static_cast<TCMalloc_PageHeap*>(context)->scavengerThread();
-#if COMPILER(MSVC)
-  // Without this, Visual Studio will complain that this method does not return a value.
-  return 0;
-#endif
+    ASSERT(pageheap_lock.IsHeld());
+    return m_scavengingSuspended;
 }
 
-ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger()
+ALWAYS_INLINE void TCMalloc_PageHeap::scheduleScavenger()
+{
+    ASSERT(pageheap_lock.IsHeld());
+    m_scavengingSuspended = false;
+    dispatch_resume(m_scavengeTimer);
+}
+
+ALWAYS_INLINE void TCMalloc_PageHeap::rescheduleScavenger()
+{
+    // Nothing to do here for libdispatch.
+}
+
+ALWAYS_INLINE void TCMalloc_PageHeap::suspendScavenger()
+{
+    ASSERT(pageheap_lock.IsHeld());
+    m_scavengingSuspended = true;
+    dispatch_suspend(m_scavengeTimer);
+}
+
+#elif OS(WINDOWS)
+
+void TCMalloc_PageHeap::scavengerTimerFired(void* context, BOOLEAN)
+{
+    static_cast<TCMalloc_PageHeap*>(context)->periodicScavenge();
+}
+
+void TCMalloc_PageHeap::initializeScavenger()
+{
+    m_scavengeQueueTimer = 0;
+}
+
+ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended()
+{
+    ASSERT(IsHeld(pageheap_lock));
+    return !m_scavengeQueueTimer;
+}
+
+ALWAYS_INLINE void TCMalloc_PageHeap::scheduleScavenger()
+{
+    // We need to use WT_EXECUTEONLYONCE here and reschedule the timer, because
+    // Windows will fire the timer event even when the function is already running.
+    ASSERT(IsHeld(pageheap_lock));
+    CreateTimerQueueTimer(&m_scavengeQueueTimer, 0, scavengerTimerFired, this, kScavengeDelayInSeconds * 1000, 0, WT_EXECUTEONLYONCE);
+}
+
+ALWAYS_INLINE void TCMalloc_PageHeap::rescheduleScavenger()
+{
+    // We must delete the timer and create it again, because it is not possible to retrigger a timer on Windows.
+    suspendScavenger();
+    scheduleScavenger();
+}
+
+ALWAYS_INLINE void TCMalloc_PageHeap::suspendScavenger()
 {
-  if (!m_scavengeThreadActive && shouldScavenge())
-    pthread_cond_signal(&m_scavengeCondition);
+    ASSERT(IsHeld(pageheap_lock));
+    HANDLE scavengeQueueTimer = m_scavengeQueueTimer;
+    m_scavengeQueueTimer = 0;
+    DeleteTimerQueueTimer(0, scavengeQueueTimer, 0);
 }
 
-#else // !HAVE(DISPATCH_H)
+#else
 
 void TCMalloc_PageHeap::initializeScavenger()
 {
-  m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL);
-  m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue);
-  dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeDelayInSeconds * NSEC_PER_SEC);
-  dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC);
-  dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); });
-  m_scavengingScheduled = false;
+    // Create a non-recursive mutex.
+#if !defined(PTHREAD_MUTEX_NORMAL) || PTHREAD_MUTEX_NORMAL == PTHREAD_MUTEX_DEFAULT
+    pthread_mutex_init(&m_scavengeMutex, 0);
+#else
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+
+    pthread_mutex_init(&m_scavengeMutex, &attr);
+
+    pthread_mutexattr_destroy(&attr);
+#endif
+
+    pthread_cond_init(&m_scavengeCondition, 0);
+    m_scavengeThreadActive = true;
+    pthread_t thread;
+    pthread_create(&thread, 0, runScavengerThread, this);
+}
+
+void* TCMalloc_PageHeap::runScavengerThread(void* context)
+{
+    static_cast<TCMalloc_PageHeap*>(context)->scavengerThread();
+#if (COMPILER(MSVC) || COMPILER(SUNCC))
+    // Without this, Visual Studio and Sun Studio will complain that this method does not return a value.
+    return 0;
+#endif
 }
 
 ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger()
 {
-  if (!m_scavengingScheduled && shouldScavenge()) {
-    m_scavengingScheduled = true;
-    dispatch_resume(m_scavengeTimer);
-  }
+    // m_scavengeMutex should be held before accessing m_scavengeThreadActive.
+    ASSERT(pthread_mutex_trylock(m_scavengeMutex));
+    if (!m_scavengeThreadActive && shouldScavenge())
+        pthread_cond_signal(&m_scavengeCondition);
 }
 
 #endif
@@ -1542,12 +1637,15 @@ void TCMalloc_PageHeap::scavenge()
     size_t pagesToRelease = min_free_committed_pages_since_last_scavenge_ * kScavengePercentage;
     size_t targetPageCount = std::max<size_t>(kMinimumFreeCommittedPageCount, free_committed_pages_ - pagesToRelease);
 
+    Length lastFreeCommittedPages = free_committed_pages_;
     while (free_committed_pages_ > targetPageCount) {
+        ASSERT(Check());
         for (int i = kMaxPages; i > 0 && free_committed_pages_ >= targetPageCount; i--) {
             SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i];
             // If the span size is bigger than kMinSpanListsWithSpans pages return all the spans in the list, else return all but 1 span.  
             // Return only 50% of a spanlist at a time so spans of size 1 are not the only ones left.
-            size_t numSpansToReturn = (i > kMinSpanListsWithSpans) ? DLL_Length(&slist->normal) : static_cast<size_t>(.5 * DLL_Length(&slist->normal));
+            size_t length = DLL_Length(&slist->normal);
+            size_t numSpansToReturn = (i > kMinSpanListsWithSpans) ? length : length / 2;
             for (int j = 0; static_cast<size_t>(j) < numSpansToReturn && !DLL_IsEmpty(&slist->normal) && free_committed_pages_ > targetPageCount; j++) {
                 Span* s = slist->normal.prev; 
                 DLL_Remove(s);
@@ -1562,6 +1660,10 @@ void TCMalloc_PageHeap::scavenge()
                 DLL_Prepend(&slist->returned, s);
             }
         }
+
+        if (lastFreeCommittedPages == free_committed_pages_)
+            break;
+        lastFreeCommittedPages = free_committed_pages_;
     }
 
     min_free_committed_pages_since_last_scavenge_ = free_committed_pages_;
@@ -2015,27 +2117,28 @@ bool TCMalloc_PageHeap::GrowHeap(Length n) {
 bool TCMalloc_PageHeap::Check() {
   ASSERT(free_[0].normal.next == &free_[0].normal);
   ASSERT(free_[0].returned.next == &free_[0].returned);
-  CheckList(&large_.normal, kMaxPages, 1000000000);
-  CheckList(&large_.returned, kMaxPages, 1000000000);
+  CheckList(&large_.normal, kMaxPages, 1000000000, false);
+  CheckList(&large_.returned, kMaxPages, 1000000000, true);
   for (Length s = 1; s < kMaxPages; s++) {
-    CheckList(&free_[s].normal, s, s);
-    CheckList(&free_[s].returned, s, s);
+    CheckList(&free_[s].normal, s, s, false);
+    CheckList(&free_[s].returned, s, s, true);
   }
   return true;
 }
 
 #if ASSERT_DISABLED
-bool TCMalloc_PageHeap::CheckList(Span*, Length, Length) {
+bool TCMalloc_PageHeap::CheckList(Span*, Length, Length, bool) {
   return true;
 }
 #else
-bool TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages) {
+bool TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages, bool decommitted) {
   for (Span* s = list->next; s != list; s = s->next) {
     CHECK_CONDITION(s->free);
     CHECK_CONDITION(s->length >= min_pages);
     CHECK_CONDITION(s->length <= max_pages);
     CHECK_CONDITION(GetDescriptor(s->start) == s);
     CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s);
+    CHECK_CONDITION(s->decommitted == decommitted);
   }
   return true;
 }
@@ -2047,6 +2150,7 @@ static void ReleaseFreeList(Span* list, Span* returned) {
   while (!DLL_IsEmpty(list)) {
     Span* s = list->prev;
     DLL_Remove(s);
+    s->decommitted = true;
     DLL_Prepend(returned, s);
     TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
                            static_cast<size_t>(s->length << kPageShift));
@@ -2120,7 +2224,7 @@ class TCMalloc_ThreadCache_FreeList {
   template <class Finder, class Reader>
   void enumerateFreeObjects(Finder& finder, const Reader& reader)
   {
-      for (void* nextObject = list_; nextObject; nextObject = *reader(reinterpret_cast<void**>(nextObject)))
+      for (void* nextObject = list_; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject)))
           finder.visit(nextObject);
   }
 #endif
@@ -2133,7 +2237,7 @@ class TCMalloc_ThreadCache_FreeList {
 class TCMalloc_ThreadCache {
  private:
   typedef TCMalloc_ThreadCache_FreeList FreeList;
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
   typedef DWORD ThreadIdentifier;
 #else
   typedef pthread_t ThreadIdentifier;
@@ -2245,7 +2349,7 @@ class TCMalloc_Central_FreeList {
     Span* remoteSpan = nonempty_.next;
 
     for (Span* span = reader(remoteSpan); span && remoteSpan != remoteNonempty; remoteSpan = span->next, span = (span->next ? reader(span->next) : 0)) {
-      for (void* nextObject = span->objects; nextObject; nextObject = *reader(reinterpret_cast<void**>(nextObject)))
+      for (void* nextObject = span->objects; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject)))
         finder.visit(nextObject);
     }
   }
@@ -2339,13 +2443,7 @@ class TCMalloc_Central_FreeListPadded : public TCMalloc_Central_FreeList {
 static TCMalloc_Central_FreeListPadded central_cache[kNumClasses];
 
 // Page-level allocator
-static SpinLock pageheap_lock = SPINLOCK_INITIALIZER;
-
-#if PLATFORM(ARM)
-static void* pageheap_memory[(sizeof(TCMalloc_PageHeap) + sizeof(void*) - 1) / sizeof(void*)] __attribute__((aligned));
-#else
 static AllocAlignmentInteger pageheap_memory[(sizeof(TCMalloc_PageHeap) + sizeof(AllocAlignmentInteger) - 1) / sizeof(AllocAlignmentInteger)];
-#endif
 static bool phinited = false;
 
 // Avoid extra level of indirection by making "pageheap" be just an alias
@@ -2365,13 +2463,29 @@ static inline TCMalloc_PageHeap* getPageHeap()
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 
-#if !HAVE(DISPATCH_H)
-#if OS(WINDOWS)
-static void sleep(unsigned seconds)
+#if HAVE(DISPATCH_H) || OS(WINDOWS)
+
+void TCMalloc_PageHeap::periodicScavenge()
 {
-    ::Sleep(seconds * 1000);
+    SpinLockHolder h(&pageheap_lock);
+    pageheap->scavenge();
+
+    if (shouldScavenge()) {
+        rescheduleScavenger();
+        return;
+    }
+
+    suspendScavenger();
 }
-#endif
+
+ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger()
+{
+    ASSERT(pageheap_lock.IsHeld());
+    if (isScavengerSuspended() && shouldScavenge())
+        scheduleScavenger();
+}
+
+#else
 
 void TCMalloc_PageHeap::scavengerThread()
 {
@@ -2396,21 +2510,7 @@ void TCMalloc_PageHeap::scavengerThread()
   }
 }
 
-#else
-
-void TCMalloc_PageHeap::periodicScavenge()
-{
-  {
-    SpinLockHolder h(&pageheap_lock);
-    pageheap->scavenge();
-  }
-
-  if (!shouldScavenge()) {
-    m_scavengingScheduled = false;
-    dispatch_suspend(m_scavengeTimer);
-  }
-}
-#endif // HAVE(DISPATCH_H)
+#endif
 
 #endif
 
@@ -2431,20 +2531,28 @@ static __thread TCMalloc_ThreadCache *threadlocal_heap;
 // Until then, we use a slow path to get the heap object.
 static bool tsd_inited = false;
 #if USE(PTHREAD_GETSPECIFIC_DIRECT)
-static pthread_key_t heap_key = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0;
+static const pthread_key_t heap_key = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0;
 #else
 static pthread_key_t heap_key;
 #endif
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
 DWORD tlsIndex = TLS_OUT_OF_INDEXES;
 #endif
 
 static ALWAYS_INLINE void setThreadHeap(TCMalloc_ThreadCache* heap)
 {
-    // still do pthread_setspecific when using MSVC fast TLS to
-    // benefit from the delete callback.
+#if USE(PTHREAD_GETSPECIFIC_DIRECT)
+    // Can't have two libraries both doing this in the same process,
+    // so check and make this crash right away.
+    if (pthread_getspecific(heap_key))
+        CRASH();
+#endif
+
+    // Still do pthread_setspecific even if there's an alternate form
+    // of thread-local storage in use, to benefit from the delete callback.
     pthread_setspecific(heap_key, heap);
-#if COMPILER(MSVC)
+
+#if OS(WINDOWS)
     TlsSetValue(tlsIndex, heap);
 #endif
 }
@@ -2698,7 +2806,13 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() {
     if (span) pageheap->RegisterSizeClass(span, size_class_);
   }
   if (span == NULL) {
+#if HAVE(ERRNO_H)
     MESSAGE("allocation failed: %d\n", errno);
+#elif OS(WINDOWS)
+    MESSAGE("allocation failed: %d\n", ::GetLastError());
+#else
+    MESSAGE("allocation failed\n");
+#endif
     lock_.Lock();
     return;
   }
@@ -2721,7 +2835,7 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() {
   char* nptr;
   while ((nptr = ptr + size) <= limit) {
     *tail = ptr;
-    tail = reinterpret_cast<void**>(ptr);
+    tail = reinterpret_cast_ptr<void**>(ptr);
     ptr = nptr;
     num++;
   }
@@ -2949,7 +3063,7 @@ inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetThreadHeap() {
     // __thread is faster, but only when the kernel supports it
   if (KernelSupportsTLS())
     return threadlocal_heap;
-#elif COMPILER(MSVC)
+#elif OS(WINDOWS)
     return static_cast<TCMalloc_ThreadCache*>(TlsGetValue(tlsIndex));
 #else
     return static_cast<TCMalloc_ThreadCache*>(pthread_getspecific(heap_key));
@@ -2983,12 +3097,12 @@ void TCMalloc_ThreadCache::InitTSD() {
 #else
   pthread_key_create(&heap_key, DestroyThreadCache);
 #endif
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
   tlsIndex = TlsAlloc();
 #endif
   tsd_inited = true;
     
-#if !COMPILER(MSVC)
+#if !OS(WINDOWS)
   // We may have used a fake pthread_t for the main thread.  Fix it.
   pthread_t zero;
   memset(&zero, 0, sizeof(zero));
@@ -2999,7 +3113,7 @@ void TCMalloc_ThreadCache::InitTSD() {
   ASSERT(pageheap_lock.IsHeld());
 #endif
   for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) {
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
     if (h->tid_ == 0) {
       h->tid_ = GetCurrentThreadId();
     }
@@ -3017,7 +3131,7 @@ TCMalloc_ThreadCache* TCMalloc_ThreadCache::CreateCacheIfNecessary() {
   {
     SpinLockHolder h(&pageheap_lock);
 
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
     DWORD me;
     if (!tsd_inited) {
       me = 0;
@@ -3038,7 +3152,7 @@ TCMalloc_ThreadCache* TCMalloc_ThreadCache::CreateCacheIfNecessary() {
     // In that case, the heap for this thread has already been created
     // and added to the linked list.  So we search for that first.
     for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) {
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
       if (h->tid_ == me) {
 #else
       if (pthread_equal(h->tid_, me)) {
@@ -3069,7 +3183,7 @@ void TCMalloc_ThreadCache::BecomeIdle() {
   if (heap->in_setspecific_) return;    // Do not disturb the active caller
 
   heap->in_setspecific_ = true;
-  pthread_setspecific(heap_key, NULL);
+  setThreadHeap(NULL);
 #ifdef HAVE_TLS
   // Also update the copy in __thread
   threadlocal_heap = NULL;
@@ -3712,16 +3826,20 @@ template <bool crashOnFailure>
 ALWAYS_INLINE
 #endif
 void* malloc(size_t size) {
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= size)  // If overflow would occur...
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= size)  // If overflow would occur...
         return 0;
-    size += sizeof(AllocAlignmentInteger);
-    void* result = do_malloc(size);
+    void* result = do_malloc(size + Internal::ValidationBufferSize);
     if (!result)
         return 0;
 
-    *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
-    result = static_cast<AllocAlignmentInteger*>(result) + 1;
+    Internal::ValidationHeader* header = static_cast<Internal::ValidationHeader*>(result);
+    header->m_size = size;
+    header->m_type = Internal::AllocTypeMalloc;
+    header->m_prefix = static_cast<unsigned>(Internal::ValidationPrefix);
+    result = header + 1;
+    *Internal::fastMallocValidationSuffix(result) = Internal::ValidationSuffix;
+    fastMallocValidate(result);
 #else
     void* result = do_malloc(size);
 #endif
@@ -3740,13 +3858,13 @@ void free(void* ptr) {
   MallocHook::InvokeDeleteHook(ptr);
 #endif
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     if (!ptr)
         return;
 
-    AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(ptr);
-    if (*header != Internal::AllocTypeMalloc)
-        Internal::fastMallocMatchFailed(ptr);
+    fastMallocValidate(ptr);
+    Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(ptr);
+    memset(ptr, 0xCC, header->m_size);
     do_free(header);
 #else
     do_free(ptr);
@@ -3761,12 +3879,20 @@ ALWAYS_INLINE void* calloc(size_t, size_t);
 
 void* fastCalloc(size_t n, size_t elem_size)
 {
-    return calloc<true>(n, elem_size);
+    void* result = calloc<true>(n, elem_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    fastMallocValidate(result);
+#endif
+    return result;
 }
 
 TryMallocReturnValue tryFastCalloc(size_t n, size_t elem_size)
 {
-    return calloc<false>(n, elem_size);
+    void* result = calloc<false>(n, elem_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    fastMallocValidate(result);
+#endif
+    return result;
 }
 
 template <bool crashOnFailure>
@@ -3779,18 +3905,13 @@ void* calloc(size_t n, size_t elem_size) {
   if (n > 1 && elem_size && (totalBytes / elem_size) != n)
     return 0;
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= totalBytes)  // If overflow would occur...
-        return 0;
-
-    totalBytes += sizeof(AllocAlignmentInteger);
-    void* result = do_malloc(totalBytes);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    void* result = malloc<crashOnFailure>(totalBytes);
     if (!result)
         return 0;
 
     memset(result, 0, totalBytes);
-    *static_cast<AllocAlignmentInteger*>(result) = Internal::AllocTypeMalloc;
-    result = static_cast<AllocAlignmentInteger*>(result) + 1;
+    fastMallocValidate(result);
 #else
     void* result = do_malloc(totalBytes);
     if (result != NULL) {
@@ -3825,12 +3946,26 @@ ALWAYS_INLINE void* realloc(void*, size_t);
 
 void* fastRealloc(void* old_ptr, size_t new_size)
 {
-    return realloc<true>(old_ptr, new_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    fastMallocValidate(old_ptr);
+#endif
+    void* result = realloc<true>(old_ptr, new_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    fastMallocValidate(result);
+#endif
+    return result;
 }
 
 TryMallocReturnValue tryFastRealloc(void* old_ptr, size_t new_size)
 {
-    return realloc<false>(old_ptr, new_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    fastMallocValidate(old_ptr);
+#endif
+    void* result = realloc<false>(old_ptr, new_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    fastMallocValidate(result);
+#endif
+    return result;
 }
 
 template <bool crashOnFailure>
@@ -3838,8 +3973,8 @@ ALWAYS_INLINE
 #endif
 void* realloc(void* old_ptr, size_t new_size) {
   if (old_ptr == NULL) {
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    void* result = malloc(new_size);
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    void* result = malloc<crashOnFailure>(new_size);
 #else
     void* result = do_malloc(new_size);
 #ifndef WTF_CHANGES
@@ -3856,14 +3991,14 @@ void* realloc(void* old_ptr, size_t new_size) {
     return NULL;
   }
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    if (std::numeric_limits<size_t>::max() - sizeof(AllocAlignmentInteger) <= new_size)  // If overflow would occur...
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= new_size)  // If overflow would occur...
         return 0;
-    new_size += sizeof(AllocAlignmentInteger);
-    AllocAlignmentInteger* header = Internal::fastMallocMatchValidationValue(old_ptr);
-    if (*header != Internal::AllocTypeMalloc)
-        Internal::fastMallocMatchFailed(old_ptr);
+    Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(old_ptr);
+    fastMallocValidate(old_ptr);
     old_ptr = header;
+    header->m_size = new_size;
+    new_size += Internal::ValidationBufferSize;
 #endif
 
   // Get the size of the old entry
@@ -3902,13 +4037,15 @@ void* realloc(void* old_ptr, size_t new_size) {
     // that we already know the sizeclass of old_ptr.  The benefit
     // would be small, so don't bother.
     do_free(old_ptr);
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    new_ptr = static_cast<AllocAlignmentInteger*>(new_ptr) + 1;
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    new_ptr = static_cast<Internal::ValidationHeader*>(new_ptr) + 1;
+    *Internal::fastMallocValidationSuffix(new_ptr) = Internal::ValidationSuffix;
 #endif
     return new_ptr;
   } else {
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-    old_ptr = static_cast<AllocAlignmentInteger*>(old_ptr) + 1; // Set old_ptr back to the user pointer.
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    old_ptr = static_cast<Internal::ValidationHeader*>(old_ptr) + 1; // Set old_ptr back to the user pointer.
+    *Internal::fastMallocValidationSuffix(old_ptr) = Internal::ValidationSuffix;
 #endif
     return old_ptr;
   }
@@ -4169,6 +4306,9 @@ FastMallocStatistics fastMallocStatistics()
 
 size_t fastMallocSize(const void* ptr)
 {
+#if ENABLE(WTF_MALLOC_VALIDATION)
+    return Internal::fastMallocValidationHeader(const_cast<void*>(ptr))->m_size;
+#else
     const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
     Span* span = pageheap->GetDescriptorEnsureSafe(p);
 
@@ -4184,6 +4324,7 @@ size_t fastMallocSize(const void* ptr)
         return ByteSizeForClass(cl);
 
     return span->length << kPageShift;
+#endif
 }
 
 #if OS(DARWIN)
@@ -4229,12 +4370,15 @@ public:
             return 1;
 
         Span* span = m_reader(reinterpret_cast<Span*>(ptr));
+        if (!span)
+            return 1;
+
         if (span->free) {
             void* ptr = reinterpret_cast<void*>(span->start << kPageShift);
             m_freeObjectFinder.visit(ptr);
         } else if (span->sizeclass) {
             // Walk the free list of the small-object span, keeping track of each object seen
-            for (void* nextObject = span->objects; nextObject; nextObject = *m_reader(reinterpret_cast<void**>(nextObject)))
+            for (void* nextObject = span->objects; nextObject; nextObject = m_reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject)))
                 m_freeObjectFinder.visit(nextObject);
         }
         return span->length;
@@ -4318,7 +4462,7 @@ public:
             return 1;
 
         Span* span = m_reader(reinterpret_cast<Span*>(ptr));
-        if (!span->start)
+        if (!span || !span->start)
             return 1;
 
         if (m_seenPointers.contains(ptr))
@@ -4468,8 +4612,10 @@ void* FastMallocZone::zoneRealloc(malloc_zone_t*, void*, size_t)
 extern "C" {
 malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print,
     &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics
+
     , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher.
     , 0, 0, 0, 0 // These members will not be used unless the zone advertises itself as version seven or higher.
+
     };
 }
 
index 1ccd6a64e05d05babac01ab094314e1f553cc74a..37cf0868ec0c5752bb96b78009ca7e7facd7548e 100644 (file)
@@ -103,9 +103,25 @@ namespace WTF {
             AllocTypeNew,                   // Encompasses global operator new.
             AllocTypeNewArray               // Encompasses global operator new[].
         };
+
+        enum {
+            ValidationPrefix = 0xf00df00d,
+            ValidationSuffix = 0x0badf00d
+        };
+
+        typedef unsigned ValidationTag;
+
+        struct ValidationHeader {
+            AllocType m_type;
+            unsigned m_size;
+            ValidationTag m_prefix;
+            unsigned m_alignment;
+        };
+
+        static const int ValidationBufferSize = sizeof(ValidationHeader) + sizeof(ValidationTag);
     }
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
 
     // Malloc validation is a scheme whereby a tag is attached to an
     // allocation which identifies how it was originally allocated.
@@ -120,30 +136,36 @@ namespace WTF {
     // is implemented.
 
     namespace Internal {
+    
+        // Handle a detected alloc/free mismatch. By default this calls CRASH().
+        void fastMallocMatchFailed(void* p);
 
-        // Return the AllocType tag associated with the allocated block p.
-        inline AllocType fastMallocMatchValidationType(const void* p)
+        inline ValidationHeader* fastMallocValidationHeader(void* p)
         {
-            const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1;
-            return static_cast<AllocType>(*type);
+            return reinterpret_cast<ValidationHeader*>(static_cast<char*>(p) - sizeof(ValidationHeader));
         }
 
-        // Return the address of the AllocType tag associated with the allocated block p.
-        inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p)
+        inline ValidationTag* fastMallocValidationSuffix(void* p)
+        {
+            ValidationHeader* header = fastMallocValidationHeader(p);
+            if (header->m_prefix != static_cast<unsigned>(ValidationPrefix))
+                fastMallocMatchFailed(p);
+            
+            return reinterpret_cast<ValidationTag*>(static_cast<char*>(p) + header->m_size);
+        }
+
+        // Return the AllocType tag associated with the allocated block p.
+        inline AllocType fastMallocMatchValidationType(void* p)
         {
-            return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger));
+            return fastMallocValidationHeader(p)->m_type;
         }
 
         // Set the AllocType tag to be associaged with the allocated block p.
         inline void setFastMallocMatchValidationType(void* p, AllocType allocType)
         {
-            AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1;
-            *type = static_cast<AllocAlignmentInteger>(allocType);
+            fastMallocValidationHeader(p)->m_type = allocType;
         }
 
-        // Handle a detected alloc/free mismatch. By default this calls CRASH().
-        void fastMallocMatchFailed(void* p);
-
     } // namespace Internal
 
     // This is a higher level function which is used by FastMalloc-using code.
@@ -156,16 +178,34 @@ namespace WTF {
     }
 
     // This is a higher level function which is used by FastMalloc-using code.
-    inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType)
+    inline void fastMallocMatchValidateFree(void* p, Internal::AllocType)
     {
         if (!p)
             return;
+    
+        Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p);
+        if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix))
+            Internal::fastMallocMatchFailed(p);
 
-        if (Internal::fastMallocMatchValidationType(p) != allocType)
+        if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix)
             Internal::fastMallocMatchFailed(p);
+
         Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc);  // Set it to this so that fastFree thinks it's OK.
     }
 
+    inline void fastMallocValidate(void* p)
+    {
+        if (!p)
+            return;
+        
+        Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p);
+        if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix))
+            Internal::fastMallocMatchFailed(p);
+        
+        if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix)
+            Internal::fastMallocMatchFailed(p);
+    }
+
 #else
 
     inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType)
@@ -207,7 +247,7 @@ using WTF::fastMallocAllow;
 #define WTF_PRIVATE_INLINE inline
 #endif
 
-#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
+#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC && !PLATFORM(BREWMP))
 
 // The nothrow functions here are actually not all that helpful, because fastMalloc will
 // call CRASH() rather than returning 0, and returning 0 is what nothrow is all about.
diff --git a/wtf/FixedArray.h b/wtf/FixedArray.h
new file mode 100644 (file)
index 0000000..c67d18c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 FixedArray_h
+#define FixedArray_h
+
+#include <wtf/Assertions.h>
+
+namespace WTF {
+
+template <typename T, size_t Size> class FixedArray {
+public:
+    T& operator[](size_t i)
+    {
+        ASSERT(i < Size);
+        return m_data[i];
+    }
+
+    const T& operator[](size_t i) const
+    {
+        ASSERT(i < Size);
+        return m_data[i];
+    }
+
+    T* data() { return m_data; }
+    size_t size() const { return Size; }
+
+private:
+    T m_data[Size];
+};
+
+} // namespace WTF
+
+using WTF::FixedArray;
+
+#endif // FixedArray_h
index 448de7d5a5ebacaafa64ff2dfac9b46ff422d06d..28be168eb309f02feba06b1e90a50cd49ff53b54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2006, 2009, 2011 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
@@ -27,18 +27,38 @@ namespace WTF {
     template<typename T> class ListRefPtr;
     template<typename T> class OwnArrayPtr;
     template<typename T> class OwnPtr;
+    template<typename T> class PassOwnArrayPtr;
     template<typename T> class PassOwnPtr;
     template<typename T> class PassRefPtr;
     template<typename T> class RefPtr;
     template<typename T, size_t inlineCapacity> class Vector;
+
+    class AtomicString;
+    class AtomicStringImpl;
+    class CString;
+    class Decoder;
+    class Encoder;
+    class String;
+    class StringBuffer;
+    class StringImpl;
 }
 
 using WTF::ListRefPtr;
 using WTF::OwnArrayPtr;
 using WTF::OwnPtr;
+using WTF::PassOwnArrayPtr;
 using WTF::PassOwnPtr;
 using WTF::PassRefPtr;
 using WTF::RefPtr;
 using WTF::Vector;
 
+using WTF::AtomicString;
+using WTF::AtomicStringImpl;
+using WTF::CString;
+using WTF::Encoder;
+using WTF::Decoder;
+using WTF::String;
+using WTF::StringBuffer;
+using WTF::StringImpl;
+
 #endif // WTF_Forward_h
index 4ed75c517906fcc2efc97ed2fdd16fb227a999cb..b97d8c8fd0f97a21bbeabeb5114beb752b74979f 100644 (file)
 #define WTF_HashCountedSet_h
 
 #include "Assertions.h"
-#include "FastAllocBase.h"
 #include "HashMap.h"
 #include "Vector.h"
 
 namespace WTF {
 
     template<typename Value, typename HashFunctions = typename DefaultHash<Value>::Hash,
-        typename Traits = HashTraits<Value> > class HashCountedSet : public FastAllocBase {
+        typename Traits = HashTraits<Value> > class HashCountedSet {
+        WTF_MAKE_FAST_ALLOCATED;
     private:
         typedef HashMap<Value, unsigned, HashFunctions, Traits> ImplType;
     public:
index 682c83b4d3ac7ac96840ec17dd97e1ad7eeadab3..6afa2fa57e70ad0320850f3733dcd799714b0083 100644 (file)
@@ -40,6 +40,7 @@ namespace WTF {
         typedef HashTableConstKeysIterator<HashTableType, KeyType, MappedType> Keys;
         typedef HashTableConstValuesIterator<HashTableType, KeyType, MappedType> Values;
 
+        HashTableConstIteratorAdapter() {}
         HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
 
         const ValueType* get() const { return (const ValueType*)m_impl.get(); }
@@ -62,6 +63,7 @@ namespace WTF {
         typedef HashTableKeysIterator<HashTableType, KeyType, MappedType> Keys;
         typedef HashTableValuesIterator<HashTableType, KeyType, MappedType> Values;
 
+        HashTableIteratorAdapter() {}
         HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
 
         ValueType* get() const { return (ValueType*)m_impl.get(); }
index 09094d1ad50de8f679a05515671035eeb434bc27..7731546654d5832fffe026b3a92995552a949976 100644 (file)
@@ -29,7 +29,8 @@ namespace WTF {
 
     template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash,
         typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> >
-    class HashMap : public FastAllocBase {
+    class HashMap {
+        WTF_MAKE_FAST_ALLOCATED;
     private:
         typedef KeyTraitsArg KeyTraits;
         typedef MappedTraitsArg MappedTraits;
index 442949081f20d640c56639ca54876ab170899840..82245f3ecdd8845dbae28e659f5583da95159b83 100644 (file)
@@ -35,7 +35,8 @@ namespace WTF {
     template<typename T> struct IdentityExtractor;
 
     template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash,
-        typename TraitsArg = HashTraits<ValueArg> > class HashSet : public FastAllocBase {
+        typename TraitsArg = HashTraits<ValueArg> > class HashSet {
+        WTF_MAKE_FAST_ALLOCATED;
     private:
         typedef HashArg HashFunctions;
         typedef TraitsArg ValueTraits;
@@ -48,7 +49,7 @@ namespace WTF {
             HashFunctions, ValueTraits, ValueTraits> HashTableType;
 
     public:
-        typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
+        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> iterator;
         typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
 
         void swap(HashSet&);
@@ -57,13 +58,10 @@ namespace WTF {
         int capacity() const;
         bool isEmpty() const;
 
-        iterator begin();
-        iterator end();
-        const_iterator begin() const;
-        const_iterator end() const;
+        iterator begin() const;
+        iterator end() const;
 
-        iterator find(const ValueType&);
-        const_iterator find(const ValueType&) const;
+        iterator find(const ValueType&) const;
         bool contains(const ValueType&) const;
 
         // An alternate version of find() that finds the object by hashing and comparing
@@ -71,8 +69,7 @@ namespace WTF {
         // must have the following function members:
         //   static unsigned hash(const T&);
         //   static bool equal(const ValueType&, const T&);
-        template<typename T, typename HashTranslator> iterator find(const T&);
-        template<typename T, typename HashTranslator> const_iterator find(const T&) const;
+        template<typename T, typename HashTranslator> iterator find(const T&) const;
         template<typename T, typename HashTranslator> bool contains(const T&) const;
 
         // The return value is a pair of an interator to the new value's location, 
@@ -137,37 +134,19 @@ namespace WTF {
     }
 
     template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::begin()
+    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::begin() const
     {
         return m_impl.begin(); 
     }
 
     template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::end()
+    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::end() const
     {
         return m_impl.end(); 
     }
 
     template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::const_iterator HashSet<T, U, V>::begin() const
-    {
-        return m_impl.begin(); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::const_iterator HashSet<T, U, V>::end() const
-    {
-        return m_impl.end(); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::find(const ValueType& value)
-    {
-        return m_impl.find(value); 
-    }
-
-    template<typename T, typename U, typename V>
-    inline typename HashSet<T, U, V>::const_iterator HashSet<T, U, V>::find(const ValueType& value) const
+    inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::find(const ValueType& value) const
     {
         return m_impl.find(value); 
     }
@@ -181,15 +160,6 @@ namespace WTF {
     template<typename Value, typename HashFunctions, typename Traits>
     template<typename T, typename HashTranslator>
     typename HashSet<Value, HashFunctions, Traits>::iterator
-    inline HashSet<Value, HashFunctions, Traits>::find(const T& value)
-    {
-        typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
-        return m_impl.template find<T, Adapter>(value);
-    }
-
-    template<typename Value, typename HashFunctions, typename Traits>
-    template<typename T, typename HashTranslator>
-    typename HashSet<Value, HashFunctions, Traits>::const_iterator
     inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const
     {
         typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
@@ -205,14 +175,14 @@ namespace WTF {
     }
 
     template<typename T, typename U, typename V>
-    pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType& value)
+    inline pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType& value)
     {
         return m_impl.add(value);
     }
 
     template<typename Value, typename HashFunctions, typename Traits>
     template<typename T, typename HashTranslator>
-    pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
+    inline pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool>
     HashSet<Value, HashFunctions, Traits>::add(const T& value)
     {
         typedef HashSetTranslatorAdapter<ValueType, ValueTraits, T, HashTranslator> Adapter;
index ceb89636368ea20ef522914b4c3d0a910205f58d..79e8b3f3559ac387dce811905746d040df9aaa07 100644 (file)
@@ -126,7 +126,7 @@ namespace WTF {
     public:
         HashTableConstIterator()
         {
-            addIterator(0, this);
+            addIterator(static_cast<const HashTableType*>(0), this);
         }
 
         // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0
@@ -259,19 +259,21 @@ namespace WTF {
 
     using std::swap;
 
-#if !COMPILER(MSVC)
-    // Visual C++ has a swap for pairs defined.
+    // Work around MSVC's standard library, whose swap for pairs does not swap by component.
+    template<typename T> inline void hashTableSwap(T& a, T& b)
+    {
+        swap(a, b);
+    }
 
-    // swap pairs by component, in case of pair members that specialize swap
-    template<typename T, typename U> inline void swap(pair<T, U>& a, pair<T, U>& b)
+    // Swap pairs by component, in case of pair members that specialize swap.
+    template<typename T, typename U> inline void hashTableSwap(pair<T, U>& a, pair<T, U>& b)
     {
         swap(a.first, b.first);
         swap(a.second, b.second);
     }
-#endif
 
     template<typename T, bool useSwap> struct Mover;
-    template<typename T> struct Mover<T, true> { static void move(T& from, T& to) { swap(from, to); } };
+    template<typename T> struct Mover<T, true> { static void move(T& from, T& to) { hashTableSwap(from, to); } };
     template<typename T> struct Mover<T, false> { static void move(T& from, T& to) { to = from; } };
 
     template<typename Key, typename Value, typename HashFunctions> class IdentityHashTranslator {
@@ -333,6 +335,7 @@ namespace WTF {
         void remove(const KeyType&);
         void remove(iterator);
         void removeWithoutEntryConsistencyCheck(iterator);
+        void removeWithoutEntryConsistencyCheck(const_iterator);
         void clear();
 
         static bool isEmptyBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::emptyValue(); }
@@ -853,6 +856,15 @@ namespace WTF {
         removeAndInvalidateWithoutEntryConsistencyCheck(const_cast<ValueType*>(it.m_iterator.m_position));
     }
 
+    template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
+    inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeWithoutEntryConsistencyCheck(const_iterator it)
+    {
+        if (it == end())
+            return;
+
+        removeAndInvalidateWithoutEntryConsistencyCheck(const_cast<ValueType*>(it.m_position));
+    }
+
     template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits>
     inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(const KeyType& key)
     {
@@ -1108,6 +1120,7 @@ namespace WTF {
     // iterator adapters
 
     template<typename HashTableType, typename ValueType> struct HashTableConstIteratorAdapter {
+        HashTableConstIteratorAdapter() {}
         HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {}
 
         const ValueType* get() const { return (const ValueType*)m_impl.get(); }
@@ -1121,6 +1134,7 @@ namespace WTF {
     };
 
     template<typename HashTableType, typename ValueType> struct HashTableIteratorAdapter {
+        HashTableIteratorAdapter() {}
         HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {}
 
         ValueType* get() const { return (ValueType*)m_impl.get(); }
index c8d40f7d54e0f5d0ff82b082c6a607998ba26aa6..fba5afe687e0057bde4db5c0790426c5cc63c1d1 100644 (file)
@@ -81,12 +81,14 @@ namespace WTF {
         static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); }
     };
 
-    template<typename P> struct HashTraits<RefPtr<P> > : GenericHashTraits<RefPtr<P> > {
+    template<typename T> struct SimpleClassHashTraits : GenericHashTraits<T> {
         static const bool emptyValueIsZero = true;
-        static void constructDeletedValue(RefPtr<P>& slot) { new (&slot) RefPtr<P>(HashTableDeletedValue); }
-        static bool isDeletedValue(const RefPtr<P>& value) { return value.isHashTableDeletedValue(); }
+        static void constructDeletedValue(T& slot) { new (&slot) T(HashTableDeletedValue); }
+        static bool isDeletedValue(const T& value) { return value.isHashTableDeletedValue(); }
     };
 
+    template<typename P> struct HashTraits<RefPtr<P> > : SimpleClassHashTraits<RefPtr<P> > { };
+
     // special traits for pairs, helpful for their use in HashMap implementation
 
     template<typename FirstTraitsArg, typename SecondTraitsArg>
diff --git a/wtf/HexNumber.h b/wtf/HexNumber.h
new file mode 100644 (file)
index 0000000..8fd6032
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 Research In Motion Limited. 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef HexNumber_h
+#define HexNumber_h
+
+#include <wtf/text/StringConcatenate.h>
+
+namespace WTF {
+
+enum HexConversionMode {
+    Lowercase,
+    Uppercase
+};
+
+namespace Internal {
+
+static const char* hexDigitsForMode(HexConversionMode mode)
+{
+    static const char lowerHexDigits[17] = "0123456789abcdef";
+    static const char upperHexDigits[17] = "0123456789ABCDEF";
+    return mode == Lowercase ? lowerHexDigits : upperHexDigits;
+}
+
+}; // namespace Internal
+
+template<typename T>
+inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase)
+{
+    const char* hexDigits = Internal::hexDigitsForMode(mode);
+    destination.append(hexDigits[byte >> 4]);
+    destination.append(hexDigits[byte & 0xF]);
+}
+
+template<typename T>
+inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase)
+{
+    const char* hexDigits = Internal::hexDigitsForMode(mode);
+    if (byte >= 0x10)
+        destination[index++] = hexDigits[byte >> 4];
+    destination[index++] = hexDigits[byte & 0xF];
+}
+
+template<typename T>
+inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase)
+{
+    const char* hexDigits = Internal::hexDigitsForMode(mode);
+    *destination++ = hexDigits[byte >> 4];
+    *destination++ = hexDigits[byte & 0xF];
+}
+
+template<typename T>
+inline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase)
+{
+    const char* hexDigits = Internal::hexDigitsForMode(mode);
+    Vector<UChar, 8> result;
+    do {
+        result.prepend(hexDigits[number % 16]);
+        number >>= 4;
+    } while (number > 0);
+
+    destination.append(result.data(), result.size());
+}
+
+// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion.
+template<typename T>
+inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase)
+{
+    ASSERT(desiredDigits);
+
+    const char* hexDigits = Internal::hexDigitsForMode(mode);
+    Vector<UChar, 8> result;
+    do {
+        result.prepend(hexDigits[number % 16]);
+        number >>= 4;
+    } while (result.size() < desiredDigits);
+
+    ASSERT(result.size() == desiredDigits);
+    destination.append(result.data(), result.size());
+}
+
+} // namespace WTF
+
+using WTF::appendByteAsHex;
+using WTF::appendUnsignedAsHex;
+using WTF::appendUnsignedAsHexFixedSize;
+using WTF::placeByteAsHex;
+using WTF::placeByteAsHexCompressIfPossible;
+using WTF::Lowercase;
+
+#endif // HexNumber_h
index 09355ade40a3ade2c5a70431f9b6205da8c42011..25b73c188a3f8182e26ea2f216c0dfe56a4e07b2 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -24,6 +25,8 @@
 #include "Assertions.h"
 #include "HashSet.h"
 #include "OwnPtr.h"
+#include "PassOwnPtr.h"
+#include "StdLibExtras.h"
 
 namespace WTF {
 
@@ -51,7 +54,8 @@ namespace WTF {
     template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator;
     template<typename ValueArg, size_t inlineCapacity, typename HashArg> struct ListHashSetNodeHashFunctions;
 
-    template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet : public FastAllocBase {
+    template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet {
+        WTF_MAKE_FAST_ALLOCATED;
     private:
         typedef ListHashSetNode<ValueArg, inlineCapacity> Node;
         typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator;
@@ -88,10 +92,24 @@ namespace WTF {
         const_iterator begin() const;
         const_iterator end() const;
 
+        ValueType& first();
+        const ValueType& first() const;
+
+        ValueType& last();
+        const ValueType& last() const;
+        void removeLast();
+
         iterator find(const ValueType&);
         const_iterator find(const ValueType&) const;
         bool contains(const ValueType&) const;
 
+        // An alternate version of find() that finds the object by hashing and comparing
+        // with some other type, to avoid the cost of type conversion.
+        // The HashTranslator interface is defined in HashSet.
+        template<typename T, typename HashTranslator> iterator find(const T&);
+        template<typename T, typename HashTranslator> const_iterator find(const T&) const;
+        template<typename T, typename HashTranslator> bool contains(const T&) const;
+
         // the return value is a pair of an iterator to the new value's location, 
         // and a bool that is true if an new entry was added
         pair<iterator, bool> add(const ValueType&);
@@ -171,7 +189,7 @@ namespace WTF {
         }
 
     private:
-        Node* pool() { return reinterpret_cast<Node*>(m_pool.pool); }
+        Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); }
         Node* pastPool() { return pool() + m_poolSize; }
 
         bool inPool(Node* node)
@@ -359,7 +377,7 @@ namespace WTF {
     inline ListHashSet<T, inlineCapacity, U>::ListHashSet()
         : m_head(0)
         , m_tail(0)
-        , m_allocator(new NodeAllocator)
+        , m_allocator(adoptPtr(new NodeAllocator))
     {
     }
 
@@ -367,7 +385,7 @@ namespace WTF {
     inline ListHashSet<T, inlineCapacity, U>::ListHashSet(const ListHashSet& other)
         : m_head(0)
         , m_tail(0)
-        , m_allocator(new NodeAllocator)
+        , m_allocator(adoptPtr(new NodeAllocator))
     {
         const_iterator end = other.end();
         for (const_iterator it = other.begin(); it != end; ++it)
@@ -439,6 +457,42 @@ namespace WTF {
         return makeConstIterator(0); 
     }
 
+    template<typename T, size_t inlineCapacity, typename U>
+    inline T& ListHashSet<T, inlineCapacity, U>::first()
+    {
+        ASSERT(!isEmpty());
+        return m_head->m_value;
+    }
+
+    template<typename T, size_t inlineCapacity, typename U>
+    inline const T& ListHashSet<T, inlineCapacity, U>::first() const
+    {
+        ASSERT(!isEmpty());
+        return m_head->m_value;
+    }
+
+    template<typename T, size_t inlineCapacity, typename U>
+    inline T& ListHashSet<T, inlineCapacity, U>::last()
+    {
+        ASSERT(!isEmpty());
+        return m_tail->m_value;
+    }
+
+    template<typename T, size_t inlineCapacity, typename U>
+    inline const T& ListHashSet<T, inlineCapacity, U>::last() const
+    {
+        ASSERT(!isEmpty());
+        return m_tail->m_value;
+    }
+
+    template<typename T, size_t inlineCapacity, typename U>
+    inline void ListHashSet<T, inlineCapacity, U>::removeLast()
+    {
+        ASSERT(!isEmpty());
+        m_impl.remove(m_tail);
+        unlinkAndDelete(m_tail);
+    }
+
     template<typename T, size_t inlineCapacity, typename U>
     inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value)
     {
@@ -459,6 +513,45 @@ namespace WTF {
         return makeConstIterator(*it);
     }
 
+    template<typename ValueType, size_t inlineCapacity, typename T, typename Translator>
+    struct ListHashSetTranslatorAdapter {
+    private:
+        typedef ListHashSetNode<ValueType, inlineCapacity> Node;
+    public:
+        static unsigned hash(const T& key) { return Translator::hash(key); }
+        static bool equal(Node* const& a, const T& b) { return Translator::equal(a->m_value, b); }
+    };
+
+    template<typename ValueType, size_t inlineCapacity, typename U>
+    template<typename T, typename HashTranslator>
+    inline typename ListHashSet<ValueType, inlineCapacity, U>::iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value)
+    {
+        typedef ListHashSetTranslatorAdapter<ValueType, inlineCapacity, T, HashTranslator> Adapter;
+        ImplTypeConstIterator it = m_impl.template find<T, Adapter>(value);
+        if (it == m_impl.end())
+            return end();
+        return makeIterator(*it);
+    }
+
+    template<typename ValueType, size_t inlineCapacity, typename U>
+    template<typename T, typename HashTranslator>
+    inline typename ListHashSet<ValueType, inlineCapacity, U>::const_iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) const
+    {
+        typedef ListHashSetTranslatorAdapter<ValueType, inlineCapacity, T, HashTranslator> Adapter;
+        ImplTypeConstIterator it = m_impl.template find<T, Adapter>(value);
+        if (it == m_impl.end())
+            return end();
+        return makeConstIterator(*it);
+    }
+
+    template<typename ValueType, size_t inlineCapacity, typename U>
+    template<typename T, typename HashTranslator>
+    inline bool ListHashSet<ValueType, inlineCapacity, U>::contains(const T& value) const
+    {
+        typedef ListHashSetTranslatorAdapter<ValueType, inlineCapacity, T, HashTranslator> Adapter;
+        return m_impl.template contains<T, Adapter>(value);
+    }
+
     template<typename T, size_t inlineCapacity, typename U>
     inline bool ListHashSet<T, inlineCapacity, U>::contains(const ValueType& value) const
     {
index 41813d3f9f49a9c892c02992b0393b4333c04057..c465b99ea4c1a33d3179cdc964cca01a0607f5a8 100644 (file)
@@ -32,7 +32,8 @@
 
 namespace WTF {
 
-template <typename T> class Locker : public Noncopyable {
+template <typename T> class Locker {
+    WTF_MAKE_NONCOPYABLE(Locker);
 public:
     Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); }
     ~Locker() { m_lockable.unlock(); }
index cd1837ae16481928853087056c7db87b9c8a5a5d..07bbadd9f5ea3dbf1718a990229498420c902b27 100644 (file)
@@ -54,6 +54,7 @@
 #include "StringExtras.h"
 #include "text/CString.h"
 #endif
+#include <wtf/StdLibExtras.h>
 
 namespace WTF {
 
@@ -67,14 +68,15 @@ static void expectMD5(CString input, CString expected)
 {
     MD5 md5;
     md5.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length());
-    Vector<uint8_t, 16> digest = md5.checksum();
+    Vector<uint8_t, 16> digest;
+    md5.checksum(digest);
     char* buf = 0;
     CString actual = CString::newUninitialized(32, buf);
     for (size_t i = 0; i < 16; i++) {
         snprintf(buf, 3, "%02x", digest.at(i));
         buf += 2;
     }
-    ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%d] actual:%s expected:%s", input.data(), input.length(), actual.data(), expected.data());
+    ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%lu] actual:%s expected:%s", input.data(), static_cast<unsigned long>(input.length()), actual.data(), expected.data());
 }
 
 static void testMD5()
@@ -102,7 +104,7 @@ static void reverseBytes(uint8_t* buf, unsigned longs)
     do {
         uint32_t t = static_cast<uint32_t>(buf[3] << 8 | buf[2]) << 16 | buf[1] << 8 | buf[0];
         ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(buf) % sizeof(t)), "alignment error of buf");
-        *reinterpret_cast<uint32_t *>(buf) = t;
+        *reinterpret_cast_ptr<uint32_t *>(buf) = t;
         buf += 4;
     } while (--longs);
 }
@@ -201,6 +203,7 @@ static void MD5Transform(uint32_t buf[4], const uint32_t in[16])
 
 MD5::MD5()
 {
+    // FIXME: Move unit tests somewhere outside the constructor. See bug 55853.
     testMD5();
     m_buf[0] = 0x67452301;
     m_buf[1] = 0xefcdab89;
@@ -237,7 +240,7 @@ void MD5::addBytes(const uint8_t* input, size_t length)
         }
         memcpy(p, buf, t);
         reverseBytes(m_in, 16);
-        MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); // m_in is 4-byte aligned.
+        MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned.
         buf += t;
         length -= t;
     }
@@ -247,7 +250,7 @@ void MD5::addBytes(const uint8_t* input, size_t length)
     while (length >= 64) {
         memcpy(m_in, buf, 64);
         reverseBytes(m_in, 16);
-        MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in)); // m_in is 4-byte aligned.
+        MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned.
         buf += 64;
         length -= 64;
     }
@@ -256,7 +259,7 @@ void MD5::addBytes(const uint8_t* input, size_t length)
     memcpy(m_in, buf, length);
 }
 
-Vector<uint8_t, 16> MD5::checksum()
+void MD5::checksum(Vector<uint8_t, 16>& digest)
 {
     // Compute number of bytes mod 64
     unsigned count = (m_bits[0] >> 3) & 0x3F;
@@ -274,7 +277,7 @@ Vector<uint8_t, 16> MD5::checksum()
         // Two lots of padding:  Pad the first block to 64 bytes
         memset(p, 0, count);
         reverseBytes(m_in, 16);
-        MD5Transform(m_buf, reinterpret_cast<uint32_t *>(m_in)); // m_in is 4-byte aligned.
+        MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t *>(m_in)); // m_in is 4-byte aligned.
 
         // Now fill the next block with 56 bytes
         memset(m_in, 0, 56);
@@ -286,19 +289,21 @@ Vector<uint8_t, 16> MD5::checksum()
 
     // Append length in bits and transform
     // m_in is 4-byte aligned.
-    (reinterpret_cast<uint32_t*>(m_in))[14] = m_bits[0];
-    (reinterpret_cast<uint32_t*>(m_in))[15] = m_bits[1];
+    (reinterpret_cast_ptr<uint32_t*>(m_in))[14] = m_bits[0];
+    (reinterpret_cast_ptr<uint32_t*>(m_in))[15] = m_bits[1];
 
-    MD5Transform(m_buf, reinterpret_cast<uint32_t*>(m_in));
+    MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in));
     reverseBytes(reinterpret_cast<uint8_t*>(m_buf), 4);
-    Vector<uint8_t, 16> digest;
+
+    // Now, m_buf contains checksum result.
+    if (!digest.isEmpty())
+        digest.clear();
     digest.append(reinterpret_cast<uint8_t*>(m_buf), 16);
 
     // In case it's sensitive
     memset(m_buf, 0, sizeof(m_buf));
     memset(m_bits, 0, sizeof(m_bits));
     memset(m_in, 0, sizeof(m_in));
-    return digest;
 }
 
 } // namespace WTF
index 8ebfc45d66e2318f5dba7856c524ec9d7bad63a4..3caa810baa40a62831488f56d108143bb33f0503 100644 (file)
--- a/wtf/MD5.h
+++ b/wtf/MD5.h
@@ -46,7 +46,7 @@ public:
     void addBytes(const uint8_t* input, size_t length);
 
     // checksum has a side effect of resetting the state of the object.
-    Vector<uint8_t, 16> checksum();
+    void checksum(Vector<uint8_t, 16>&);
 
 private:
     uint32_t m_buf[4];
index 1a0682bb6b60c267b40319c3aa6e40cbdb86579d..3229e5b06f315b0c2ec5b4cc860984bca930560a 100644 (file)
@@ -34,6 +34,8 @@
 #include "StdLibExtras.h"
 #include "Threading.h"
 
+#include <wtf/iphone/WebCoreThread.h>
+
 #if PLATFORM(CHROMIUM)
 #error Chromium uses a different main thread implementation
 #endif
@@ -149,13 +151,14 @@ void dispatchFunctionsFromMainThread()
             MutexLocker locker(mainThreadFunctionQueueMutex());
             if (!functionQueue().size())
                 break;
-            invocation = functionQueue().first();
-            functionQueue().removeFirst();
+            invocation = functionQueue().takeFirst();
         }
 
         invocation.function(invocation.context);
-        if (invocation.syncFlag)
+        if (invocation.syncFlag) {
+            MutexLocker locker(mainThreadFunctionQueueMutex());
             invocation.syncFlag->signal();
+        }
 
         // If we are running accumulated functions for too long so UI may become unresponsive, we need to
         // yield so the user input can be processed. Otherwise user may not be able to even close the window.
@@ -219,7 +222,7 @@ void cancelCallOnMainThread(MainThreadFunction* function, void* context)
 
 void setMainThreadCallbacksPaused(bool paused)
 {
-    ASSERT(isMainThread());
+    ASSERT((isMainThread() || pthread_main_np()) && WebCoreWebThreadIsLockedOrDisabled());
 
     if (callbacksPaused == paused)
         return;
@@ -230,7 +233,7 @@ void setMainThreadCallbacksPaused(bool paused)
         scheduleDispatchFunctionsOnMainThread();
 }
 
-#if !PLATFORM(MAC) && !PLATFORM(QT)
+#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(BREWMP)
 bool isMainThread()
 {
     return currentThread() == mainThreadIdentifier;
index 62df1455005020962210c62aca4193646326d611..4332e40b852c5743afa9eecaf8a2417d3928b779 100644 (file)
@@ -47,7 +47,6 @@ public:
     {
         void* output;
         kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output));
-        ASSERT(!err);
         if (err)
             output = 0;
         return output;
@@ -58,6 +57,15 @@ public:
     {
         return static_cast<T*>((*this)(reinterpret_cast<vm_address_t>(address), size));
     }
+
+    template <typename T>
+    T* nextEntryInLinkedList(T** address) const
+    {
+        T** output = (*this)(address);
+        if (!output)
+            return 0;
+        return *output;
+    }
 };
 
 } // namespace WTF
index 1f77b61364459a94cf509840a6548c4560c62eda..54983161103d63462604f63fd2569345c97c4850 100644 (file)
 #ifndef WTF_MathExtras_h
 #define WTF_MathExtras_h
 
+#include <algorithm>
 #include <cmath>
 #include <float.h>
+#include <limits>
 #include <stdlib.h>
 
 #if OS(SOLARIS)
@@ -54,6 +56,14 @@ const double piDouble = M_PI;
 const float piFloat = static_cast<float>(M_PI);
 #endif
 
+#ifndef M_PI_2
+const double piOverTwoDouble = 1.57079632679489661923;
+const float piOverTwoFloat = 1.57079632679489661923f;
+#else
+const double piOverTwoDouble = M_PI_2;
+const float piOverTwoFloat = static_cast<float>(M_PI_2);
+#endif
+
 #ifndef M_PI_4
 const double piOverFourDouble = 0.785398163397448309616;
 const float piOverFourFloat = 0.785398163397448309616f;
@@ -80,7 +90,7 @@ inline bool isfinite(double x) { return finite(x) && !isnand(x); }
 inline bool isinf(double x) { return !finite(x) && !isnand(x); }
 #endif
 #ifndef signbit
-inline bool signbit(double x) { return x < 0.0; } // FIXME: Wrong for negative 0.
+inline bool signbit(double x) { return copysign(1.0, x) < 0; }
 #endif
 
 #endif
@@ -96,7 +106,7 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x
 
 #endif
 
-#if COMPILER(MSVC) || COMPILER(RVCT)
+#if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0)))
 
 // We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss.
 static double round(double num)
@@ -137,6 +147,13 @@ inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x +
 inline double copysign(double x, double y) { return _copysign(x, y); }
 inline int isfinite(double x) { return _finite(x); }
 
+// MSVC's math.h does not currently supply log2.
+inline double log2(double num)
+{
+    // This constant is roughly M_LN2, which is not provided by default on Windows.
+    return log(num) / 0.693147180559945309417232121458176568;
+}
+
 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values.
 inline double wtf_atan2(double x, double y)
 {
@@ -190,7 +207,74 @@ inline float deg2turn(float d) { return d / 360.0f; }
 inline float rad2grad(float r) { return r * 200.0f / piFloat; }
 inline float grad2rad(float g) { return g * piFloat / 200.0f; }
 
-#if !COMPILER(MSVC) && !COMPILER(WINSCW) && !(COMPILER(RVCT) && OS(SYMBIAN))
+inline int clampToInteger(double x)
+{
+    const double intMax = static_cast<double>(std::numeric_limits<int>::max());
+    const double intMin = static_cast<double>(std::numeric_limits<int>::min());
+    
+    if (x >= intMax)
+        return std::numeric_limits<int>::max();
+    if (x <= intMin)
+        return std::numeric_limits<int>::min();
+    return static_cast<int>(x);
+}
+
+inline float clampToFloat(double x)
+{
+    const double floatMax = static_cast<double>(std::numeric_limits<float>::max());
+    const double floatMin = -static_cast<double>(std::numeric_limits<float>::max());
+    
+    if (x >= floatMax)
+        return std::numeric_limits<float>::max();
+    if (x <= floatMin)
+        return -std::numeric_limits<float>::max();
+    return static_cast<float>(x);
+}
+
+inline int clampToPositiveInteger(double x)
+{
+    const double intMax = static_cast<double>(std::numeric_limits<int>::max());
+    
+    if (x >= intMax)
+        return std::numeric_limits<int>::max();
+    if (x <= 0)
+        return 0;
+    return static_cast<int>(x);
+}
+
+inline int clampToInteger(float x)
+{
+    const float intMax = static_cast<float>(std::numeric_limits<int>::max());
+    const float intMin = static_cast<float>(std::numeric_limits<int>::min());
+    
+    if (x >= intMax)
+        return std::numeric_limits<int>::max();
+    if (x <= intMin)
+        return std::numeric_limits<int>::min();
+    return static_cast<int>(x);
+}
+
+inline int clampToPositiveInteger(float x)
+{
+    const float intMax = static_cast<float>(std::numeric_limits<int>::max());
+    
+    if (x >= intMax)
+        return std::numeric_limits<int>::max();
+    if (x <= 0)
+        return 0;
+    return static_cast<int>(x);
+}
+
+inline int clampToInteger(unsigned x)
+{
+    const unsigned intMax = static_cast<unsigned>(std::numeric_limits<int>::max());
+    
+    if (x >= intMax)
+        return std::numeric_limits<int>::max();
+    return static_cast<int>(x);
+}
+
+#if !COMPILER(MSVC) && !(COMPILER(RVCT) && PLATFORM(BREWMP)) && !OS(SOLARIS) && !OS(SYMBIAN)
 using std::isfinite;
 using std::isinf;
 using std::isnan;
index 48bd10ad0dca9b18d819307027923ce06df6880f..3e481547794e5f784d6a7c28d23430ba28f22519 100644 (file)
@@ -41,14 +41,15 @@ namespace WTF {
     enum MessageQueueWaitResult {
         MessageQueueTerminated,       // Queue was destroyed while waiting for message.
         MessageQueueTimeout,          // Timeout was specified and it expired.
-        MessageQueueMessageReceived,  // A message was successfully received and returned.
+        MessageQueueMessageReceived   // A message was successfully received and returned.
     };
 
     // The queue takes ownership of messages and transfer it to the new owner
     // when messages are fetched from the queue.
     // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>.
     template<typename DataType>
-    class MessageQueue : public Noncopyable {
+    class MessageQueue {
+        WTF_MAKE_NONCOPYABLE(MessageQueue);
     public:
         MessageQueue() : m_killed(false) { }
         ~MessageQueue();
@@ -92,7 +93,7 @@ namespace WTF {
     inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
-        m_queue.append(message.release());
+        m_queue.append(message.leakPtr());
         m_condition.signal();
     }
 
@@ -102,7 +103,7 @@ namespace WTF {
     {
         MutexLocker lock(m_mutex);
         bool wasEmpty = m_queue.isEmpty();
-        m_queue.append(message.release());
+        m_queue.append(message.leakPtr());
         m_condition.signal();
         return wasEmpty;
     }
@@ -111,7 +112,7 @@ namespace WTF {
     inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
-        m_queue.prepend(message.release());
+        m_queue.prepend(message.leakPtr());
         m_condition.signal();
     }
 
@@ -119,9 +120,9 @@ namespace WTF {
     inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
     {
         MessageQueueWaitResult exitReason; 
-        PassOwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
+        OwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime());
         ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
-        return result;
+        return result.release();
     }
 
     template<typename DataType>
@@ -139,19 +140,19 @@ namespace WTF {
 
         if (m_killed) {
             result = MessageQueueTerminated;
-            return 0;
+            return nullptr;
         }
 
         if (timedOut) {
             result = MessageQueueTimeout;
-            return 0;
+            return nullptr;
         }
 
         ASSERT(found != m_queue.end());
-        DataType* message = *found;
+        OwnPtr<DataType> message = adoptPtr(*found);
         m_queue.remove(found);
         result = MessageQueueMessageReceived;
-        return message;
+        return message.release();
     }
 
     template<typename DataType>
@@ -159,13 +160,11 @@ namespace WTF {
     {
         MutexLocker lock(m_mutex);
         if (m_killed)
-            return 0;
+            return nullptr;
         if (m_queue.isEmpty())
-            return 0;
+            return nullptr;
 
-        DataType* message = m_queue.first();
-        m_queue.removeFirst();
-        return message;
+        return adoptPtr(m_queue.takeFirst());
     }
 
     template<typename DataType>
diff --git a/wtf/NonCopyingSort.h b/wtf/NonCopyingSort.h
new file mode 100644 (file)
index 0000000..fd611bd
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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 COMPUTER, 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 WTF_NonCopyingSort_h
+#define WTF_NonCopyingSort_h
+
+namespace WTF {
+
+using std::swap;
+
+template<typename RandomAccessIterator, typename Predicate>
+inline void siftDown(RandomAccessIterator array, ptrdiff_t start, ptrdiff_t end, Predicate compareLess) 
+{
+    ptrdiff_t root = start;
+
+    while (root * 2 + 1 <= end) {
+        ptrdiff_t child = root * 2 + 1;
+        if (child < end && compareLess(array[child], array[child + 1]))
+            child++;
+        
+        if (compareLess(array[root], array[child])) {
+            swap(array[root], array[child]);
+            root = child;
+        } else
+            return;
+    }
+}
+
+template<typename RandomAccessIterator, typename Predicate>
+inline void heapify(RandomAccessIterator array, ptrdiff_t count, Predicate compareLess) 
+{
+    ptrdiff_t start = (count - 2) / 2;
+     
+    while (start >= 0) {
+        siftDown(array, start, count - 1, compareLess);
+        start--;
+    }
+}
+
+template<typename RandomAccessIterator, typename Predicate>
+void heapSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess)
+{
+    ptrdiff_t count = end - start;
+    heapify(start, count, compareLess);
+
+    ptrdiff_t endIndex = count - 1;
+    while (endIndex > 0) {
+        swap(start[endIndex], start[0]);
+        siftDown(start, 0, endIndex - 1, compareLess);
+        endIndex--;
+    }
+}
+
+template<typename RandomAccessIterator, typename Predicate>
+inline void nonCopyingSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess)
+{
+    // heapsort happens to use only swaps, not copies, but the essential thing about
+    // this function is the fact that it does not copy, not the specific algorithm
+    heapSort(start, end, compareLess);
+}
+
+} // namespace WTF
+
+using WTF::nonCopyingSort;
+
+#endif // WTF_NonCopyingSort_h
index 60a46e2669787bb02b7ee345d6cdef07a4c59de7..cc6bc559a3c2f1d68aa8d8db4e3975b5d6fbadd0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006, 2010 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
 #ifndef WTF_Noncopyable_h
 #define WTF_Noncopyable_h
 
-// We don't want argument-dependent lookup to pull in everything from the WTF
-// namespace when you use Noncopyable, so put it in its own namespace.
-
-#include "FastAllocBase.h"
-
-namespace WTFNoncopyable {
-
-    class Noncopyable : public FastAllocBase {
-        Noncopyable(const Noncopyable&);
-        Noncopyable& operator=(const Noncopyable&);
-    protected:
-        Noncopyable() { }
-        ~Noncopyable() { }
-    };
-
-    class NoncopyableCustomAllocated {
-        NoncopyableCustomAllocated(const NoncopyableCustomAllocated&);
-        NoncopyableCustomAllocated& operator=(const NoncopyableCustomAllocated&);
-    protected:
-        NoncopyableCustomAllocated() { }
-        ~NoncopyableCustomAllocated() { }
-    };
-
-} // namespace WTFNoncopyable
-
-using WTFNoncopyable::Noncopyable;
-using WTFNoncopyable::NoncopyableCustomAllocated;
+#ifndef __has_feature
+    #define __has_feature(x) 0
+#endif
+
+#if __has_feature(cxx_deleted_functions)
+    #define WTF_MAKE_NONCOPYABLE(ClassName) \
+        _Pragma("clang diagnostic push") \
+        _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \
+        _Pragma("clang diagnostic ignored \"-Wc++0x-extensions\"") \
+        private: \
+            ClassName(const ClassName&) = delete; \
+            ClassName& operator=(const ClassName&) = delete; \
+        _Pragma("clang diagnostic pop")
+#else
+    #define WTF_MAKE_NONCOPYABLE(ClassName) \
+        private: \
+            ClassName(const ClassName&); \
+            ClassName& operator=(const ClassName&)
+#endif
 
 #endif // WTF_Noncopyable_h
diff --git a/wtf/NullPtr.cpp b/wtf/NullPtr.cpp
new file mode 100644 (file)
index 0000000..224f1f1
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+
+Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+
+*/
+
+#include "config.h"
+#include "NullPtr.h"
+
+#if !HAVE(NULLPTR)
+
+std::nullptr_t nullptr;
+
+#endif
diff --git a/wtf/NullPtr.h b/wtf/NullPtr.h
new file mode 100644 (file)
index 0000000..c0e7bd3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+
+Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 NullPtr_h
+#define NullPtr_h
+
+// For compilers and standard libraries that do not yet include it, this adds the
+// nullptr_t type and nullptr object. They are defined in the same namespaces they
+// would be in compiler and library that had the support.
+
+#ifndef __has_feature
+    #define __has_feature(feature) 0
+#endif
+
+#if __has_feature(cxx_nullptr) || (GCC_VERSION_AT_LEAST(4, 6, 0) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define HAVE_NULLPTR 1
+
+#else
+
+namespace std {
+    class nullptr_t { };
+}
+
+extern std::nullptr_t nullptr;
+
+#endif
+
+#endif
diff --git a/wtf/OSAllocator.h b/wtf/OSAllocator.h
new file mode 100644 (file)
index 0000000..ca93056
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 OSAllocator_h
+#define OSAllocator_h
+
+#include <wtf/UnusedParam.h>
+#include <wtf/VMTags.h>
+#include <wtf/VMTags.h>
+
+namespace WTF {
+
+class OSAllocator {
+public:
+    enum Usage {
+        UnknownUsage = -1,
+        FastMallocPages = VM_TAG_FOR_TCMALLOC_MEMORY,
+        JSGCHeapPages = VM_TAG_FOR_COLLECTOR_MEMORY,
+        JSVMStackPages = VM_TAG_FOR_REGISTERFILE_MEMORY,
+        JSJITCodePages = VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY,
+    };
+
+    // These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state,
+    // releaseDecommitted should be called on a region of VM allocated by a single reservation,
+    // the memory must all currently be in a decommitted state.
+    static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
+    static void releaseDecommitted(void*, size_t);
+
+    // These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should
+    // never be accessed, since the OS may not have attached physical memory for these regions).
+    // Clients should only call commit on uncommitted regions and decommit on committed regions.
+    static void commit(void*, size_t, bool writable, bool executable);
+    static void decommit(void*, size_t);
+
+    // These methods are symmetric; reserveAndCommit allocates VM in an committed state,
+    // decommitAndRelease should be called on a region of VM allocated by a single reservation,
+    // the memory must all currently be in a committed state.
+    static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
+    static void decommitAndRelease(void* base, size_t size);
+
+    // These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than
+    // committing/decommitting the entire region additional parameters allow a subregion to be
+    // specified.
+    static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false);
+    static void decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize);
+};
+
+inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable)
+{
+    void* base = reserveUncommitted(reserveSize, usage, writable, executable);
+    commit(base, commitSize, writable, executable);
+    return base;
+}
+
+inline void OSAllocator::decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize)
+{
+    ASSERT(decommitBase >= releaseBase && (static_cast<char*>(decommitBase) + decommitSize) <= (static_cast<char*>(releaseBase) + releaseSize));
+#if OS(WINCE) || OS(SYMBIAN)
+    // On most platforms we can actually skip this final decommit; releasing the VM will
+    // implicitly decommit any physical memory in the region. This is not true on WINCE.
+    // On Symbian, this makes implementation simpler and better aligned with the RChunk API
+    decommit(decommitBase, decommitSize);
+#else
+    UNUSED_PARAM(decommitBase);
+    UNUSED_PARAM(decommitSize);
+#endif
+    releaseDecommitted(releaseBase, releaseSize);
+}
+
+inline void OSAllocator::decommitAndRelease(void* base, size_t size)
+{
+    decommitAndRelease(base, size, base, size);
+}
+
+} // namespace WTF
+
+using WTF::OSAllocator;
+
+#endif // OSAllocator_h
diff --git a/wtf/OSAllocatorPosix.cpp b/wtf/OSAllocatorPosix.cpp
new file mode 100644 (file)
index 0000000..a6052ed
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "OSAllocator.h"
+
+#include "PageAllocation.h"
+#include <errno.h>
+#include <sys/mman.h>
+#include <wtf/Assertions.h>
+#include <wtf/UnusedParam.h>
+
+namespace WTF {
+
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
+{
+    void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
+#if HAVE(MADV_FREE_REUSE)
+    // To support the "reserve then commit" model, we have to initially decommit.
+    while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
+#endif
+    return result;
+}
+
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
+{
+    // All POSIX reservations start out logically committed.
+    int protection = PROT_READ;
+    if (writable)
+        protection |= PROT_WRITE;
+    if (executable)
+        protection |= PROT_EXEC;
+
+    int flags = MAP_PRIVATE | MAP_ANON;
+#if defined MAP_JIT
+    if (executable)
+        flags |= MAP_JIT;
+#endif
+
+#if OS(DARWIN)
+    int fd = usage;
+#else
+    int fd = -1;
+#endif
+
+    void* result = 0;
+#if (OS(DARWIN) && CPU(X86_64))
+    if (executable) {
+        ASSERT(includesGuardPages);
+        // Cook up an address to allocate at, using the following recipe:
+        //   17 bits of zero, stay in userspace kids.
+        //   26 bits of randomness for ASLR.
+        //   21 bits of zero, at least stay aligned within one level of the pagetables.
+        //
+        // But! - as a temporary workaround for some plugin problems (rdar://problem/6812854),
+        // for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus
+        // 2^24, which should put up somewhere in the middle of userspace (in the address range
+        // 0x200000000000 .. 0x5fffffffffff).
+        intptr_t randomLocation = 0;
+        randomLocation = arc4random() & ((1 << 25) - 1);
+        randomLocation += (1 << 24);
+        randomLocation <<= 21;
+        result = reinterpret_cast<void*>(randomLocation);
+    }
+#endif
+
+    result = mmap(result, bytes, protection, flags, fd, 0);
+    if (result == MAP_FAILED) {
+    #if ENABLE(INTERPRETER)
+        if (executable)
+            result = 0;
+        else
+    #endif
+            CRASH();
+    }
+    if (result && includesGuardPages) {
+        // We use mmap to remap the guardpages rather than using mprotect as
+        // mprotect results in multiple references to the code region.  This
+        // breaks the madvise based mechanism we use to return physical memory
+        // to the OS.
+        mmap(result, pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0);
+        mmap(static_cast<char*>(result) + bytes - pageSize(), pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0);
+    }
+
+    return result;
+}
+
+void OSAllocator::commit(void* address, size_t bytes, bool, bool)
+{
+#if HAVE(MADV_FREE_REUSE)
+    while (madvise(address, bytes, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { }
+#else
+    // Non-MADV_FREE_REUSE reservations automatically commit on demand.
+    UNUSED_PARAM(address);
+    UNUSED_PARAM(bytes);
+#endif
+}
+
+void OSAllocator::decommit(void* address, size_t bytes)
+{
+#if HAVE(MADV_FREE_REUSE)
+    while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
+#elif HAVE(MADV_FREE)
+    while (madvise(address, bytes, MADV_FREE) == -1 && errno == EAGAIN) { }
+#elif HAVE(MADV_DONTNEED)
+    while (madvise(address, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { }
+#else
+    UNUSED_PARAM(address);
+    UNUSED_PARAM(bytes);
+#endif
+}
+
+void OSAllocator::releaseDecommitted(void* address, size_t bytes)
+{
+    int result = munmap(address, bytes);
+    if (result == -1)
+        CRASH();
+}
+
+} // namespace WTF
diff --git a/wtf/OSAllocatorSymbian.cpp b/wtf/OSAllocatorSymbian.cpp
new file mode 100644 (file)
index 0000000..59bcdba
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "OSAllocator.h"
+
+#include "PageAllocatorSymbian.h"
+
+namespace WTF {
+
+// Array to store code chunks used by JIT engine(s)
+static RPointerArray<SymbianChunk> codeChunksContainer;
+
+// The singleton data allocator (non code)
+static PageAllocatorSymbian dataAllocator;
+
+_LIT(KErrorStringInternalConsistency, "OSAllocator:ConsistencyError");
+_LIT(KErrorStringChunkCreation, "OSAllocator:ChunkInitError");
+_LIT(KErrorStringPageSize, "OSAllocator:WrongPageSize");
+
+// Makes a new code chunk for a JIT engine with everything in committed state
+static void* allocateCodeChunk(size_t bytes) 
+{
+    RChunk c; 
+    TInt error = c.CreateLocalCode(bytes, bytes);
+    __ASSERT_ALWAYS(error == KErrNone, User::Panic(KErrorStringChunkCreation, error));
+   
+    codeChunksContainer.Append(new SymbianChunk(c.Handle())); 
+    return static_cast<void*>(c.Base()); 
+}
+   
+// Frees the _entire_ code chunk in which this address resides. 
+static bool deallocateCodeChunk(void* address) 
+{     
+    bool found = false; 
+    for (int i = 0; i < codeChunksContainer.Count(); i++) { 
+        SymbianChunk* p = codeChunksContainer[i];
+        if (p && p->contains(address)) { 
+            codeChunksContainer.Remove(i);
+            delete p;
+            found = true;
+        }
+    }
+    return found; 
+}
+
+// Return the (singleton) object that manages all non-code VM operations
+static PageAllocatorSymbian* dataAllocatorInstance() 
+{
+    return &dataAllocator; 
+}
+
+// Reserve memory and return the base address of the region
+void* OSAllocator::reserveUncommitted(size_t reservationSize, Usage usage, bool , bool executable, bool) 
+{
+    void* base = 0; 
+    if (executable) 
+        base = allocateCodeChunk(reservationSize);
+    else
+        base = dataAllocatorInstance()->reserve(reservationSize);
+    return base; 
+}
+
+// Inverse operation of reserveUncommitted()
+void OSAllocator::releaseDecommitted(void* parkedBase, size_t bytes) 
+{
+    if (dataAllocatorInstance()->contains(parkedBase)) 
+        dataAllocatorInstance()->release(parkedBase, bytes);
+
+    // NOOP for code chunks (JIT) because we released them in decommit()
+}
+
+// Commit what was previously reserved via reserveUncommitted()
+void OSAllocator::commit(void* address, size_t bytes, bool, bool executable) 
+{
+    // For code chunks, we commit (early) in reserveUncommitted(), so NOOP
+    // For data regions, do real work
+    if (!executable) 
+        dataAllocatorInstance()->commit(address, bytes);
+}
+
+void OSAllocator::decommit(void* address, size_t bytes) 
+{ 
+    if (dataAllocatorInstance()->contains(address))
+        dataAllocatorInstance()->decommit(address, bytes);
+    else
+        deallocateCodeChunk(address); // for code chunk, decommit AND release    
+}
+    
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool)
+{ 
+    void* base = reserveUncommitted(bytes, usage, writable, executable);
+    commit(base, bytes, writable, executable);
+    return base;
+}
+
+
+// The PageAllocatorSymbian class helps map OSAllocator calls for reserve/commit/decommit
+// to a single large Symbian chunk. Only works with multiples of page size, and as a corollary 
+// all addresses accepted or returned by it are also page-sized aligned. 
+// Design notes: 
+// - We initialize a chunk up-front with a large reservation size
+// - The entire reservation reserve is logically divided into pageSized blocks (4K on Symbian) 
+// - The map maintains 1 bit for each of the 4K-sized region in our address space
+// - OSAllocator::reserveUncommitted() requests lead to 1 or more bits being set in map 
+//   to indicate internally reserved state. The VM address corresponding to the first bit is returned. 
+// - OSAllocator::commit() actually calls RChunk.commit() and commits *all or part* of the region 
+//   reserved via reserveUncommitted() previously. 
+// - OSAllocator::decommit() calls RChunk.decommit() 
+// - OSAllocator::releaseDecommitted() unparks all the bits in the map, but trusts that a previously
+//   call to decommit() would have returned the memory to the OS 
+PageAllocatorSymbian::PageAllocatorSymbian()
+{        
+    __ASSERT_ALWAYS(m_pageSize == WTF::pageSize(), User::Panic(KErrorStringPageSize, m_pageSize));
+    
+    RChunk chunk;
+    TInt error = chunk.CreateDisconnectedLocal(0, 0, TInt(largeReservationSize));
+    __ASSERT_ALWAYS(error == KErrNone, User::Panic(KErrorStringChunkCreation, error));
+    
+    m_chunk = new SymbianChunk(chunk.Handle()); // takes ownership of chunk
+}
+
+PageAllocatorSymbian::~PageAllocatorSymbian() 
+{
+    delete m_chunk;
+}
+
+// Reserves a region internally in the bitmap
+void* PageAllocatorSymbian::reserve(size_t bytes) 
+{ 
+    // Find first available region
+    const size_t nPages = bytes / m_pageSize;
+    const int64_t startIdx = m_map.findRunOfZeros(nPages);
+
+    // Pseudo OOM
+    if (startIdx < 0)
+        return 0;
+    
+    for (size_t i = startIdx; i < startIdx + nPages ; i++)
+        m_map.set(i);
+    
+    return static_cast<void*>( m_chunk->m_base + (TUint)(m_pageSize * startIdx) ); 
+}
+
+// Reverses the effects of a reserve() call
+void PageAllocatorSymbian::release(void* address, size_t bytes)
+{
+    const size_t startIdx = (static_cast<char*>(address) - m_chunk->m_base) / m_pageSize;
+    const size_t nPages = bytes / m_pageSize;
+    for (size_t i = startIdx; i < startIdx + nPages ; i++)
+        m_map.clear(i);
+}
+
+// Actually commit memory from the OS, after a previous call to reserve()
+bool PageAllocatorSymbian::commit(void* address, size_t bytes) 
+{ 
+    // sanity check that bits were previously set
+    const size_t idx = (static_cast<char*>(address) - m_chunk->m_base) / m_pageSize;
+    const size_t nPages = bytes / m_pageSize;
+    __ASSERT_ALWAYS(m_map.get(idx), User::Panic(KErrorStringInternalConsistency, idx));
+    __ASSERT_ALWAYS(m_map.get(idx+nPages-1), User::Panic(KErrorStringInternalConsistency, idx+nPages-1));
+    
+    TInt error = m_chunk->Commit(static_cast<char*>(address) - m_chunk->m_base, bytes);
+    return (error == KErrNone);
+}
+
+// Inverse operation of commit(), a release() should follow later
+bool PageAllocatorSymbian::decommit(void* address, size_t bytes) 
+{ 
+    TInt error = m_chunk->Decommit(static_cast<char*>(address) - m_chunk->m_base, bytes);
+    return (error == KErrNone); 
+}
+
+bool PageAllocatorSymbian::contains(const void* address) const
+{
+    return m_chunk->contains(address);     
+}
+
+} // namespace WTF
diff --git a/wtf/OSAllocatorWin.cpp b/wtf/OSAllocatorWin.cpp
new file mode 100644 (file)
index 0000000..e7beb8a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "OSAllocator.h"
+
+#include "windows.h"
+#include <wtf/Assertions.h>
+
+namespace WTF {
+
+static inline DWORD protection(bool writable, bool executable)
+{
+    return executable ?
+        (writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ) :
+        (writable ? PAGE_READWRITE : PAGE_READONLY);
+}
+
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool executable)
+{
+    void* result = VirtualAlloc(0, bytes, MEM_RESERVE, protection(writable, executable));
+    if (!result)
+        CRASH();
+    return result;
+}
+
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage, bool writable, bool executable)
+{
+    void* result = VirtualAlloc(0, bytes, MEM_RESERVE | MEM_COMMIT, protection(writable, executable));
+    if (!result)
+        CRASH();
+    return result;
+}
+
+void OSAllocator::commit(void* address, size_t bytes, bool writable, bool executable)
+{
+    void* result = VirtualAlloc(address, bytes, MEM_COMMIT, protection(writable, executable));
+    if (!result)
+        CRASH();
+}
+
+void OSAllocator::decommit(void* address, size_t bytes)
+{
+    bool result = VirtualFree(address, bytes, MEM_DECOMMIT);
+    if (!result)
+        CRASH();
+}
+
+void OSAllocator::releaseDecommitted(void* address, size_t bytes)
+{
+    // According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx,
+    // dwSize must be 0 if dwFreeType is MEM_RELEASE.
+    bool result = VirtualFree(address, 0, MEM_RELEASE);
+    if (!result)
+        CRASH();
+}
+
+} // namespace WTF
diff --git a/wtf/OSRandomSource.cpp b/wtf/OSRandomSource.cpp
new file mode 100644 (file)
index 0000000..7d86f6f
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 Google 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 GOOGLE, 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 COMPUTER, 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. 
+ */
+
+#include "config.h"
+#include "OSRandomSource.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#if OS(SYMBIAN)
+#include <e32math.h>
+#endif
+
+#if OS(UNIX)
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#if OS(WINDOWS)
+#include <windows.h>
+#include <wincrypt.h> // windows.h must be included before wincrypt.h.
+#endif
+
+namespace WTF {
+
+#if USE(OS_RANDOMNESS)
+void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length)
+{
+#if OS(SYMBIAN)
+    TInt random;
+    while (length > sizeof(random)) {
+        random = Math::Random();
+        memcpy(buffer, &random, sizeof(random));
+        length -= sizeof(random);
+        buffer += sizeof(random);
+    }
+    if (length > 0) {
+        random = Math::Random();
+        memcpy(buffer, &random, length);
+    }
+#elif OS(UNIX)
+    int fd = open("/dev/urandom", O_RDONLY, 0);
+    if (fd < 0)
+        CRASH(); // We need /dev/urandom for this API to work...
+
+    if (read(fd, buffer, length) != static_cast<ssize_t>(length))
+        CRASH();
+
+    close(fd);
+#elif OS(WINDOWS)
+    HCRYPTPROV hCryptProv = 0;
+    if (!CryptAcquireContext(&hCryptProv, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+        CRASH();
+    if (!CryptGenRandom(hCryptProv, length, buffer))
+        CRASH();
+    CryptReleaseContext(hCryptProv, 0);
+#else
+    #error "This configuration doesn't have a strong source of randomness."
+    // WARNING: When adding new sources of OS randomness, the randomness must
+    //          be of cryptographic quality!
+#endif
+}
+#endif
+
+}
diff --git a/wtf/OSRandomSource.h b/wtf/OSRandomSource.h
new file mode 100644 (file)
index 0000000..214a954
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) Google, 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 GOOGLE, 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 COMPUTER, 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 WTF_OSRandomSource_h
+#define WTF_OSRandomSource_h
+
+namespace WTF {
+
+#if USE(OS_RANDOMNESS)
+// This function attempts to fill buffer with randomness from the operating
+// system.  If insufficient randomness is available, the buffer will be
+// partially filled.  Rather than calling this function directly, consider
+// calling cryptographicallyRandomNumber or cryptographicallyRandomValues.
+void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length);
+#endif
+
+}
+
+#endif
index 61375c7691c163eaeb7b6415b1b23de97a70d665..2828698ff3a665904cd65ff5d653ce22bda0c3e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006 Apple Computer, Inc.
+ *  Copyright (C) 2006, 2010 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
 #ifndef WTF_OwnArrayPtr_h
 #define WTF_OwnArrayPtr_h
 
+#include "Assertions.h"
+#include "Noncopyable.h"
+#include "NullPtr.h"
+#include "PassOwnArrayPtr.h"
 #include <algorithm>
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
 
 namespace WTF {
 
-    template <typename T> class OwnArrayPtr : public Noncopyable {
-    public:
-        explicit OwnArrayPtr(T* ptr = 0) : m_ptr(ptr) { }
-        ~OwnArrayPtr() { safeDelete(); }
+template<typename T> class PassOwnArrayPtr;
+template<typename T> PassOwnArrayPtr<T> adoptArrayPtr(T*);
 
-        T* get() const { return m_ptr; }
-        T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; }
+template <typename T> class OwnArrayPtr {
+public:
+    typedef T* PtrType;
 
-        void set(T* ptr) { ASSERT(m_ptr != ptr); safeDelete(); m_ptr = ptr; }
-        void clear() { safeDelete(); m_ptr = 0; }
+    OwnArrayPtr() : m_ptr(0) { }
 
-        T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
-        T* operator->() const { ASSERT(m_ptr); return m_ptr; }
+    // See comment in PassOwnArrayPtr.h for why this takes a const reference.
+    template<typename U> OwnArrayPtr(const PassOwnArrayPtr<U>& o);
 
-        T& operator[](std::ptrdiff_t i) const { ASSERT(m_ptr); ASSERT(i >= 0); return m_ptr[i]; }
+    // This copy constructor is used implicitly by gcc when it generates
+    // transients for assigning a PassOwnArrayPtr<T> object to a stack-allocated
+    // OwnArrayPtr<T> object. It should never be called explicitly and gcc
+    // should optimize away the constructor when generating code.
+    OwnArrayPtr(const OwnArrayPtr<T>&);
 
-        bool operator!() const { return !m_ptr; }
+    ~OwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); }
 
-        // This conversion operator allows implicit conversion to bool but not to other integer types.
+    PtrType get() const { return m_ptr; }
+
+    void clear();
+    PassOwnArrayPtr<T> release();
+    PtrType leakPtr() WARN_UNUSED_RETURN;
+
+    T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+    PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
+
+    T& operator[](std::ptrdiff_t i) const { ASSERT(m_ptr); ASSERT(i >= 0); return m_ptr[i]; }
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
 #if COMPILER(WINSCW)
-        operator bool() const { return m_ptr; }
+    operator bool() const { return m_ptr; }
 #else
-        typedef T* OwnArrayPtr::*UnspecifiedBoolType;
-        operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; }
+    typedef T* OwnArrayPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; }
 #endif
 
-        void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); }
+    OwnArrayPtr& operator=(const PassOwnArrayPtr<T>&);
+    OwnArrayPtr& operator=(std::nullptr_t) { clear(); return *this; }
+    template<typename U> OwnArrayPtr& operator=(const PassOwnArrayPtr<U>&);
+
+    void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); }
 
-    private:
-        void safeDelete() { typedef char known[sizeof(T) ? 1 : -1]; if (sizeof(known)) delete [] m_ptr; }
+#ifdef LOOSE_OWN_ARRAY_PTR
+    explicit OwnArrayPtr(PtrType ptr) : m_ptr(ptr) { }
+    void set(PtrType);
+#endif
 
-        T* m_ptr;
-    };
-    
-    template <typename T> inline void swap(OwnArrayPtr<T>& a, OwnArrayPtr<T>& b) { a.swap(b); }
+private:
+    PtrType m_ptr;
+};
+
+template<typename T> template<typename U> inline OwnArrayPtr<T>::OwnArrayPtr(const PassOwnArrayPtr<U>& o)
+    : m_ptr(o.leakPtr())
+{
+}
+
+template<typename T> inline void OwnArrayPtr<T>::clear()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = 0;
+    deleteOwnedArrayPtr(ptr);
+}
+
+template<typename T> inline PassOwnArrayPtr<T> OwnArrayPtr<T>::release()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = 0;
+    return adoptArrayPtr(ptr);
+}
+
+template<typename T> inline typename OwnArrayPtr<T>::PtrType OwnArrayPtr<T>::leakPtr()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = 0;
+    return ptr;
+}
+
+#ifdef LOOSE_OWN_ARRAY_PTR
+template<typename T> inline void OwnArrayPtr<T>::set(PtrType ptr)
+{
+    ASSERT(!ptr || m_ptr != ptr);
+    PtrType oldPtr = m_ptr;
+    m_ptr = ptr;
+    deleteOwnedArrayPtr(oldPtr);
+}
+#endif
 
-    template <typename T> inline T* getPtr(const OwnArrayPtr<T>& p)
-    {
-        return p.get();
-    }
+template<typename T> inline OwnArrayPtr<T>& OwnArrayPtr<T>::operator=(const PassOwnArrayPtr<T>& o)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = o.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    deleteOwnedArrayPtr(ptr);
+    return *this;
+}
+
+template<typename T> template<typename U> inline OwnArrayPtr<T>& OwnArrayPtr<T>::operator=(const PassOwnArrayPtr<U>& o)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = o.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    deleteOwnedArrayPtr(ptr);
+    return *this;
+}
+
+template <typename T> inline void swap(OwnArrayPtr<T>& a, OwnArrayPtr<T>& b)
+{
+    a.swap(b);
+}
+
+template<typename T, typename U> inline bool operator==(const OwnArrayPtr<T>& a, U* b)
+{
+    return a.get() == b; 
+}
+
+template<typename T, typename U> inline bool operator==(T* a, const OwnArrayPtr<U>& b) 
+{
+    return a == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const OwnArrayPtr<T>& a, U* b)
+{
+    return a.get() != b; 
+}
+
+template<typename T, typename U> inline bool operator!=(T* a, const OwnArrayPtr<U>& b)
+{
+    return a != b.get(); 
+}
+
+template <typename T> inline T* getPtr(const OwnArrayPtr<T>& p)
+{
+    return p.get();
+}
 
 } // namespace WTF
 
index 8b6cbf45e7acd24831843d1c734266b985407ea9..9d4841a8e299f4a13f036da7280eb67571a34aec 100644 (file)
 #define OwnFastMallocPtr_h
 
 #include "FastMalloc.h"
-#include "Noncopyable.h"
 
 namespace WTF {
 
-    template<class T> class OwnFastMallocPtr : public Noncopyable {
+    template<class T> class OwnFastMallocPtr {
+        WTF_MAKE_NONCOPYABLE(OwnFastMallocPtr);
     public:
         explicit OwnFastMallocPtr(T* ptr) : m_ptr(ptr)
         {
index af1684bddb1423389e73ef2bb7fb7fc2b41befcd..f80ec54ddc2cdceefcf0df705e6b44872596c483 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2006, 2007, 2008, 2009, 2010 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
@@ -22,7 +22,7 @@
 #define WTF_OwnPtr_h
 
 #include "Assertions.h"
-#include "Noncopyable.h"
+#include "NullPtr.h"
 #include "OwnPtrCommon.h"
 #include "TypeTraits.h"
 #include <algorithm>
@@ -32,32 +32,32 @@ namespace WTF {
 
     // Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type.
 
-    template <typename T> class PassOwnPtr;
+    template<typename T> class PassOwnPtr;
+    template<typename T> PassOwnPtr<T> adoptPtr(T*);
 
-    template <typename T> class OwnPtr : public Noncopyable {
+    template<typename T> class OwnPtr {
     public:
         typedef typename RemovePointer<T>::Type ValueType;
         typedef ValueType* PtrType;
 
-        explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+        OwnPtr() : m_ptr(0) { }
+
         // See comment in PassOwnPtr.h for why this takes a const reference.
-        template <typename U> OwnPtr(const PassOwnPtr<U>& o);
+        template<typename U> OwnPtr(const PassOwnPtr<U>& o);
 
         // This copy constructor is used implicitly by gcc when it generates
         // transients for assigning a PassOwnPtr<T> object to a stack-allocated
-        // OwnPtr<T> object.  It should never be called explicitly and gcc
+        // OwnPtr<T> object. It should never be called explicitly and gcc
         // should optimize away the constructor when generating code.
-        OwnPtr(const OwnPtr<ValueType>& o);
+        OwnPtr(const OwnPtr<ValueType>&);
 
         ~OwnPtr() { deleteOwnedPtr(m_ptr); }
 
         PtrType get() const { return m_ptr; }
-        PtrType release() { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
-
-        // FIXME: This should be renamed to adopt. 
-        void set(PtrType ptr) { ASSERT(!ptr || m_ptr != ptr); deleteOwnedPtr(m_ptr); m_ptr = ptr; }
 
-        void clear() { deleteOwnedPtr(m_ptr); m_ptr = 0; }
+        void clear();
+        PassOwnPtr<T> release();
+        PtrType leakPtr() WARN_UNUSED_RETURN;
 
         ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
         PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
@@ -69,65 +69,109 @@ namespace WTF {
         operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; }
 
         OwnPtr& operator=(const PassOwnPtr<T>&);
-        template <typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
+        OwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
+        template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&);
 
         void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); }
 
+#ifdef LOOSE_OWN_PTR
+        explicit OwnPtr(PtrType ptr) : m_ptr(ptr) { }
+        void set(PtrType);
+#endif
+
     private:
+        OwnPtr& operator=(const OwnPtr<T>&);
+
+        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
+        // double-destruction), so these equality operators should never be needed.
+        template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+        template<typename U> bool operator!=(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+        template<typename U> bool operator==(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+        template<typename U> bool operator!=(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+
         PtrType m_ptr;
     };
 
-    template <typename T> template <typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o)
-        : m_ptr(o.release())
+    template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o)
+        : m_ptr(o.leakPtr())
+    {
+    }
+
+    template<typename T> inline void OwnPtr<T>::clear()
+    {
+        PtrType ptr = m_ptr;
+        m_ptr = 0;
+        deleteOwnedPtr(ptr);
+    }
+
+    template<typename T> inline PassOwnPtr<T> OwnPtr<T>::release()
+    {
+        PtrType ptr = m_ptr;
+        m_ptr = 0;
+        return adoptPtr(ptr);
+    }
+
+    template<typename T> inline typename OwnPtr<T>::PtrType OwnPtr<T>::leakPtr()
     {
+        PtrType ptr = m_ptr;
+        m_ptr = 0;
+        return ptr;
+    }
+
+#ifdef LOOSE_OWN_PTR
+    template<typename T> inline void OwnPtr<T>::set(PtrType ptr)
+    {
+        ASSERT(!ptr || m_ptr != ptr);
+        PtrType oldPtr = m_ptr;
+        m_ptr = ptr;
+        deleteOwnedPtr(oldPtr);
     }
+#endif
 
-    template <typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
+    template<typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o)
     {
-        T* ptr = m_ptr;
-        m_ptr = o.release();
+        PtrType ptr = m_ptr;
+        m_ptr = o.leakPtr();
         ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
+        deleteOwnedPtr(ptr);
         return *this;
     }
 
-    template <typename T> template <typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
+    template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o)
     {
-        T* ptr = m_ptr;
-        m_ptr = o.release();
+        PtrType ptr = m_ptr;
+        m_ptr = o.leakPtr();
         ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
+        deleteOwnedPtr(ptr);
         return *this;
     }
 
-    template <typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
+    template<typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b)
     {
         a.swap(b);
     }
 
-    template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b)
     {
         return a.get() == b; 
     }
 
-    template <typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b) 
     {
         return a == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b)
     {
         return a.get() != b; 
     }
 
-    template <typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
+    template<typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b)
     {
         return a != b.get(); 
     }
 
-    template <typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
+    template<typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p)
     {
         return p.get();
     }
index c59fdc51e4cd21a2e5c672d12123261d6f049545..19256eabc372621732174f50285715163483b49c 100644 (file)
@@ -41,9 +41,13 @@ typedef struct HRGN__* HRGN;
 #if PLATFORM(BREWMP)
 // Forward delcarations at this point avoid the need to include BREW includes
 // in WTF headers.
+typedef struct _ISocket ISocket;
 typedef struct _IFileMgr IFileMgr;
 typedef struct _IFile IFile;
 typedef struct IBitmap IBitmap;
+typedef struct ISSL ISSL;
+typedef struct IMemGroup IMemGroup;
+typedef struct IMemSpace IMemSpace;
 #endif
 
 namespace WTF {
@@ -69,6 +73,10 @@ namespace WTF {
     void deleteOwnedPtr(IFileMgr*);
     void deleteOwnedPtr(IFile*);
     void deleteOwnedPtr(IBitmap*);
+    void deleteOwnedPtr(ISSL*);
+    void deleteOwnedPtr(ISocket*);
+    void deleteOwnedPtr(IMemGroup*);
+    void deleteOwnedPtr(IMemSpace*);
 #endif
 
 } // namespace WTF
diff --git a/wtf/PageAllocation.h b/wtf/PageAllocation.h
new file mode 100644 (file)
index 0000000..ff6f195
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 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 PageAllocation_h
+#define PageAllocation_h
+
+#include <wtf/Assertions.h>
+#include <wtf/OSAllocator.h>
+#include <wtf/PageBlock.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/VMTags.h>
+#include <algorithm>
+
+#if OS(DARWIN)
+#include <mach/mach_init.h>
+#include <mach/vm_map.h>
+#endif
+
+#if OS(HAIKU)
+#include <OS.h>
+#endif
+
+#if OS(WINDOWS)
+#include <malloc.h>
+#include <windows.h>
+#endif
+
+#if OS(SYMBIAN)
+#include <e32hal.h>
+#include <e32std.h>
+#endif
+
+#if HAVE(ERRNO_H)
+#include <errno.h>
+#endif
+
+#if HAVE(MMAP)
+#include <sys/mman.h>
+#include <unistd.h>
+#endif
+
+namespace WTF {
+
+/*
+    PageAllocation
+
+    The PageAllocation class provides a cross-platform memory allocation interface
+    with similar capabilities to posix mmap/munmap.  Memory is allocated by calling
+    PageAllocation::allocate, and deallocated by calling deallocate on the
+    PageAllocation object.  The PageAllocation holds the allocation's base pointer
+    and size.
+
+    The allocate method is passed the size required (which must be a multiple of
+    the system page size, which can be accessed using PageAllocation::pageSize).
+    Callers may also optinally provide a flag indicating the usage (for use by
+    system memory usage tracking tools, where implemented), and boolean values
+    specifying the required protection (defaulting to writable, non-executable).
+*/
+
+class PageAllocation : private PageBlock {
+public:
+    PageAllocation()
+    {
+    }
+
+    using PageBlock::size;
+    using PageBlock::base;
+
+#ifndef __clang__
+    using PageBlock::operator bool;
+#else
+    // FIXME: This is a workaround for <rdar://problem/8876150>, wherein Clang incorrectly emits an access
+    // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool".
+    operator bool() const { return PageBlock::operator bool(); }
+#endif
+
+    static PageAllocation allocate(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
+    {
+        ASSERT(isPageAligned(size));
+        return PageAllocation(OSAllocator::reserveAndCommit(size, usage, writable, executable), size);
+    }
+
+    void deallocate()
+    {
+        // Clear base & size before calling release; if this is *inside* allocation
+        // then we won't be able to clear then after deallocating the memory.
+        PageAllocation tmp;
+        std::swap(tmp, *this);
+
+        ASSERT(tmp);
+        ASSERT(!*this);
+
+        OSAllocator::decommitAndRelease(tmp.base(), tmp.size());
+    }
+
+private:
+    PageAllocation(void* base, size_t size)
+        : PageBlock(base, size, false)
+    {
+    }
+};
+
+} // namespace WTF
+
+using WTF::PageAllocation;
+
+#endif // PageAllocation_h
diff --git a/wtf/PageAllocationAligned.cpp b/wtf/PageAllocationAligned.cpp
new file mode 100644 (file)
index 0000000..6f54710
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "PageAllocationAligned.h"
+
+namespace WTF {
+
+PageAllocationAligned PageAllocationAligned::allocate(size_t size, size_t alignment, OSAllocator::Usage usage, bool writable, bool executable)
+{
+    ASSERT(isPageAligned(size));
+    ASSERT(isPageAligned(alignment));
+    ASSERT(isPowerOfTwo(alignment));
+    ASSERT(size >= alignment);
+    size_t alignmentMask = alignment - 1;
+
+#if OS(DARWIN)
+    int flags = VM_FLAGS_ANYWHERE;
+    if (usage != OSAllocator::UnknownUsage)
+        flags |= usage;
+    int protection = PROT_READ;
+    if (writable)
+        protection |= PROT_WRITE;
+    if (executable)
+        protection |= PROT_EXEC;
+
+    vm_address_t address = 0;
+    vm_map(current_task(), &address, size, alignmentMask, flags, MEMORY_OBJECT_NULL, 0, FALSE, protection, PROT_READ | PROT_WRITE | PROT_EXEC, VM_INHERIT_DEFAULT);
+    return PageAllocationAligned(reinterpret_cast<void*>(address), size);
+#else
+    size_t alignmentDelta = alignment - pageSize();
+
+    // Resererve with suffcient additional VM to correctly align.
+    size_t reservationSize = size + alignmentDelta;
+    void* reservationBase = OSAllocator::reserveUncommitted(reservationSize, usage, writable, executable);
+
+    // Select an aligned region within the reservation and commit.
+    void* alignedBase = reinterpret_cast<uintptr_t>(reservationBase) & alignmentMask
+        ? reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(reservationBase) & ~alignmentMask) + alignment)
+        : reservationBase;
+    OSAllocator::commit(alignedBase, size, writable, executable);
+
+    return PageAllocationAligned(alignedBase, size, reservationBase, reservationSize);
+#endif
+}
+
+void PageAllocationAligned::deallocate()
+{
+    // Clear base & size before calling release; if this is *inside* allocation
+    // then we won't be able to clear then after deallocating the memory.
+    PageAllocationAligned tmp;
+    std::swap(tmp, *this);
+
+    ASSERT(tmp);
+    ASSERT(!*this);
+
+#if OS(DARWIN)
+    vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(tmp.base()), tmp.size());
+#else
+    ASSERT(tmp.m_reservation.contains(tmp.base(), tmp.size()));
+    OSAllocator::decommitAndRelease(tmp.m_reservation.base(), tmp.m_reservation.size(), tmp.base(), tmp.size());
+#endif
+}
+
+} // namespace WTF
diff --git a/wtf/PageAllocationAligned.h b/wtf/PageAllocationAligned.h
new file mode 100644 (file)
index 0000000..c018dab
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 PageAllocationAligned_h
+#define PageAllocationAligned_h
+
+#include <wtf/OSAllocator.h>
+#include <wtf/PageReservation.h>
+
+namespace WTF {
+
+class PageAllocationAligned : private PageBlock {
+public:
+    PageAllocationAligned()
+    {
+    }
+
+    using PageBlock::operator bool;
+    using PageBlock::size;
+    using PageBlock::base;
+
+    static PageAllocationAligned allocate(size_t size, size_t alignment, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false);
+
+    void deallocate();
+
+private:
+#if OS(DARWIN)
+    PageAllocationAligned(void* base, size_t size)
+        : PageBlock(base, size, false)
+    {
+    }
+#else
+    PageAllocationAligned(void* base, size_t size, void* reservationBase, size_t reservationSize)
+        : PageBlock(base, size, false)
+        , m_reservation(reservationBase, reservationSize, false)
+    {
+    }
+
+    PageBlock m_reservation;
+#endif
+};
+
+
+} // namespace WTF
+
+using WTF::PageAllocationAligned;
+
+#endif // PageAllocationAligned_h
diff --git a/wtf/PageAllocatorSymbian.h b/wtf/PageAllocatorSymbian.h
new file mode 100644 (file)
index 0000000..eba5b03
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
+ *
+ * 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 PageAllocatorSymbian_h
+#define PageAllocatorSymbian_h
+
+#include <e32std.h>
+#include <wtf/Bitmap.h>
+
+namespace WTF { 
+
+size_t pageSize();
+
+// Convenience wrapper around an RChunk
+class SymbianChunk : public RChunk {
+   
+public:   
+    SymbianChunk(TInt handle) 
+    {
+        SetHandle(handle);
+        // prevent kernel calls by caching these
+        m_base = reinterpret_cast<char*>(Base()); 
+        m_maxSize = MaxSize();
+    }
+    
+    ~SymbianChunk() 
+    { 
+        Decommit(0, m_maxSize);
+        Close();
+    }
+     
+    // checks if address is in chunk's virtual address space
+    bool contains(const void* address) const 
+    {
+        return (static_cast<const char*>(address) >= m_base && static_cast<const char*>(address) < (m_base + m_maxSize));  
+    }
+    
+    char* m_base; 
+    size_t m_maxSize; 
+    
+};
+
+// Size of the large up-front reservation
+#if defined(__WINS__) 
+// Emulator has limited virtual address space
+const size_t largeReservationSize = 96*1024*1024;
+#else
+// HW has plenty of virtual addresses
+const size_t largeReservationSize = 256*1024*1024;
+#endif
+
+class PageAllocatorSymbian { 
+
+public:     
+    PageAllocatorSymbian();
+    ~PageAllocatorSymbian();
+    
+    void* reserve(size_t);
+    void release(void*, size_t);
+    bool commit(void*, size_t);
+    bool decommit(void*, size_t);
+    
+    bool contains(const void*) const; 
+    
+private:     
+    static const size_t m_pageSize = 4096; 
+    SymbianChunk* m_chunk; 
+    Bitmap<largeReservationSize / m_pageSize> m_map;
+    
+};
+
+} // namespace WTF
+
+#endif // PageAllocatorSymbian_h
+
diff --git a/wtf/PageBlock.cpp b/wtf/PageBlock.cpp
new file mode 100644 (file)
index 0000000..6fb68e5
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#include "config.h"
+#include "PageBlock.h"
+
+#if OS(UNIX) && !OS(SYMBIAN)
+#include <unistd.h>
+#endif
+
+#if OS(WINDOWS)
+#include <malloc.h>
+#include <windows.h>
+#endif
+
+#if OS(SYMBIAN)
+#include <e32hal.h>
+#include <e32std.h>
+#endif
+
+namespace WTF {
+
+static size_t s_pageSize;
+
+#if OS(UNIX) && !OS(SYMBIAN)
+
+inline size_t systemPageSize()
+{
+    return getpagesize();
+}
+
+#elif OS(WINDOWS)
+
+inline size_t systemPageSize()
+{
+    static size_t size = 0;
+    SYSTEM_INFO system_info;
+    GetSystemInfo(&system_info);
+    size = system_info.dwPageSize;
+    return size;
+}
+
+#elif OS(SYMBIAN)
+
+inline size_t systemPageSize()
+{
+    static TInt page_size = 0;
+    UserHal::PageSizeInBytes(page_size);
+    return page_size;
+}
+
+#endif
+
+size_t pageSize()
+{
+    if (!s_pageSize)
+        s_pageSize = systemPageSize();
+    ASSERT(isPowerOfTwo(s_pageSize));
+    return s_pageSize;
+}
+
+} // namespace WTF
diff --git a/wtf/PageBlock.h b/wtf/PageBlock.h
new file mode 100644 (file)
index 0000000..e17c546
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 PageBlock_h
+#define PageBlock_h
+
+namespace WTF {
+
+size_t pageSize();
+inline bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); }
+inline bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); }
+inline bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); }
+
+class PageBlock {
+public:
+    PageBlock();
+    PageBlock(const PageBlock&);
+    PageBlock(void*, size_t, bool hasGuardPages);
+    
+    void* base() const { return m_base; }
+    size_t size() const { return m_size; }
+
+    operator bool() const { return !!m_realBase; }
+
+    bool contains(void* containedBase, size_t containedSize)
+    {
+        return containedBase >= m_base
+            && (static_cast<char*>(containedBase) + containedSize) <= (static_cast<char*>(m_base) + m_size);
+    }
+
+private:
+    void* m_realBase;
+    void* m_base;
+    size_t m_size;
+};
+
+inline PageBlock::PageBlock()
+    : m_realBase(0)
+    , m_base(0)
+    , m_size(0)
+{
+}
+
+inline PageBlock::PageBlock(const PageBlock& other)
+    : m_realBase(other.m_realBase)
+    , m_base(other.m_base)
+    , m_size(other.m_size)
+{
+}
+
+inline PageBlock::PageBlock(void* base, size_t size, bool hasGuardPages)
+    : m_realBase(base)
+    , m_base(static_cast<char*>(base) + ((base && hasGuardPages) ? pageSize() : 0))
+    , m_size(size)
+{
+}
+
+} // namespace WTF
+
+using WTF::pageSize;
+using WTF::isPageAligned;
+using WTF::isPageAligned;
+using WTF::isPowerOfTwo;
+
+#endif // PageBlock_h
diff --git a/wtf/PageReservation.h b/wtf/PageReservation.h
new file mode 100644 (file)
index 0000000..77783eb
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2010 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 PageReservation_h
+#define PageReservation_h
+
+#include <wtf/PageAllocation.h>
+
+namespace WTF {
+
+/*
+    PageReservation
+
+    Like PageAllocation, the PageReservation class provides a cross-platform memory
+    allocation interface, but with a set of capabilities more similar to that of
+    VirtualAlloc than posix mmap.  PageReservation can be used to allocate virtual
+    memory without committing physical memory pages using PageReservation::reserve.
+    Following a call to reserve all memory in the region is in a decommited state,
+    in which the memory should not be used (accessing the memory may cause a fault).
+
+    Before using memory it must be committed by calling commit, which is passed start
+    and size values (both of which require system page size granularity).  One the
+    committed memory is no longer needed 'decommit' may be called to return the
+    memory to its devommitted state.  Commit should only be called on memory that is
+    currently decommitted, and decommit should only be called on memory regions that
+    are currently committed.  All memory should be decommited before the reservation
+    is deallocated.  Values in memory may not be retained accross a pair of calls if
+    the region of memory is decommitted and then committed again.
+
+    Memory protection should not be changed on decommitted memory, and if protection
+    is changed on memory while it is committed it should be returned to the orignal
+    protection before decommit is called.
+*/
+
+class PageReservation : private PageBlock {
+public:
+    PageReservation()
+        : m_committed(0)
+        , m_writable(false)
+        , m_executable(false)
+    {
+    }
+
+    using PageBlock::base;
+    using PageBlock::size;
+
+#ifndef __clang__
+    using PageBlock::operator bool;
+#else
+    // FIXME: This is a workaround for <rdar://problem/8876150>, wherein Clang incorrectly emits an access
+    // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool".
+    operator bool() const { return PageBlock::operator bool(); }
+#endif
+
+    void commit(void* start, size_t size)
+    {
+        ASSERT(*this);
+        ASSERT(isPageAligned(start));
+        ASSERT(isPageAligned(size));
+        ASSERT(contains(start, size));
+
+        m_committed += size;
+        OSAllocator::commit(start, size, m_writable, m_executable);
+    }
+
+    void decommit(void* start, size_t size)
+    {
+        ASSERT(*this);
+        ASSERT(isPageAligned(start));
+        ASSERT(isPageAligned(size));
+        ASSERT(contains(start, size));
+
+        m_committed -= size;
+        OSAllocator::decommit(start, size);
+    }
+
+    size_t committed()
+    {
+        return m_committed;
+    }
+
+    static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
+    {
+        ASSERT(isPageAligned(size));
+        return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false);
+    }
+    
+    static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
+    {
+        ASSERT(isPageAligned(size));
+        return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true);
+    }
+
+    void deallocate()
+    {
+        ASSERT(!m_committed);
+
+        // Clear base & size before calling release; if this is *inside* allocation
+        // then we won't be able to clear then after deallocating the memory.
+        PageReservation tmp;
+        std::swap(tmp, *this);
+
+        ASSERT(tmp);
+        ASSERT(!*this);
+
+        OSAllocator::releaseDecommitted(tmp.base(), tmp.size());
+    }
+
+private:
+    PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages)
+        : PageBlock(base, size, hasGuardPages)
+        , m_committed(0)
+        , m_writable(writable)
+        , m_executable(executable)
+    {
+    }
+
+    size_t m_committed;
+    bool m_writable;
+    bool m_executable;
+};
+
+}
+
+using WTF::PageReservation;
+
+#endif // PageReservation_h
diff --git a/wtf/ParallelJobs.h b/wtf/ParallelJobs.h
new file mode 100644 (file)
index 0000000..2e0524d
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Gabor Loki <loki@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobs_h
+#define ParallelJobs_h
+
+#include "Assertions.h"
+#include "Noncopyable.h"
+#include "RefPtr.h"
+#include <wtf/Vector.h>
+
+#if ENABLE(PARALLEL_JOBS)
+
+// Usage:
+//
+// #if ENABLE(PARALLEL_JOBS)
+//
+//     // Initialize parallel jobs
+//     ParallelJobs<TypeOfParameter> parallelJobs(&worker [, requestedNumberOfJobs]);
+//
+//     // Fill the parameter array
+//     for(i = 0; i < parallelJobs.numberOfJobs(); ++i) {
+//       TypeOfParameter& params = parallelJobs.parameter(i);
+//       params.attr1 = localVars ...
+//       ...
+//     }
+//
+//     // Execute parallel jobs
+//     parallelJobs.execute();
+//
+// #else
+//
+//     inlineFunction(args...);
+//
+// #endif // ENABLE(PARALLEL_JOBS)
+
+#if ENABLE(THREADING_GENERIC)
+#include "ParallelJobsGeneric.h"
+
+#elif ENABLE(THREADING_OPENMP)
+#include "ParallelJobsOpenMP.h"
+
+#elif ENABLE(THREADING_LIBDISPATCH)
+#include "ParallelJobsLibdispatch.h"
+
+#else
+#error "No parallel processing API for ParallelJobs"
+
+#endif
+
+namespace WTF {
+
+template<typename Type>
+class ParallelJobs {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    typedef void (*WorkerFunction)(Type*);
+
+    ParallelJobs(WorkerFunction func, int requestedJobNumber = 0) :
+        m_parallelEnvironment(reinterpret_cast<ParallelEnvironment::ThreadFunction>(func), sizeof(Type), requestedJobNumber)
+    {
+        m_parameters.grow(m_parallelEnvironment.numberOfJobs());
+        ASSERT(numberOfJobs() == m_parameters.size());
+    }
+
+    size_t numberOfJobs()
+    {
+        return m_parameters.size();
+    }
+
+    Type& parameter(size_t i)
+    {
+        return m_parameters[i];
+    }
+
+    void execute()
+    {
+        m_parallelEnvironment.execute(reinterpret_cast<unsigned char*>(m_parameters.data()));
+    }
+
+private:
+    ParallelEnvironment m_parallelEnvironment;
+    Vector<Type> m_parameters;
+};
+
+} // namespace WTF
+
+using WTF::ParallelJobs;
+
+#endif // ENABLE(PARALLEL_JOBS)
+
+#endif // ParallelJobs_h
diff --git a/wtf/ParallelJobsGeneric.cpp b/wtf/ParallelJobsGeneric.cpp
new file mode 100644 (file)
index 0000000..e241b83
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Gabor Loki <loki@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(PARALLEL_JOBS) && ENABLE(THREADING_GENERIC)
+
+#include "ParallelJobs.h"
+
+namespace WTF {
+
+Vector< RefPtr<ParallelEnvironment::ThreadPrivate> >* ParallelEnvironment::s_threadPool = 0;
+
+bool ParallelEnvironment::ThreadPrivate::tryLockFor(ParallelEnvironment* parent)
+{
+    bool locked = m_mutex.tryLock();
+
+    if (!locked)
+        return false;
+
+    if (m_parent) {
+        m_mutex.unlock();
+        return false;
+    }
+
+    if (!m_threadID)
+        m_threadID = createThread(&ParallelEnvironment::ThreadPrivate::workerThread, this, "Parallel worker");
+
+    if (m_threadID)
+        m_parent = parent;
+
+    m_mutex.unlock();
+    return m_threadID;
+}
+
+void ParallelEnvironment::ThreadPrivate::execute(ThreadFunction threadFunction, void* parameters)
+{
+    MutexLocker lock(m_mutex);
+
+    m_threadFunction = threadFunction;
+    m_parameters = parameters;
+    m_running = true;
+    m_threadCondition.signal();
+}
+
+void ParallelEnvironment::ThreadPrivate::waitForFinish()
+{
+    MutexLocker lock(m_mutex);
+
+    while (m_running)
+        m_threadCondition.wait(m_mutex);
+}
+
+void* ParallelEnvironment::ThreadPrivate::workerThread(void* threadData)
+{
+    ThreadPrivate* sharedThread = reinterpret_cast<ThreadPrivate*>(threadData);
+    MutexLocker lock(sharedThread->m_mutex);
+
+    while (sharedThread->m_threadID) {
+        if (sharedThread->m_running) {
+            (*sharedThread->m_threadFunction)(sharedThread->m_parameters);
+            sharedThread->m_running = false;
+            sharedThread->m_parent = 0;
+            sharedThread->m_threadCondition.signal();
+        }
+
+        sharedThread->m_threadCondition.wait(sharedThread->m_mutex);
+    }
+    return 0;
+}
+
+} // namespace WTF
+
+#endif // ENABLE(PARALLEL_JOBS) && ENABLE(THREADING_GENERIC)
diff --git a/wtf/ParallelJobsGeneric.h b/wtf/ParallelJobsGeneric.h
new file mode 100644 (file)
index 0000000..2aa44d5
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Gabor Loki <loki@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsGeneric_h
+#define ParallelJobsGeneric_h
+
+#if ENABLE(THREADING_GENERIC)
+
+#include <wtf/RefCounted.h>
+#include <wtf/Threading.h>
+
+namespace WTF {
+
+static const unsigned int maxParallelThreads = 2;
+
+class ParallelEnvironment {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    typedef void (*ThreadFunction)(void*);
+
+    ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, unsigned int requestedJobNumber) :
+        m_threadFunction(threadFunction),
+        m_sizeOfParameter(sizeOfParameter)
+    {
+        if (!requestedJobNumber || requestedJobNumber > maxParallelThreads)
+            requestedJobNumber = maxParallelThreads;
+
+        if (!s_threadPool)
+            s_threadPool = new Vector< RefPtr<ThreadPrivate> >();
+
+        // The main thread should be also a worker.
+        unsigned int maxNewThreads = requestedJobNumber - 1;
+
+        for (unsigned int i = 0; i < maxParallelThreads && m_threads.size() < maxNewThreads; ++i) {
+            if (s_threadPool->size() < i + 1)
+                s_threadPool->append(ThreadPrivate::create());
+
+            if ((*s_threadPool)[i]->tryLockFor(this))
+                m_threads.append((*s_threadPool)[i]);
+        }
+
+        m_numberOfJobs = m_threads.size() + 1;
+    }
+
+    int numberOfJobs()
+    {
+        return m_numberOfJobs;
+    }
+
+    void execute(unsigned char* parameters)
+    {
+        size_t i;
+        for (i = 0; i < m_threads.size(); ++i) {
+            m_threads[i]->execute(m_threadFunction, parameters);
+            parameters += m_sizeOfParameter;
+        }
+
+        // The work for the main thread
+        (*m_threadFunction)(parameters);
+
+        // Wait until all jobs are done.
+        for (i = 0; i < m_threads.size(); ++i)
+            m_threads[i]->waitForFinish();
+    }
+
+    class ThreadPrivate : public RefCounted<ThreadPrivate> {
+    public:
+        ThreadPrivate()
+            : m_threadID(0)
+            , m_running(false)
+            , m_parent(0)
+        {
+        }
+
+        bool tryLockFor(ParallelEnvironment*);
+
+        void execute(ThreadFunction, void*);
+
+        void waitForFinish();
+
+        static PassRefPtr<ThreadPrivate> create()
+        {
+            return adoptRef(new ThreadPrivate());
+        }
+
+        static void* workerThread(void*);
+
+    private:
+        ThreadIdentifier m_threadID;
+        bool m_running;
+        ParallelEnvironment* m_parent;
+
+        mutable Mutex m_mutex;
+        ThreadCondition m_threadCondition;
+
+        ThreadFunction m_threadFunction;
+        void* m_parameters;
+    };
+
+private:
+    ThreadFunction m_threadFunction;
+    size_t m_sizeOfParameter;
+    int m_numberOfJobs;
+
+    Vector< RefPtr<ThreadPrivate> > m_threads;
+    static Vector< RefPtr<ThreadPrivate> >* s_threadPool;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(THREADING_GENERIC)
+
+
+#endif // ParallelJobsGeneric_h
diff --git a/wtf/ParallelJobsLibdispatch.h b/wtf/ParallelJobsLibdispatch.h
new file mode 100644 (file)
index 0000000..687c771
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Gabor Loki <loki@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsLibdispatch_h
+#define ParallelJobsLibdispatch_h
+
+#if ENABLE(THREADING_LIBDISPATCH)
+
+#include <dispatch/dispatch.h>
+
+namespace WTF {
+
+static const int maxParallelThreads = 2;
+
+class ParallelEnvironment {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    typedef void (*ThreadFunction)(void*);
+
+    ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) :
+        m_threadFunction(threadFunction),
+        m_sizeOfParameter(sizeOfParameter)
+    {
+        if (!requestedJobNumber || requestedJobNumber > maxParallelThreads)
+            requestedJobNumber = maxParallelThreads;
+
+        ASSERT(requestedJobNumber > 0);
+
+        m_numberOfJobs = requestedJobNumber;
+    }
+
+    int numberOfJobs()
+    {
+        return m_numberOfJobs;
+    }
+
+    void execute(unsigned char* parameters)
+    {
+        // libdispatch is NOT supported inside a template
+        dispatch_queue_t parallelJobsQueue = dispatch_queue_create("ParallelJobs", 0);
+
+        for (int i = 0; i < m_numberOfJobs - 1; ++i) {
+            dispatch_async(parallelJobsQueue, ^{(*m_threadFunction)(parameters);});
+            parameters += m_sizeOfParameter;
+        }
+
+        // The work for the main thread. Wait until all jobs are done.
+        dispatch_sync(parallelJobsQueue, ^{(*m_threadFunction)(parameters);});
+    }
+
+private:
+    ThreadFunction m_threadFunction;
+    size_t m_sizeOfParameter;
+    int m_numberOfJobs;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(THREADING_LIBDISPATCH)
+
+#endif // ParallelJobsLibdispatch_h
diff --git a/wtf/ParallelJobsOpenMP.h b/wtf/ParallelJobsOpenMP.h
new file mode 100644 (file)
index 0000000..706bd80
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Gabor Loki <loki@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsOpenMP_h
+#define ParallelJobsOpenMP_h
+
+#if ENABLE(THREADING_OPENMP)
+
+#include <omp.h>
+
+namespace WTF {
+
+class ParallelEnvironment {
+    WTF_MAKE_NONCOPYABLE(ParallelEnvironment);
+public:
+    typedef void (*ThreadFunction)(void*);
+
+    ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) :
+        m_threadFunction(threadFunction),
+        m_sizeOfParameter(sizeOfParameter)
+    {
+        int maxNumberOfThreads = omp_get_max_threads();
+
+        if (!requestedJobNumber || requestedJobNumber > maxNumberOfThreads)
+            requestedJobNumber = maxNumberOfThreads;
+
+        ASSERT(requestedJobNumber > 0);
+
+        m_numberOfJobs = requestedJobNumber;
+
+    }
+
+    int numberOfJobs()
+    {
+        return m_numberOfJobs;
+    }
+
+    void execute(unsigned char* parameters)
+    {
+        omp_set_num_threads(m_numberOfJobs);
+
+#pragma omp parallel for
+        for (int i = 0; i < m_numberOfJobs; ++i)
+            (*m_threadFunction)(parameters + i * m_sizeOfParameter);
+    }
+
+private:
+    ThreadFunction m_threadFunction;
+    size_t m_sizeOfParameter;
+    int m_numberOfJobs;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(THREADING_OPENMP)
+
+#endif // ParallelJobsOpenMP_h
diff --git a/wtf/PassOwnArrayPtr.h b/wtf/PassOwnArrayPtr.h
new file mode 100644 (file)
index 0000000..3f30924
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2010 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 WTF_PassOwnArrayPtr_h
+#define WTF_PassOwnArrayPtr_h
+
+#include "Assertions.h"
+#include "NullPtr.h"
+#include "TypeTraits.h"
+
+namespace WTF {
+
+template<typename T> class OwnArrayPtr;
+template<typename T> class PassOwnArrayPtr;
+template<typename T> PassOwnArrayPtr<T> adoptArrayPtr(T*);
+template<typename T> void deleteOwnedArrayPtr(T* ptr);
+
+template<typename T> class PassOwnArrayPtr {
+public:
+    typedef T* PtrType;
+
+    PassOwnArrayPtr() : m_ptr(0) { }
+
+#if !defined(LOOSE_PASS_OWN_PTR) || !HAVE(NULLPTR)
+    PassOwnArrayPtr(std::nullptr_t) : m_ptr(0) { }
+#endif
+
+    // It somewhat breaks the type system to allow transfer of ownership out of
+    // a const PassOwnArrayPtr. However, it makes it much easier to work with PassOwnArrayPtr
+    // temporaries, and we don't have a need to use real const PassOwnArrayPtrs anyway.
+    PassOwnArrayPtr(const PassOwnArrayPtr& o) : m_ptr(o.leakPtr()) { }
+    template<typename U> PassOwnArrayPtr(const PassOwnArrayPtr<U>& o) : m_ptr(o.leakPtr()) { }
+
+    ~PassOwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); }
+
+    PtrType get() const { return m_ptr; }
+
+    void clear();
+    PtrType leakPtr() const WARN_UNUSED_RETURN;
+
+    T& operator*() const { ASSERT(m_ptr); return *m_ptr; }
+    PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
+
+    bool operator!() const { return !m_ptr; }
+
+    // This conversion operator allows implicit conversion to bool but not to other integer types.
+#if COMPILER(WINSCW)
+    operator bool() const { return m_ptr; }
+#else
+    typedef PtrType PassOwnArrayPtr::*UnspecifiedBoolType;
+    operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnArrayPtr::m_ptr : 0; }
+#endif
+
+    PassOwnArrayPtr& operator=(const PassOwnArrayPtr<T>&);
+#if !defined(LOOSE_PASS_OWN_ARRAY_PTR) || !HAVE(NULLPTR)
+    PassOwnArrayPtr& operator=(std::nullptr_t) { clear(); return *this; }
+#endif
+    template<typename U> PassOwnArrayPtr& operator=(const PassOwnArrayPtr<U>&);
+
+    template<typename U> friend PassOwnArrayPtr<U> adoptArrayPtr(U*);
+
+#ifdef LOOSE_PASS_OWN_ARRAY_PTR
+    PassOwnArrayPtr(PtrType ptr) : m_ptr(ptr) { }
+    PassOwnArrayPtr& operator=(PtrType);
+#endif
+
+private:
+#ifndef LOOSE_PASS_OWN_ARRAY_PTR
+    explicit PassOwnArrayPtr(PtrType ptr) : m_ptr(ptr) { }
+#endif
+
+    mutable PtrType m_ptr;
+};
+
+template<typename T> inline void PassOwnArrayPtr<T>::clear()
+{
+    PtrType ptr = m_ptr;
+    m_ptr = 0;
+    deleteOwnedArrayPtr(ptr);
+}
+
+template<typename T> inline typename PassOwnArrayPtr<T>::PtrType PassOwnArrayPtr<T>::leakPtr() const
+{
+    PtrType ptr = m_ptr;
+    m_ptr = 0;
+    return ptr;
+}
+
+#ifdef LOOSE_PASS_OWN_ARRAY_PTR
+template<typename T> inline PassOwnArrayPtr<T>& PassOwnArrayPtr<T>::operator=(PtrType optr)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = optr;
+    ASSERT(!ptr || m_ptr != ptr);
+    if (ptr)
+        deleteOwnedArrayPtr(ptr);
+    return *this;
+}
+#endif
+
+template<typename T> inline PassOwnArrayPtr<T>& PassOwnArrayPtr<T>::operator=(const PassOwnArrayPtr<T>& optr)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = optr.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    if (ptr)
+        deleteOwnedArrayPtr(ptr);
+    return *this;
+}
+
+template<typename T> template<typename U> inline PassOwnArrayPtr<T>& PassOwnArrayPtr<T>::operator=(const PassOwnArrayPtr<U>& optr)
+{
+    PtrType ptr = m_ptr;
+    m_ptr = optr.leakPtr();
+    ASSERT(!ptr || m_ptr != ptr);
+    if (ptr)
+        deleteOwnedArrayPtr(ptr);
+    return *this;
+}
+
+template<typename T, typename U> inline bool operator==(const PassOwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) 
+{
+    return a.get() == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator==(const PassOwnArrayPtr<T>& a, const OwnArrayPtr<U>& b) 
+{
+    return a.get() == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator==(const OwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) 
+{
+    return a.get() == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator==(const PassOwnArrayPtr<T>& a, U* b) 
+{
+    return a.get() == b; 
+}
+
+template<typename T, typename U> inline bool operator==(T* a, const PassOwnArrayPtr<U>& b) 
+{
+    return a == b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const PassOwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) 
+{
+    return a.get() != b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const PassOwnArrayPtr<T>& a, const OwnArrayPtr<U>& b) 
+{
+    return a.get() != b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const OwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) 
+{
+    return a.get() != b.get(); 
+}
+
+template<typename T, typename U> inline bool operator!=(const PassOwnArrayPtr<T>& a, U* b)
+{
+    return a.get() != b; 
+}
+
+template<typename T, typename U> inline bool operator!=(T* a, const PassOwnArrayPtr<U>& b) 
+{
+    return a != b.get(); 
+}
+
+template<typename T> inline PassOwnArrayPtr<T> adoptArrayPtr(T* ptr)
+{
+    return PassOwnArrayPtr<T>(ptr);
+}
+
+template<typename T> inline void deleteOwnedArrayPtr(T* ptr)
+{
+    typedef char known[sizeof(T) ? 1 : -1];
+    if (sizeof(known))
+        delete [] ptr;
+}
+
+template<typename T, typename U> inline PassOwnArrayPtr<T> static_pointer_cast(const PassOwnArrayPtr<U>& p) 
+{
+    return adoptArrayPtr(static_cast<T*>(p.leakPtr()));
+}
+
+template<typename T, typename U> inline PassOwnArrayPtr<T> const_pointer_cast(const PassOwnArrayPtr<U>& p) 
+{
+    return adoptArrayPtr(const_cast<T*>(p.leakPtr()));
+}
+
+template<typename T> inline T* getPtr(const PassOwnArrayPtr<T>& p)
+{
+    return p.get();
+}
+
+} // namespace WTF
+
+using WTF::PassOwnArrayPtr;
+using WTF::adoptArrayPtr;
+using WTF::const_pointer_cast;
+using WTF::static_pointer_cast;
+
+#endif // WTF_PassOwnArrayPtr_h
index ae7045786329cebced2a26676b6707e9e8b0cf77..3635f3c665377f86ad1c1536b9f075380b5fbc6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #define WTF_PassOwnPtr_h
 
 #include "Assertions.h"
+#include "NullPtr.h"
 #include "OwnPtrCommon.h"
 #include "TypeTraits.h"
 
+#if !PLATFORM(CHROMIUM) && !PLATFORM(WIN) && !PLATFORM(MAC) && !PLATFORM(QT)
+// Remove this once we make all WebKit code compatible with stricter rules about PassOwnPtr.
+#define LOOSE_PASS_OWN_PTR
+#endif
+
 namespace WTF {
 
     // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type.
 
-    template <typename T> class OwnPtr;
+    template<typename T> class OwnPtr;
+    template<typename T> class PassOwnPtr;
+    template<typename T> PassOwnPtr<T> adoptPtr(T*);
 
-    template <typename T> class PassOwnPtr {
+    template<typename T> class PassOwnPtr {
     public:
         typedef typename RemovePointer<T>::Type ValueType;
         typedef ValueType* PtrType;
 
-        PassOwnPtr(PtrType ptr = 0) : m_ptr(ptr) { }
+        PassOwnPtr() : m_ptr(0) { }
+        PassOwnPtr(std::nullptr_t) : m_ptr(0) { }
+
         // It somewhat breaks the type system to allow transfer of ownership out of
         // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr
-        // temporaries, and we don't really have a need to use real const PassOwnPtrs 
-        // anyway.
-        PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.release()) { }
-        template <typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.release()) { }
+        // temporaries, and we don't have a need to use real const PassOwnPtrs anyway.
+        PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { }
+        template<typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.leakPtr()) { }
 
         ~PassOwnPtr() { deleteOwnedPtr(m_ptr); }
 
         PtrType get() const { return m_ptr; }
 
-        void clear() { m_ptr = 0; }
-        PtrType release() const { PtrType ptr = m_ptr; m_ptr = 0; return ptr; }
+        void clear();
+        PtrType leakPtr() const WARN_UNUSED_RETURN;
 
         ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
         PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
@@ -65,105 +74,146 @@ namespace WTF {
         typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
         operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
 
-        PassOwnPtr& operator=(T*);
         PassOwnPtr& operator=(const PassOwnPtr<T>&);
-        template <typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
+#if !defined(LOOSE_PASS_OWN_PTR) || !HAVE(NULLPTR)
+        PassOwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
+#endif
+        template<typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
+
+        template<typename U> friend PassOwnPtr<U> adoptPtr(U*);
+
+#ifdef LOOSE_PASS_OWN_PTR
+        PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
+        PassOwnPtr& operator=(PtrType);
+#endif
 
     private:
+#ifndef LOOSE_PASS_OWN_PTR
+        explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
+#endif
+
+        // We should never have two OwnPtrs for the same underlying object (otherwise we'll get
+        // double-destruction), so these equality operators should never be needed.
+        template<typename U> bool operator==(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+        template<typename U> bool operator!=(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+        template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+        template<typename U> bool operator!=(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; }
+
         mutable PtrType m_ptr;
     };
 
-    template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(T* optr)
+    template<typename T> inline void PassOwnPtr<T>::clear()
     {
-        T* ptr = m_ptr;
+        PtrType ptr = m_ptr;
+        m_ptr = 0;
+        deleteOwnedPtr(ptr);
+    }
+
+    template<typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const
+    {
+        PtrType ptr = m_ptr;
+        m_ptr = 0;
+        return ptr;
+    }
+
+#ifdef LOOSE_PASS_OWN_PTR
+    template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(PtrType optr)
+    {
+        PtrType ptr = m_ptr;
         m_ptr = optr;
         ASSERT(!ptr || m_ptr != ptr);
         if (ptr)
             deleteOwnedPtr(ptr);
         return *this;
     }
+#endif
 
-    template <typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
+    template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
     {
-        T* ptr = m_ptr;
-        m_ptr = optr.release();
+        PtrType ptr = m_ptr;
+        m_ptr = optr.leakPtr();
         ASSERT(!ptr || m_ptr != ptr);
         if (ptr)
             deleteOwnedPtr(ptr);
         return *this;
     }
 
-    template <typename T> template <typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
+    template<typename T> template<typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
     {
-        T* ptr = m_ptr;
-        m_ptr = optr.release();
+        PtrType ptr = m_ptr;
+        m_ptr = optr.leakPtr();
         ASSERT(!ptr || m_ptr != ptr);
         if (ptr)
             deleteOwnedPtr(ptr);
         return *this;
     }
 
-    template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) 
     {
         return a.get() == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b) 
     {
         return a.get() == b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b) 
     {
         return a.get() == b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b) 
+    template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b) 
     {
         return a.get() == b; 
     }
     
-    template <typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b) 
     {
         return a == b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) 
     {
         return a.get() != b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b) 
     {
         return a.get() != b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b) 
     {
         return a.get() != b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
     {
         return a.get() != b; 
     }
     
-    template <typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b) 
     {
         return a != b.get(); 
     }
 
-    template <typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p) 
+    template<typename T> inline PassOwnPtr<T> adoptPtr(T* ptr)
+    {
+        return PassOwnPtr<T>(ptr);
+    }
+
+    template<typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p) 
     {
-        return PassOwnPtr<T>(static_cast<T*>(p.release())); 
+        return adoptPtr(static_cast<T*>(p.leakPtr()));
     }
 
-    template <typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p) 
+    template<typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p) 
     {
-        return PassOwnPtr<T>(const_cast<T*>(p.release())); 
+        return adoptPtr(const_cast<T*>(p.leakPtr()));
     }
 
-    template <typename T> inline T* getPtr(const PassOwnPtr<T>& p)
+    template<typename T> inline T* getPtr(const PassOwnPtr<T>& p)
     {
         return p.get();
     }
@@ -171,6 +221,7 @@ namespace WTF {
 } // namespace WTF
 
 using WTF::PassOwnPtr;
+using WTF::adoptPtr;
 using WTF::const_pointer_cast;
 using WTF::static_pointer_cast;
 
index 25a93a4351e084ea7b651aad1e680ba1e83ac62e..7b4af6b66af2f688f0fc251bd04e9bd3f509ec3f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
 #define WTF_PassRefPtr_h
 
 #include "AlwaysInline.h"
+#include "NullPtr.h"
 
 namespace WTF {
 
     template<typename T> class RefPtr;
     template<typename T> class PassRefPtr;
-    template <typename T> PassRefPtr<T> adoptRef(T*);
+    template<typename T> PassRefPtr<T> adoptRef(T*);
 
+    inline void adopted(const void*) { }
 
-    // Remove inline for WINSCW compiler to prevent the compiler agressively resolving
-    // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as
-    // a class member or function arguments before T is defined.
-
-    // [Qt]r57240 broke Qt build (might be a gcc bug)
-    // FIXME! See: https://bugs.webkit.org/show_bug.cgi?id=37253
-    template<typename T>
 #if !COMPILER(WINSCW)
 #if !PLATFORM(QT)
-    ALWAYS_INLINE
+    #define REF_DEREF_INLINE ALWAYS_INLINE
 #else
-    inline
+    // Using ALWAYS_INLINE broke the Qt build. This may be a GCC bug.
+    // See https://bugs.webkit.org/show_bug.cgi?id=37253 for details.
+    #define REF_DEREF_INLINE inline
 #endif
+#else
+    // No inlining for WINSCW compiler to prevent the compiler agressively resolving
+    // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as
+    // a class member or function arguments before T is defined.
+    #define REF_DEREF_INLINE
 #endif
-    void refIfNotNull(T* ptr)
+
+    template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
     {
         if (LIKELY(ptr != 0))
             ptr->ref();
     }
 
-    // [Qt]r57240 broke Qt build (might be a gcc bug)
-    // FIXME! See: https://bugs.webkit.org/show_bug.cgi?id=37253
-    template<typename T> 
-#if !COMPILER(WINSCW)
-#if !PLATFORM(QT)
-    ALWAYS_INLINE
-#else
-    inline
-#endif
-#endif
-    void derefIfNotNull(T* ptr)
+    template<typename T> REF_DEREF_INLINE void derefIfNotNull(T* ptr)
     {
         if (LIKELY(ptr != 0))
             ptr->deref();
     }
 
+    #undef REF_DEREF_INLINE
+
     template<typename T> class PassRefPtr {
     public:
-        PassRefPtr() : m_ptr(0) {}
+        PassRefPtr() : m_ptr(0) { }
         PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
         // It somewhat breaks the type system to allow transfer of ownership out of
         // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
-        // temporaries, and we don't really have a need to use real const PassRefPtrs 
-        // anyway.
-        PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {}
-        template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { }
+        // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
+        PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
+        template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }
 
         ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }
 
-        template <class U> 
-        PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); }
+        template<typename U> PassRefPtr(const RefPtr<U>&);
         
         T* get() const { return m_ptr; }
 
-        void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; }
-        T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
+        void clear();
+        T* leakRef() const WARN_UNUSED_RETURN;
 
         T& operator*() const { return *m_ptr; }
         T* operator->() const { return m_ptr; }
-        
+
         bool operator!() const { return !m_ptr; }
 
         // This conversion operator allows implicit conversion to bool but not to other integer types.
@@ -98,25 +91,33 @@ namespace WTF {
 
         PassRefPtr& operator=(T*);
         PassRefPtr& operator=(const PassRefPtr&);
-        template <typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
-        template <typename U> PassRefPtr& operator=(const RefPtr<U>&);
+#if !HAVE(NULLPTR)
+        PassRefPtr& operator=(std::nullptr_t) { clear(); return *this; }
+#endif
+        template<typename U> PassRefPtr& operator=(const PassRefPtr<U>&);
+        template<typename U> PassRefPtr& operator=(const RefPtr<U>&);
 
         friend PassRefPtr adoptRef<T>(T*);
+
+        // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
+        T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
+
     private:
         // adopting constructor
-        PassRefPtr(T* ptr, bool) : m_ptr(ptr) {}
+        PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }
+
         mutable T* m_ptr;
     };
     
     // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr
-    // begins life non-null, and can only become null through a call to releaseRef()
+    // begins life non-null, and can only become null through a call to leakRef()
     // or clear().
 
     // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However,
     // if we use inheritance, GCC's optimizer fails to realize that destruction
     // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the
     // most important code from PassRefPtr.
-    template <typename T> class NonNullPassRefPtr {
+    template<typename T> class NonNullPassRefPtr {
     public:
         NonNullPassRefPtr(T* ptr)
             : m_ptr(ptr)
@@ -125,7 +126,7 @@ namespace WTF {
             m_ptr->ref();
         }
 
-        template <class U> NonNullPassRefPtr(const RefPtr<U>& o)
+        template<typename U> NonNullPassRefPtr(const RefPtr<U>& o)
             : m_ptr(o.get())
         {
             ASSERT(m_ptr);
@@ -133,19 +134,19 @@ namespace WTF {
         }
 
         NonNullPassRefPtr(const NonNullPassRefPtr& o)
-            : m_ptr(o.releaseRef())
+            : m_ptr(o.leakRef())
         {
             ASSERT(m_ptr);
         }
 
-        template <class U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
-            : m_ptr(o.releaseRef())
+        template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o)
+            : m_ptr(o.leakRef())
         {
             ASSERT(m_ptr);
         }
 
-        template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o)
-            : m_ptr(o.releaseRef())
+        template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o)
+            : m_ptr(o.leakRef())
         {
             ASSERT(m_ptr);
         }
@@ -154,17 +155,41 @@ namespace WTF {
 
         T* get() const { return m_ptr; }
 
-        void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
-        T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; }
+        void clear();
+        T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; }
 
         T& operator*() const { return *m_ptr; }
         T* operator->() const { return m_ptr; }
 
+        // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
+        T* releaseRef() const WARN_UNUSED_RETURN { return leakRef(); }
+
     private:
         mutable T* m_ptr;
     };
 
-    template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o) 
+    template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o)
+        : m_ptr(o.get())
+    {
+        T* ptr = m_ptr;
+        refIfNotNull(ptr);
+    }
+
+    template<typename T> inline void PassRefPtr<T>::clear()
+    {
+        T* ptr = m_ptr;
+        m_ptr = 0;
+        derefIfNotNull(ptr);
+    }
+
+    template<typename T> inline T* PassRefPtr<T>::leakRef() const
+    {
+        T* ptr = m_ptr;
+        m_ptr = 0;
+        return ptr;
+    }
+
+    template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o)
     {
         T* optr = o.get();
         refIfNotNull(optr);
@@ -174,7 +199,7 @@ namespace WTF {
         return *this;
     }
     
-    template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
+    template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr)
     {
         refIfNotNull(optr);
         T* ptr = m_ptr;
@@ -183,92 +208,100 @@ namespace WTF {
         return *this;
     }
 
-    template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
+    template<typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<T>& ref)
     {
         T* ptr = m_ptr;
-        m_ptr = ref.releaseRef();
+        m_ptr = ref.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
     
-    template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
+    template<typename T> template<typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const PassRefPtr<U>& ref)
     {
         T* ptr = m_ptr;
-        m_ptr = ref.releaseRef();
+        m_ptr = ref.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
     
-    template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
     { 
         return a.get() == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 
     { 
         return a.get() == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) 
     { 
         return a.get() == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b) 
+    template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b) 
     { 
         return a.get() == b; 
     }
     
-    template <typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) 
     {
         return a == b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
     { 
         return a.get() != b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 
     { 
         return a.get() != b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) 
     { 
         return a.get() != b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b)
     {
         return a.get() != b; 
     }
 
-    template <typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) 
     { 
         return a != b.get(); 
     }
     
-    template <typename T> inline PassRefPtr<T> adoptRef(T* p)
+    template<typename T> inline PassRefPtr<T> adoptRef(T* p)
     {
+        adopted(p);
         return PassRefPtr<T>(p, true);
     }
 
-    template <typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 
+    template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 
     { 
-        return adoptRef(static_cast<T*>(p.releaseRef())); 
+        return adoptRef(static_cast<T*>(p.leakRef())); 
     }
 
-    template <typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) 
+    template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) 
     { 
-        return adoptRef(const_cast<T*>(p.releaseRef())); 
+        return adoptRef(const_cast<T*>(p.leakRef())); 
     }
 
-    template <typename T> inline T* getPtr(const PassRefPtr<T>& p)
+    template<typename T> inline T* getPtr(const PassRefPtr<T>& p)
     {
         return p.get();
     }
 
+    template<typename T> inline void NonNullPassRefPtr<T>::clear()
+    {
+        T* ptr = m_ptr;
+        m_ptr = 0;
+        derefIfNotNull(ptr);
+    }
+
 } // namespace WTF
 
 using WTF::PassRefPtr;
diff --git a/wtf/PassTraits.h b/wtf/PassTraits.h
new file mode 100644 (file)
index 0000000..3462734
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 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.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 WTF_PassTraits_h
+#define WTF_PassTraits_h
+
+#include "OwnPtr.h"
+#include "RefPtr.h"
+
+// The PassTraits template exists to help optimize (or make possible) use
+// of WTF data structures with WTF smart pointers that have a Pass
+// variant for transfer of ownership
+
+namespace WTF {
+
+template<typename T> struct PassTraits {
+    typedef T Type;
+    typedef T PassType;
+    static PassType transfer(Type& value) { return value; }
+};
+
+template<typename T> struct PassTraits<OwnPtr<T> > {
+    typedef OwnPtr<T> Type;
+    typedef PassOwnPtr<T> PassType;
+    static PassType transfer(Type& value) { return value.release(); }
+};
+
+template<typename T> struct PassTraits<RefPtr<T> > {
+    typedef RefPtr<T> Type;
+    typedef PassRefPtr<T> PassType;
+    static PassType transfer(Type& value) { return value.release(); }
+};
+
+} // namespace WTF
+
+using WTF::PassTraits;
+
+#endif // WTF_PassTraits_h
index 961e80fe8b4321be293e91f61a8601eafd04f832..987cfbfecf449ba6c62a5adb5bfa795918722600 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc.  All rights reserved.
  * Copyright (C) 2007-2009 Torch Mobile, Inc.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #endif
 
 /* COMPILER(RVCT)  - ARM RealView Compilation Tools */
+/* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */
 #if defined(__CC_ARM) || defined(__ARMCC__)
 #define WTF_COMPILER_RVCT 1
+#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) (__ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build))
+#else
+/* Define this for !RVCT compilers, just so we can write things like RVCT_VERSION_AT_LEAST(3, 0, 0, 0). */
+#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) 0
+#endif
+
+/* COMPILER(GCCE) - GNU Compiler Collection for Embedded */
+#if defined(__GCCE__)
+#define WTF_COMPILER_GCCE 1
+#define GCCE_VERSION (__GCCE__ * 10000 + __GCCE_MINOR__ * 100 + __GCCE_PATCHLEVEL__)
+#define GCCE_VERSION_AT_LEAST(major, minor, patch) (GCCE_VERSION >= (major * 10000 + minor * 100 + patch))
 #endif
 
 /* COMPILER(GCC) - GNU Compiler Collection */
 #if defined(__GNUC__) && !COMPILER(RVCT)
 #define WTF_COMPILER_GCC 1
 #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#define GCC_VERSION_AT_LEAST(major, minor, patch) (GCC_VERSION >= (major * 10000 + minor * 100 + patch))
+#else
+/* Define this for !GCC compilers, just so we can write things like GCC_VERSION_AT_LEAST(4, 1, 0). */
+#define GCC_VERSION_AT_LEAST(major, minor, patch) 0
 #endif
 
 /* COMPILER(MINGW) - MinGW GCC */
 #undef _WIN32
 #endif
 
+/* COMPILER(INTEL) - Intel C++ Compiler */
+#if defined(__INTEL_COMPILER)
+#define WTF_COMPILER_INTEL 1
+#endif
 
+/* COMPILER(SUNCC) */
+#if defined(__SUNPRO_CC) || defined(__SUNPRO_C)
+#define WTF_COMPILER_SUNCC 1
+#endif
 
 /* ==== CPU() - the target CPU architecture ==== */
 
 
 /* CPU(MIPS) - MIPS 32-bit */
 /* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now.  */
-#if (defined(mips) || defined(__mips__)) \
+#if (defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_)) \
     && defined(_ABIO32)
 #define WTF_CPU_MIPS 1
 #if defined(__MIPSEB__)
 #define WTF_MIPS_ARCH_REV __mips_isa_rev
 #define WTF_MIPS_ISA_REV(v) (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == v)
 #define WTF_MIPS_DOUBLE_FLOAT (defined __mips_hard_float && !defined __mips_single_float)
+#define WTF_MIPS_FP64 (defined __mips_fpr && __mips_fpr == 64)
+/* MIPS requires allocators to use aligned memory */
+#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1
 #endif /* MIPS */
 
 /* CPU(PPC) - PowerPC 32-bit */
 #define WTF_CPU_SPARC 1
 #endif
 
+/* CPU(S390X) - S390 64-bit */
+#if defined(__s390x__)
+#define WTF_CPU_S390X 1
+#define WTF_CPU_BIG_ENDIAN 1
+#endif
+
+/* CPU(S390) - S390 32-bit */
+#if defined(__s390__)
+#define WTF_CPU_S390 1
+#define WTF_CPU_BIG_ENDIAN 1
+#endif
+
 /* CPU(X86) - i386 / x86 32-bit */
 #if   defined(__i386__) \
     || defined(i386)     \
     || defined(_ARM_)
 #define WTF_CPU_ARM 1
 
-#if defined(__ARMEB__)
+#if defined(__ARMEB__) || (COMPILER(RVCT) && defined(__BIG_ENDIAN))
 #define WTF_CPU_BIG_ENDIAN 1
 
 #elif !defined(__ARM_EABI__) \
 
 #elif defined(__ARM_ARCH_5__) \
     || defined(__ARM_ARCH_5T__) \
-    || defined(__ARM_ARCH_5E__) \
-    || defined(__ARM_ARCH_5TE__) \
-    || defined(__ARM_ARCH_5TEJ__) \
     || defined(__MARM_ARMV5__)
 #define WTF_ARM_ARCH_VERSION 5
 
+#elif defined(__ARM_ARCH_5E__) \
+    || defined(__ARM_ARCH_5TE__) \
+    || defined(__ARM_ARCH_5TEJ__)
+#define WTF_ARM_ARCH_VERSION 5
+/*ARMv5TE requires allocators to use aligned memory*/
+#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1
+
 #elif defined(__ARM_ARCH_6__) \
     || defined(__ARM_ARCH_6J__) \
     || defined(__ARM_ARCH_6K__) \
 #define WTF_ARM_ARCH_VERSION 6
 
 #elif defined(__ARM_ARCH_7A__) \
-    || defined(__ARM_ARCH_7R__)
+    || defined(__ARM_ARCH_7F__) \
+    || defined(__ARM_ARCH_7R__) \
+    || defined(__ARM_ARCH_7S__)
 #define WTF_ARM_ARCH_VERSION 7
 
 /* RVCT sets _TARGET_ARCH_ARM */
 #elif defined(__TARGET_ARCH_ARM)
 #define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM
 
+#if defined(__TARGET_ARCH_5E) \
+    || defined(__TARGET_ARCH_5TE) \
+    || defined(__TARGET_ARCH_5TEJ)
+/*ARMv5TE requires allocators to use aligned memory*/
+#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1
+#endif
+
 #else
 #define WTF_ARM_ARCH_VERSION 0
 
 #elif defined(__ARM_ARCH_6T2__) \
     || defined(__ARM_ARCH_7__) \
     || defined(__ARM_ARCH_7A__) \
+    || defined(__ARM_ARCH_7F__) \
     || defined(__ARM_ARCH_7R__) \
-    || defined(__ARM_ARCH_7M__)
+    || defined(__ARM_ARCH_7M__) \
+    || defined(__ARM_ARCH_7S__)
 #define WTF_THUMB_ARCH_VERSION 4
 
 /* RVCT sets __TARGET_ARCH_THUMB */
 #  error "Cannot use both of WTF_CPU_ARM_TRADITIONAL and WTF_CPU_ARM_THUMB2 platforms"
 #endif /* !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) */
 
-#endif /* ARM */
+#if defined(__ARM_NEON__) && !defined(WTF_CPU_ARM_NEON)
+#define WTF_CPU_ARM_NEON 1
+#endif
 
+#endif /* ARM */
 
+#if CPU(ARM) || CPU(MIPS)
+#define WTF_CPU_NEEDS_ALIGNED_ACCESS 1
+#endif
 
 /* ==== OS() - underlying operating system; only to be used for mandated low-level services like 
    virtual memory, not to choose a GUI toolkit ==== */
 
 /* FIXME: BUILDING_ON_.., and TARGETING... macros should be folded into the OS() system */
 #include <AvailabilityMacros.h>
-#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
-#define BUILDING_ON_TIGER 1
-#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
 #define BUILDING_ON_LEOPARD 1
 #elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
 #define BUILDING_ON_SNOW_LEOPARD 1
 #endif
-#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
-#define TARGETING_TIGER 1
-#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
 #define TARGETING_LEOPARD 1
 #elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
 #define TARGETING_SNOW_LEOPARD 1
 
 #endif
 
-/* OS(IPHONE_OS) - iPhone OS */
-/* OS(MAC_OS_X) - Mac OS X (not including iPhone OS) */
+/* OS(IOS) - iOS */
+/* OS(MAC_OS_X) - Mac OS X (not including iOS) */
 #if OS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED)  \
     || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)                   \
     || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR))
-#define WTF_OS_IPHONE_OS 1
+#define WTF_OS_IOS 1
 #elif OS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC
 #define WTF_OS_MAC_OS_X 1
 #endif
 
 /* OS(FREEBSD) - FreeBSD */
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__DragonFly__)
 #define WTF_OS_FREEBSD 1
 #endif
 
 
 /* OS(NETBSD) - NetBSD */
 #if defined(__NetBSD__)
-#define WTF_PLATFORM_NETBSD 1
+#define WTF_OS_NETBSD 1
 #endif
 
 /* OS(OPENBSD) - OpenBSD */
 #define WTF_PLATFORM_WIN 1
 #endif
 
-/* PLATFORM(IPHONE) */
+/* PLATFORM(IOS) */
 /* FIXME: this is sometimes used as an OS switch and sometimes for higher-level things */
 #if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)
-#define WTF_PLATFORM_IPHONE 1
+#define WTF_PLATFORM_IOS 1
 #endif
 
-/* PLATFORM(IPHONE_SIMULATOR) */
+/* PLATFORM(IOS_SIMULATOR) */
 #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR
-#define WTF_PLATFORM_IPHONE 1
-#define WTF_PLATFORM_IPHONE_SIMULATOR 1
+#define WTF_PLATFORM_IOS 1
+#define WTF_PLATFORM_IOS_SIMULATOR 1
 #else
-#define WTF_PLATFORM_IPHONE_SIMULATOR 0
+#define WTF_PLATFORM_IOS_SIMULATOR 0
 #endif
 
-#if !defined(WTF_PLATFORM_IPHONE)
-#define WTF_PLATFORM_IPHONE 0
-#endif
-
-/* PLATFORM(ANDROID) */
-/* FIXME: this is sometimes used as an OS() switch, and other times to drive
-   policy choices */
-#if defined(ANDROID)
-#define WTF_PLATFORM_ANDROID 1
+#if !defined(WTF_PLATFORM_IOS)
+#define WTF_PLATFORM_IOS 0
 #endif
 
 /* Graphics engines */
 
-/* PLATFORM(CG) and PLATFORM(CI) */
-#define WTF_PLATFORM_CG 1
+/* USE(CG) and PLATFORM(CI) */
+#define WTF_USE_CG 1
+#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WIN) && USE(CG))
+#define WTF_USE_CA 1
+#endif
 
-/* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */
+/* USE(SKIA) for Win/Linux, CG for Mac */
 #if PLATFORM(CHROMIUM)
-#define ENABLE_HISTORY_ALWAYS_ASYNC 1
 #if OS(DARWIN)
-#define WTF_PLATFORM_CG 1
-#define WTF_PLATFORM_CI 1
+#define WTF_USE_CG 1
 #define WTF_USE_ATSUI 1
 #define WTF_USE_CORE_TEXT 1
+#define WTF_USE_ICCJPEG 1
 #else
-#define WTF_PLATFORM_SKIA 1
+#define WTF_USE_SKIA 1
+#define WTF_USE_CHROMIUM_NET 1
 #endif
 #endif
 
+#if PLATFORM(BREWMP)
+#define WTF_USE_SKIA 1
+#endif
+
 #if PLATFORM(GTK)
-#define WTF_PLATFORM_CAIRO 1
+#define WTF_USE_CAIRO 1
 #endif
 
 
-/* OS(WINCE) && PLATFORM(QT)
-   We can not determine the endianess at compile time. For
-   Qt for Windows CE the endianess is specified in the
-   device specific makespec
-*/
-#if OS(WINCE) && PLATFORM(QT)
-#   include <QtGlobal>
-#   undef WTF_CPU_BIG_ENDIAN
-#   undef WTF_CPU_MIDDLE_ENDIAN
-#   if Q_BYTE_ORDER == Q_BIG_ENDIAN
-#       define WTF_CPU_BIG_ENDIAN 1
-#   endif
+#if OS(WINCE)
+#include <ce_time.h>
+#define WTF_USE_MERSENNE_TWISTER_19937 1
+#endif
 
-#   include <ce_time.h>
+#if PLATFORM(QT) && OS(UNIX) && !OS(SYMBIAN) && !OS(DARWIN)
+#define WTF_USE_PTHREAD_BASED_QT 1
 #endif
 
-#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && OS(DARWIN) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
+#if (PLATFORM(GTK) || PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && (OS(DARWIN) || USE(PTHREAD_BASED_QT)) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS)
 #define ENABLE_JSC_MULTIPLE_THREADS 1
 #endif
 
+#if ENABLE(JSC_MULTIPLE_THREADS)
+#define ENABLE_WTF_MULTIPLE_THREADS 1
+#endif
+
 /* On Windows, use QueryPerformanceCounter by default */
 #if OS(WINDOWS)
 #define WTF_USE_QUERY_PERFORMANCE_COUNTER  1
 #endif
 
 #if OS(WINCE) && !PLATFORM(QT)
-#undef ENABLE_JSC_MULTIPLE_THREADS
-#define ENABLE_JSC_MULTIPLE_THREADS        0
-#define USE_SYSTEM_MALLOC                  0
-#define ENABLE_ICONDATABASE                0
-#define ENABLE_JAVASCRIPT_DEBUGGER         0
-#define ENABLE_FTPDIR                      0
-#define ENABLE_PAN_SCROLLING               0
-#define ENABLE_WML                         1
-#define HAVE_ACCESSIBILITY                 0
-
 #define NOMINMAX       /* Windows min and max conflict with standard macros */
 #define NOSHLWAPI      /* shlwapi.h not available on WinCe */
 
 #define _INC_ASSERT    /* disable "assert.h" */
 #define assert(x)
 
-/* _countof is only included in CE6; for CE5 we need to define it ourself */
-#ifndef _countof
-#define _countof(x) (sizeof(x) / sizeof((x)[0]))
-#endif
-
 #endif  /* OS(WINCE) && !PLATFORM(QT) */
 
 #if PLATFORM(QT)
 #define WTF_USE_QT4_UNICODE 1
-#if !defined(ENABLE_WIDGETS_10_SUPPORT)
-#define ENABLE_WIDGETS_10_SUPPORT 1
-#endif
 #elif OS(WINCE)
 #define WTF_USE_WINCE_UNICODE 1
+#elif PLATFORM(BREWMP)
+#define WTF_USE_BREWMP_UNICODE 1
 #elif PLATFORM(GTK)
 /* The GTK+ Unicode backend is configurable */
 #else
 #endif
 
 
-
 #if PLATFORM(CHROMIUM) && OS(DARWIN)
-#define WTF_PLATFORM_CF 1
+#define WTF_USE_CF 1
 #define WTF_USE_PTHREADS 1
 #define HAVE_PTHREAD_RWLOCK 1
-#define WTF_USE_CARBON_SECURE_INPUT_MODE 1
 #endif
 
 #define DONT_FINALIZE_ON_MAIN_THREAD 1
 
+#if PLATFORM(BREWMP)
+#define ENABLE_SINGLE_THREADED 1
+#endif
+
 #if PLATFORM(QT) && OS(DARWIN)
-#define WTF_PLATFORM_CF 1
+#define WTF_USE_CF 1
 #endif
 
-#if OS(DARWIN) && !defined(BUILDING_ON_TIGER) && !PLATFORM(GTK) && !PLATFORM(QT)
+#if OS(DARWIN) && !PLATFORM(GTK) && !PLATFORM(QT)
 #define ENABLE_PURGEABLE_MEMORY 1
 #endif
 
 #define ENABLE_CONTEXT_MENUS 0
 #define ENABLE_DISK_IMAGE_CACHE 1
 #define ENABLE_DRAG_SUPPORT 0
+#define ENABLE_DATA_TRANSFER_ITEMS 0
 #define ENABLE_FTPDIR 1
 #define ENABLE_GEOLOCATION 1
 #define ENABLE_GEOLOCATION_PERMISSION_CACHE 1
 #define ENABLE_JAVA_BRIDGE 0
 #define ENABLE_NETSCAPE_PLUGIN_API 0
 #define ENABLE_ORIENTATION_EVENTS 1
-#define ENABLE_RANGETYPE_AS_TEXT 1
 #define ENABLE_REPAINT_THROTTLING 1
 #define ENABLE_RESPECT_EXIF_ORIENTATION 1
+#define ENABLE_WEB_ARCHIVE 1
+#define HAVE_CFNETWORK_DATA_ARRAY_CALLBACK 1
 #define HAVE_PTHREAD_RWLOCK 1
 #define HAVE_READLINE 1
 #define HAVE_RUNLOOP_TIMER 0
-#define WTF_PLATFORM_CF 1
+#define WTF_USE_CF 1
+#define WTF_USE_CFNETWORK 1
 #define WTF_USE_PTHREADS 1
 #define WTF_USE_WEB_THREAD 1
 
 #define ENABLE_PURGEABLE_MEMORY 1
 #endif
 
-#define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 1
-
 #if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION >= 7
     // ARMv7;
     #define WTF_USE_JSVALUE32_64 1
     #endif
 #endif
 
-#undef ENABLE_3D_CANVAS
+#undef ENABLE_WEBGL
 #if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6
-#define ENABLE_3D_CANVAS 0
+#define ENABLE_WEBGL 0
 #else
-#define ENABLE_3D_CANVAS 1
+#define ENABLE_WEBGL 1
 #endif
 
 
 #if PLATFORM(ANDROID)
 #define WTF_USE_PTHREADS 1
-#define WTF_PLATFORM_SGL 1
 #define USE_SYSTEM_MALLOC 1
 #define ENABLE_JAVA_BRIDGE 1
 #define LOG_DISABLED 1
    This prevents unnecessary invals. */
 #define ENABLE_TEXT_CARET 1
 #define ENABLE_JAVASCRIPT_DEBUGGER 0
+#if !defined(ENABLE_JIT) && !ENABLE(ANDROID_JSC_JIT)
+#define ENABLE_JIT 0
+#endif
 #endif
 
-#if PLATFORM(WIN)
-#define WTF_USE_WININET 1
+#if PLATFORM(WIN) && !OS(WINCE)
+#define WTF_USE_CF 1
+#define WTF_USE_PTHREADS 0
+#endif
+
+#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !defined(WIN_CAIRO)
+#define WTF_USE_CFNETWORK 1
+#endif
+
+#define WTF_USE_CFURLCACHE 1
+#define WTF_USE_CFURLSTORAGESESSIONS 1
+
+#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(QT)
+#define ENABLE_WEB_ARCHIVE 1
+#endif
+
+#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !defined(WIN_CAIRO) && !PLATFORM(QT)
+#define ENABLE_FULLSCREEN_API 1
 #endif
 
 #if PLATFORM(WX)
 #define ENABLE_ASSEMBLER 1
 #define ENABLE_GLOBAL_FASTMALLOC_NEW 0
 #if OS(DARWIN)
-#define WTF_PLATFORM_CF 1
-#ifndef BUILDING_ON_TIGER
+#define WTF_USE_CF 1
 #define WTF_USE_CORE_TEXT 1
-#else
-#define WTF_USE_ATSUI 1
-#endif
+#define ENABLE_WEB_ARCHIVE 1
 #endif
 #endif
 
 #define USE_SYSTEM_MALLOC 1
 #endif
 
+#if PLATFORM(BREWMP_SIMULATOR)
+#define ENABLE_JIT 0
+#endif
+
 #if !defined(HAVE_ACCESSIBILITY)
 #define HAVE_ACCESSIBILITY 1
 #endif /* !defined(HAVE_ACCESSIBILITY) */
 #define HAVE_SIGNAL_H 1
 #endif
 
+#if !defined(HAVE_STRNSTR)
+#if OS(DARWIN) || OS(FREEBSD)
+#define HAVE_STRNSTR 1
+#endif
+#endif
+
 #if !OS(WINDOWS) && !OS(SOLARIS) && !OS(QNX) \
     && !OS(SYMBIAN) && !OS(HAIKU) && !OS(RVCT) \
     && !OS(ANDROID) && !PLATFORM(BREWMP)
 #define HAVE_SYS_PARAM_H 1
 #define HAVE_SYS_TIME_H 1
 #define HAVE_SYS_TIMEB_H 1
+#define WTF_USE_ACCELERATE 1
 
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#ifndef TARGETING_LEOPARD
 
 #define HAVE_DISPATCH_H 1
+#define HAVE_HOSTED_CORE_ANIMATION 1
 
 
 #endif
 #define HAVE_ERRNO_H 0
 #else
 #define HAVE_SYS_TIMEB_H 1
+#define HAVE_ALIGNED_MALLOC 1
+#define HAVE_ISDEBUGGERPRESENT 1
 #endif
 #define HAVE_VIRTUALALLOC 1
 
 /* ENABLE macro defaults */
 
 #if PLATFORM(QT)
-// We musn't customize the global operator new and delete for the Qt port.
+/* We must not customize the global operator new and delete for the Qt port. */
 #define ENABLE_GLOBAL_FASTMALLOC_NEW 0
+#if !OS(UNIX) || OS(SYMBIAN)
+#define USE_SYSTEM_MALLOC 1
+#endif
 #endif
 
 /* fastMalloc match validation allows for runtime verification that
 #define ENABLE_DRAG_SUPPORT 1
 #endif
 
-#if !defined(ENABLE_DASHBOARD_SUPPORT)
-#define ENABLE_DASHBOARD_SUPPORT 0
+#if !defined(ENABLE_DATA_TRANSFER_ITEMS)
+#define ENABLE_DATA_TRANSFER_ITEMS 0
 #endif
 
-#if !defined(ENABLE_WIDGETS_10_SUPPORT)
-#define ENABLE_WIDGETS_10_SUPPORT 0
+#if !defined(ENABLE_DASHBOARD_SUPPORT)
+#define ENABLE_DASHBOARD_SUPPORT 0
 #endif
 
 #if !defined(ENABLE_GEOLOCATION_PERMISSION_CACHE)
 #define ENABLE_NETSCAPE_PLUGIN_API 1
 #endif
 
+#if !defined(ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE)
+#define ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE 0
+#endif
+
 #if !defined(ENABLE_PURGEABLE_MEMORY)
 #define ENABLE_PURGEABLE_MEMORY 0
 #endif
 #define ENABLE_RESPECT_EXIF_ORIENTATION 0
 #endif
 
-#if !defined(WTF_USE_PTHREAD_GETSPECIFIC_DIRECT)
-#define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 0
-#endif
-
 #if !defined(ENABLE_OPCODE_STATS)
 #define ENABLE_OPCODE_STATS 0
 #endif
 #define ENABLE_GEOLOCATION 0
 #endif
 
+#if !defined(ENABLE_GESTURE_RECOGNIZER)
+#define ENABLE_GESTURE_RECOGNIZER 0
+#endif
+
 #if !defined(ENABLE_NOTIFICATIONS)
 #define ENABLE_NOTIFICATIONS 0
 #endif
 #define ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL 0
 #endif
 
-#if !defined(ENABLE_CONTENTEDITABLE)
-#define ENABLE_CONTENTEDITABLE 0
+#if !defined(ENABLE_FULLSCREEN_API)
+#define ENABLE_FULLSCREEN_API 0
 #endif
 
-#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64)
+#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64)
 #if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \
     || (CPU(IA64) && !CPU(IA64_32)) \
     || CPU(ALPHA) \
-    || CPU(SPARC64)
+    || CPU(SPARC64) \
+    || CPU(S390X) \
+    || CPU(PPC64)
 #define WTF_USE_JSVALUE64 1
-#elif CPU(ARM_TRADITIONAL) && !PLATFORM(IPHONE) || CPU(PPC64) || CPU(MIPS) || (PLATFORM(IPHONE) && defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6 && !defined(__llvm__))
-/* FIXME: <rdar://problem/7478149> gcc-4.2 compiler bug with USE(JSVALUE32_64) and armv6 target */
-#define WTF_USE_JSVALUE32 1
-#elif OS(WINDOWS) && COMPILER(MINGW)
-/* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg
-on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
-#define WTF_USE_JSVALUE32 1
 #else
 #define WTF_USE_JSVALUE32_64 1
 #endif
-#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64) */
+#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) */
 
 #if !defined(ENABLE_REPAINT_THROTTLING)
 #define ENABLE_REPAINT_THROTTLING 0
 #endif
 
-#if !defined(ENABLE_JIT)
+/* Disable the JIT on versions of GCC prior to 4.1 */
+#if !defined(ENABLE_JIT) && COMPILER(GCC) && !GCC_VERSION_AT_LEAST(4, 1, 0)
+#define ENABLE_JIT 0
+#endif
 
-/* The JIT is tested & working on x86_64 Mac */
-#if CPU(X86_64) && PLATFORM(MAC)
-    #define ENABLE_JIT 1
-/* The JIT is tested & working on x86 Mac */
-#elif CPU(X86) && PLATFORM(MAC)
-    #define ENABLE_JIT 1
-    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
-#elif CPU(ARM_THUMB2) && PLATFORM(IPHONE)
-    #define ENABLE_JIT 1
-/* The JIT is tested & working on Android */
-#elif CPU(ARM_THUMB2) && PLATFORM(ANDROID) && ENABLE(ANDROID_JSC_JIT)
-    #define ENABLE_JIT 1
-/* The JIT is tested & working on x86 Windows */
-#elif CPU(X86) && PLATFORM(WIN)
-    #define ENABLE_JIT 1
+/* JIT is not implemented for 64 bit on MSVC */
+#if !defined(ENABLE_JIT) && COMPILER(MSVC) && CPU(X86_64)
+#define ENABLE_JIT 0
 #endif
 
-#if PLATFORM(QT) || PLATFORM(WX)
-#if CPU(X86_64) && OS(DARWIN)
-    #define ENABLE_JIT 1
-#elif CPU(X86) && OS(DARWIN)
-    #define ENABLE_JIT 1
-    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
-#elif CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100
-    #define ENABLE_JIT 1
-    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
-#elif CPU(X86_64) && OS(WINDOWS) && COMPILER(MINGW64) && GCC_VERSION >= 40100
-    #define ENABLE_JIT 1
-#elif CPU(X86) && OS(WINDOWS) && COMPILER(MSVC)
-    #define ENABLE_JIT 1
-    #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
-#elif CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100
-    #define ENABLE_JIT 1
-    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1
-#elif CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100
-    #define ENABLE_JIT 1
-#elif CPU(ARM_TRADITIONAL) && OS(LINUX)
-    #define ENABLE_JIT 1
-#elif CPU(ARM_TRADITIONAL) && OS(SYMBIAN) && COMPILER(RVCT)
-    #define ENABLE_JIT 1
-#elif CPU(MIPS) && OS(LINUX)
-    #define ENABLE_JIT 1
-    #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 0
+/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */
+#if !defined(ENABLE_JIT) \
+    && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \
+    && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \
+    && !OS(WINCE)
+#define ENABLE_JIT 1
 #endif
-#endif /* PLATFORM(QT) */
 
-#endif /* !defined(ENABLE_JIT) */
+/* Currently only implemented for JSVALUE64, only tested on PLATFORM(MAC) */
+#if ENABLE(JIT) && USE(JSVALUE64) && PLATFORM(MAC)
+#define ENABLE_DFG_JIT 0
+/* Enabled with restrictions to circumvent known performance regressions. */
+#define ENABLE_DFG_JIT_RESTRICTIONS 0
+#endif
 
-#if 1 || !ENABLE(JIT)
+/* Ensure that either the JIT or the interpreter has been enabled. */
+#if !defined(ENABLE_INTERPRETER) && !ENABLE(JIT)
 #define ENABLE_INTERPRETER 1
 #endif
-
 #if !(ENABLE(JIT) || ENABLE(INTERPRETER))
 #error You have to have at least one execution model enabled to build JSC
 #endif
 
-/* CPU architecture specific optimizations */
-#if CPU(ARM_TRADITIONAL)
-#if ENABLE(JIT) && !defined(ENABLE_JIT_OPTIMIZE_MOD) && WTF_ARM_ARCH_AT_LEAST(5)
-#define ENABLE_JIT_OPTIMIZE_MOD 1
-#endif
+#if CPU(SH4) && PLATFORM(QT)
+#define ENABLE_JIT 1
+#define ENABLE_YARR 1
+#define ENABLE_YARR_JIT 1
+#define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1
+#define ENABLE_ASSEMBLER 1
 #endif
 
+/* Configure the JIT */
 #if ENABLE(JIT)
-#ifndef ENABLE_JIT_OPTIMIZE_CALL
-#define ENABLE_JIT_OPTIMIZE_CALL 1
-#endif
-#ifndef ENABLE_JIT_OPTIMIZE_NATIVE_CALL
-#define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0
-#endif
-#ifndef ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS
-#define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1
-#endif
-#ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS
-#define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1
-#endif
-#ifndef ENABLE_JIT_OPTIMIZE_MOD
-#define ENABLE_JIT_OPTIMIZE_MOD 0
-#endif
+    #if CPU(ARM)
+    #if !defined(ENABLE_JIT_USE_SOFT_MODULO) && WTF_ARM_ARCH_AT_LEAST(5)
+    #define ENABLE_JIT_USE_SOFT_MODULO 1
+    #endif
+    #endif
+
+    #ifndef ENABLE_JIT_OPTIMIZE_CALL
+    #define ENABLE_JIT_OPTIMIZE_CALL 1
+    #endif
+    #ifndef ENABLE_JIT_OPTIMIZE_NATIVE_CALL
+    #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 1
+    #endif
+    #ifndef ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS
+    #define ENABLE_JIT_OPTIMIZE_PROPERTY_ACCESS 1
+    #endif
+    #ifndef ENABLE_JIT_OPTIMIZE_METHOD_CALLS
+    #define ENABLE_JIT_OPTIMIZE_METHOD_CALLS 1
+    #endif
 #endif
 
 #if CPU(X86) && COMPILER(MSVC)
@@ -1044,47 +1096,26 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
 #define JSC_HOST_CALL
 #endif
 
-#if COMPILER(GCC)
+/* Configure the interpreter */
+#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__))
 #define HAVE_COMPUTED_GOTO 1
 #endif
-
 #if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER)
 #define ENABLE_COMPUTED_GOTO_INTERPRETER 1
 #endif
 
-/* Yet Another Regex Runtime. */
-#if !defined(ENABLE_YARR_JIT)
+/* Regular Expression Tracing - Set to 1 to trace RegExp's in jsc.  Results dumped at exit */
+#define ENABLE_REGEXP_TRACING 0
 
-/* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
-#if (CPU(X86) && PLATFORM(MAC)) \
-    || (CPU(X86_64) && PLATFORM(MAC)) \
-    || (CPU(ARM_THUMB2) && PLATFORM(IPHONE)) \
-    || (CPU(ARM_THUMB2) && PLATFORM(ANDROID) && ENABLE(ANDROID_JSC_JIT)) \
-    || (CPU(X86) && PLATFORM(WIN)) \
-    || (CPU(X86) && PLATFORM(WX))
-#define ENABLE_YARR 1
-#define ENABLE_YARR_JIT 1
-#endif
+/* Yet Another Regex Runtime - turned on by default for JIT enabled ports. */
+#if PLATFORM(CHROMIUM)
+#define ENABLE_YARR_JIT 0
 
-#if PLATFORM(QT)
-#if (CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100) \
-    || (CPU(X86_64) && OS(WINDOWS) && COMPILER(MINGW64) && GCC_VERSION >= 40100) \
-    || (CPU(X86) && OS(WINDOWS) && COMPILER(MSVC)) \
-    || (CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100) \
-    || (CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100) \
-    || (CPU(ARM_TRADITIONAL) && OS(LINUX)) \
-    || (CPU(ARM_TRADITIONAL) && OS(SYMBIAN) && COMPILER(RVCT)) \
-    || (CPU(MIPS) && OS(LINUX))
-#define ENABLE_YARR 1
+#elif ENABLE(JIT) && !defined(ENABLE_YARR_JIT)
 #define ENABLE_YARR_JIT 1
-#endif
-#endif
 
-#endif /* !defined(ENABLE_YARR_JIT) */
-
-/* Sanity Check */
-#if ENABLE(YARR_JIT) && !ENABLE(YARR)
-#error "YARR_JIT requires YARR"
+/* Setting this flag compares JIT results with interpreter results. */
+#define ENABLE_YARR_JIT_DEBUG 0
 #endif
 
 #if ENABLE(JIT) || ENABLE(YARR_JIT)
@@ -1101,50 +1132,42 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
 #define ENABLE_PAN_SCROLLING 1
 #endif
 
-/* Use the QXmlStreamReader implementation for XMLTokenizer */
+#if !defined(ENABLE_SMOOTH_SCROLLING)
+#define ENABLE_SMOOTH_SCROLLING 0
+#endif
+
+#if !defined(ENABLE_WEB_ARCHIVE)
+#define ENABLE_WEB_ARCHIVE 0
+#endif
+
+/* Use the QXmlStreamReader implementation for XMLDocumentParser */
 /* Use the QXmlQuery implementation for XSLTProcessor */
 #if PLATFORM(QT)
 #define WTF_USE_QXMLSTREAM 1
 #define WTF_USE_QXMLQUERY 1
 #endif
 
-#if !PLATFORM(QT)
-#define WTF_USE_FONT_FAST_PATH 1
-#endif
-
 #if PLATFORM(MAC)
 /* Complex text framework */
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+#ifndef BUILDING_ON_LEOPARD
 #define WTF_USE_ATSUI 0
 #define WTF_USE_CORE_TEXT 1
 #else
 #define WTF_USE_ATSUI 1
 #define WTF_USE_CORE_TEXT 0
 #endif
-
-/* Accelerated compositing */
-#if !defined(BUILDING_ON_TIGER)
-#define WTF_USE_ACCELERATED_COMPOSITING 1
-#endif
 #endif
 
+/* Accelerated compositing */
+#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !OS(WINCE) &&!defined(WIN_CAIRO))
 #define WTF_USE_ACCELERATED_COMPOSITING 1
-
-/* FIXME: Defining ENABLE_3D_RENDERING here isn't really right, but it's always used with
-   with WTF_USE_ACCELERATED_COMPOSITING, and it allows the feature to be turned on and
-   off in one place. */
-#if PLATFORM(WIN)
-#include "QuartzCorePresent.h"
-#if QUARTZCORE_PRESENT
-#define WTF_USE_ACCELERATED_COMPOSITING 1
-#define ENABLE_3D_RENDERING 1
-#endif
 #endif
 
-#if (PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IPHONE)
+#if (PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IOS)
 #define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1
 #endif
 
+
 #if COMPILER(GCC)
 #define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result))
 #else
@@ -1160,8 +1183,50 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */
 
 #define ENABLE_JSC_ZOMBIES 0
 
+/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */
+#define WTF_USE_PLATFORM_STRATEGIES 1
+
+#if PLATFORM(WIN)
+#define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1
+#endif
+
+/* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location.
+   Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy.
+   pre-emptive permission policy is enabled by default for all client-based implementations. */
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+#define WTF_USE_PREEMPT_GEOLOCATION_PERMISSION 1
+#endif
+
 #if CPU(ARM_THUMB2)
 #define ENABLE_BRANCH_COMPACTION 1
 #endif
 
+#if !defined(ENABLE_THREADING_OPENMP) && defined(_OPENMP)
+#define ENABLE_THREADING_OPENMP 1
+#endif
+
+#if !defined(ENABLE_PARALLEL_JOBS) && !ENABLE(SINGLE_THREADED) && (ENABLE(THREADING_GENERIC) || ENABLE(THREADING_LIBDISPATCH) || ENABLE(THREADING_OPENMP))
+#define ENABLE_PARALLEL_JOBS 1
+#endif
+
+#if ENABLE(GLIB_SUPPORT)
+#include "GTypedefs.h"
+#endif
+
+/* FIXME: This define won't be needed once #27551 is fully landed. However, 
+   since most ports try to support sub-project independence, adding new headers
+   to WTF causes many ports to break, and so this way we can address the build
+   breakages one port at a time. */
+#define WTF_USE_EXPORT_MACROS 0
+
+#if (PLATFORM(QT) && !OS(SYMBIAN)) || PLATFORM(GTK)
+#define WTF_USE_UNIX_DOMAIN_SOCKETS 1
+#endif
+
+#ifndef NDEBUG
+#ifndef ENABLE_GC_VALIDATION
+#define ENABLE_GC_VALIDATION 1
+#endif
+#endif
+
 #endif /* WTF_Platform_h */
index fc4826307a13c45549864d8ee22d67aa95658cb5..490c5914a72373c30f63df4f4127c4bb72133be6 100644 (file)
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "RandomNumber.h"
 
+#include "CryptographicallyRandomNumber.h"
 #include "RandomNumberSeed.h"
 
 #include <limits>
@@ -34,9 +35,9 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#if OS(WINCE)
+#if USE(MERSENNE_TWISTER_19937)
 extern "C" {
-#include "wince/mt19937ar.c"
+#include "mt19937ar.c"
 }
 #endif
 
@@ -44,79 +45,41 @@ extern "C" {
 #include <AEEAppGen.h>
 #include <AEESource.h>
 #include <AEEStdLib.h>
+#include <wtf/brew/RefPtrBrew.h>
+#include <wtf/brew/ShellBrew.h>
 #endif
 
 namespace WTF {
 
-double weakRandomNumber()
+double randomNumber()
 {
-#if COMPILER(MSVC) && defined(_CRT_RAND_S)
-    // rand_s is incredibly slow on windows so we fall back on rand for Math.random
-    return (rand() + (rand() / (RAND_MAX + 1.0))) / (RAND_MAX + 1.0);
-#elif PLATFORM(BREWMP)
-    uint32_t bits;
-    GETRAND(reinterpret_cast<byte*>(&bits), sizeof(uint32_t));
+#if USE(OS_RANDOMNESS)
+    uint32_t bits = cryptographicallyRandomNumber();
     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
 #else
-    return randomNumber();
-#endif
-}
+    // Without OS_RANDOMNESS, we fall back to other random number generators
+    // that might not be cryptographically secure. Ideally, most ports would
+    // define USE(OS_RANDOMNESS).
 
-double randomNumber()
-{
-#if !ENABLE(JSC_MULTIPLE_THREADS)
+#if !ENABLE(WTF_MULTIPLE_THREADS)
     static bool s_initialized = false;
     if (!s_initialized) {
         initializeRandomNumberGenerator();
         s_initialized = true;
     }
 #endif
-    
-#if COMPILER(MSVC) && defined(_CRT_RAND_S)
-    uint32_t bits;
-    rand_s(&bits);
-    return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
-#elif OS(DARWIN)
-    uint32_t bits = arc4random();
-    return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
-#elif OS(UNIX)
-    uint32_t part1 = random() & (RAND_MAX - 1);
-    uint32_t part2 = random() & (RAND_MAX - 1);
-    // random only provides 31 bits
-    uint64_t fullRandom = part1;
-    fullRandom <<= 31;
-    fullRandom |= part2;
 
-    // Mask off the low 53bits
-    fullRandom &= (1LL << 53) - 1;
-    return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
-#elif OS(WINCE)
+#if USE(MERSENNE_TWISTER_19937)
     return genrand_res53();
-#elif OS(WINDOWS)
-    uint32_t part1 = rand() & (RAND_MAX - 1);
-    uint32_t part2 = rand() & (RAND_MAX - 1);
-    uint32_t part3 = rand() & (RAND_MAX - 1);
-    uint32_t part4 = rand() & (RAND_MAX - 1);
-    // rand only provides 15 bits on Win32
-    uint64_t fullRandom = part1;
-    fullRandom <<= 15;
-    fullRandom |= part2;
-    fullRandom <<= 15;
-    fullRandom |= part3;
-    fullRandom <<= 15;
-    fullRandom |= part4;
-
-    // Mask off the low 53bits
-    fullRandom &= (1LL << 53) - 1;
-    return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
 #elif PLATFORM(BREWMP)
     uint32_t bits;
-    ISource* randomSource;
-
-    IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell;
-    ISHELL_CreateInstance(shell, AEECLSID_RANDOM, reinterpret_cast<void**>(&randomSource));
-    ISOURCE_Read(randomSource, reinterpret_cast<char*>(&bits), 4);
-    ISOURCE_Release(randomSource);
+    // Is this a cryptographically strong source of random numbers? If so, we
+    // should move this into OSRandomSource.
+    // http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/140sp/140sp851.pdf
+    // is slightly unclear on this point, although it seems to imply that it is
+    // secure.
+    RefPtr<ISource> randomSource = createRefPtrInstance<ISource>(AEECLSID_RANDOM);
+    ISOURCE_Read(randomSource.get(), reinterpret_cast<char*>(&bits), 4);
 
     return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0);
 #else
@@ -134,6 +97,7 @@ double randomNumber()
     fullRandom &= (1LL << 53) - 1;
     return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53);
 #endif
+#endif
 }
 
 }
index 0cd4f71e7fb2bd5ce7893f6a0910ba4e2228fbfb..f2e7e8f50f7ebded1b3b765f2d1c7ed117c7a4f8 100644 (file)
@@ -32,11 +32,6 @@ namespace WTF {
     // cryptographically secure if possible on the target platform
     double randomNumber();
 
-    // Returns a pseudo-random number in the range [0, 1), attempts to
-    // produce a reasonable "random" number fast.
-    // We only need this because rand_s is so slow on windows.
-    double weakRandomNumber();
-
 }
 
 using WTF::randomNumber;
index ae414c0e32a7f5f395138935fe26f496c9039613..0703abfe9b632c808fd711f774fc70bf9ca116e5 100644 (file)
@@ -38,7 +38,7 @@
 #include <unistd.h>
 #endif
 
-#if OS(WINCE)
+#if USE(MERSENNE_TWISTER_19937)
 extern "C" {
 void init_by_array(unsigned long init_key[],int key_length);
 }
@@ -53,17 +53,11 @@ inline void initializeRandomNumberGenerator()
     // On Darwin we use arc4random which initialises itself.
 #elif OS(WINCE)
     // initialize rand()
-    srand(static_cast<unsigned>(time(0)));
-
-    // use rand() to initialize the real RNG
-    unsigned long initializationBuffer[4];
-    initializationBuffer[0] = (rand() << 16) | rand();
-    initializationBuffer[1] = (rand() << 16) | rand();
-    initializationBuffer[2] = (rand() << 16) | rand();
-    initializationBuffer[3] = (rand() << 16) | rand();
-    init_by_array(initializationBuffer, 4);
+    srand(GetTickCount());
 #elif COMPILER(MSVC) && defined(_CRT_RAND_S)
     // On Windows we use rand_s which initialises itself
+#elif PLATFORM(BREWMP)
+    // On Brew MP we use AEECLSID_RANDOM which initialises itself
 #elif OS(UNIX)
     // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved
     timeval time;
@@ -72,17 +66,18 @@ inline void initializeRandomNumberGenerator()
 #else
     srand(static_cast<unsigned>(time(0)));
 #endif
-}
 
-inline void initializeWeakRandomNumberGenerator()
-{
-#if COMPILER(MSVC) && defined(_CRT_RAND_S)
-    // We need to initialise windows rand() explicitly for Math.random
-    unsigned seed = 0;
-    rand_s(&seed);
-    srand(seed);
+#if USE(MERSENNE_TWISTER_19937)
+    // use rand() to initialize the Mersenne Twister random number generator.
+    unsigned long initializationBuffer[4];
+    initializationBuffer[0] = (rand() << 16) | rand();
+    initializationBuffer[1] = (rand() << 16) | rand();
+    initializationBuffer[2] = (rand() << 16) | rand();
+    initializationBuffer[3] = (rand() << 16) | rand();
+    init_by_array(initializationBuffer, 4);
 #endif
 }
+
 }
 
 #endif
index 761a8566f4fcb777c8b9f114c83a128f28f424e6..12b670e07c1e5facd5df383ced67ac0e6d46cbf0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 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
@@ -21,8 +21,9 @@
 #ifndef RefCounted_h
 #define RefCounted_h
 
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
+#include "Assertions.h"
+#include "FastAllocBase.h"
+#include "Noncopyable.h"
 
 namespace WTF {
 
@@ -34,6 +35,7 @@ public:
     void ref()
     {
         ASSERT(!m_deletionHasBegun);
+        ASSERT(!m_adoptionIsRequired);
         ++m_refCount;
     }
 
@@ -48,23 +50,43 @@ public:
         return m_refCount;
     }
 
+    void relaxAdoptionRequirement()
+    {
+#ifndef NDEBUG
+        ASSERT(!m_deletionHasBegun);
+        ASSERT(m_adoptionIsRequired);
+        m_adoptionIsRequired = false;
+#endif
+    }
+
+    // Helper for generating JIT code. Please do not use for non-JIT purposes.
+    const int* addressOfCount() const
+    {
+        return &m_refCount;
+    }
+
 protected:
     RefCountedBase()
         : m_refCount(1)
 #ifndef NDEBUG
         , m_deletionHasBegun(false)
+        , m_adoptionIsRequired(true)
 #endif
     {
     }
 
     ~RefCountedBase()
     {
+        ASSERT(m_deletionHasBegun);
+        ASSERT(!m_adoptionIsRequired);
     }
 
     // Returns whether the pointer should be freed or not.
     bool derefBase()
     {
         ASSERT(!m_deletionHasBegun);
+        ASSERT(!m_adoptionIsRequired);
+
         ASSERT(m_refCount > 0);
         if (m_refCount == 1) {
 #ifndef NDEBUG
@@ -77,12 +99,6 @@ protected:
         return false;
     }
 
-    // Helper for generating JIT code. Please do not use for non-JIT purposes.
-    int* addressOfCount()
-    {
-        return &m_refCount;
-    }
-
 #ifndef NDEBUG
     bool deletionHasBegun() const
     {
@@ -91,17 +107,33 @@ protected:
 #endif
 
 private:
-    template<class T>
-    friend class CrossThreadRefCounted;
+    template<typename T> friend class CrossThreadRefCounted;
+
+#ifndef NDEBUG
+    friend void adopted(RefCountedBase*);
+#endif
 
     int m_refCount;
 #ifndef NDEBUG
     bool m_deletionHasBegun;
+    bool m_adoptionIsRequired;
 #endif
 };
 
+#ifndef NDEBUG
+
+inline void adopted(RefCountedBase* object)
+{
+    if (!object)
+        return;
+    ASSERT(!object->m_deletionHasBegun);
+    object->m_adoptionIsRequired = false;
+}
 
-template<class T> class RefCounted : public RefCountedBase, public Noncopyable {
+#endif
+
+template<typename T> class RefCounted : public RefCountedBase {
+    WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED;
 public:
     void deref()
     {
@@ -110,12 +142,15 @@ public:
     }
 
 protected:
+    RefCounted() { }
     ~RefCounted()
     {
     }
 };
 
-template<class T> class RefCountedCustomAllocated : public RefCountedBase, public NoncopyableCustomAllocated {
+template<typename T> class RefCountedCustomAllocated : public RefCountedBase {
+    WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated);
+
 public:
     void deref()
     {
index 80922d3367b04e3765b520478fc1b21795a58710..08b32ab3249c611d331ecd3b1a30a21a82ad83b4 100644 (file)
@@ -79,7 +79,7 @@ RefCountedLeakCounter::~RefCountedLeakCounter()
 
 void RefCountedLeakCounter::increment()
 {
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
     atomicIncrement(&m_count);
 #else
     ++m_count;
@@ -88,7 +88,7 @@ void RefCountedLeakCounter::increment()
 
 void RefCountedLeakCounter::decrement()
 {
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
     atomicDecrement(&m_count);
 #else
     --m_count;
index eed793329a472c242bf1c34e6eda83e2b675e43e..353bd35ddf5fb99ffe8596d08eb9e9c74ea1876c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -24,7 +24,6 @@
 #define WTF_RefPtr_h
 
 #include <algorithm>
-#include "AlwaysInline.h"
 #include "FastAllocBase.h"
 #include "PassRefPtr.h"
 
@@ -32,34 +31,35 @@ namespace WTF {
 
     enum PlacementNewAdoptType { PlacementNewAdopt };
 
-    template <typename T> class PassRefPtr;
-    template <typename T> class NonNullPassRefPtr;
+    template<typename T> class PassRefPtr;
+    template<typename T> class NonNullPassRefPtr;
 
     enum HashTableDeletedValueType { HashTableDeletedValue };
 
-    template <typename T> class RefPtr : public FastAllocBase {
+    template<typename T> class RefPtr {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
-        RefPtr() : m_ptr(0) { }
-        RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
-        RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { T* ptr = m_ptr; refIfNotNull(ptr); }
-        // see comment in PassRefPtr.h for why this takes const reference
-        template <typename U> RefPtr(const PassRefPtr<U>&);
-        template <typename U> RefPtr(const NonNullPassRefPtr<U>&);
+        ALWAYS_INLINE RefPtr() : m_ptr(0) { }
+        ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
+        ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
+        template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
+
+        // See comments in PassRefPtr.h for an explanation of why these takes const references.
+        template<typename U> RefPtr(const PassRefPtr<U>&);
+        template<typename U> RefPtr(const NonNullPassRefPtr<U>&);
 
         // Special constructor for cases where we overwrite an object in place.
-        RefPtr(PlacementNewAdoptType) { }
+        ALWAYS_INLINE RefPtr(PlacementNewAdoptType) { }
 
         // Hash table deleted values, which are only constructed and never copied or destroyed.
         RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
         bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
 
-        ~RefPtr() { derefIfNotNull(m_ptr); }
-        
-        template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); }
-        
+        ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }
+
         T* get() const { return m_ptr; }
         
-        void clear() { derefIfNotNull(m_ptr); m_ptr = 0; }
+        void clear();
         PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
 
         T& operator*() const { return *m_ptr; }
@@ -75,9 +75,12 @@ namespace WTF {
         RefPtr& operator=(T*);
         RefPtr& operator=(const PassRefPtr<T>&);
         RefPtr& operator=(const NonNullPassRefPtr<T>&);
-        template <typename U> RefPtr& operator=(const RefPtr<U>&);
-        template <typename U> RefPtr& operator=(const PassRefPtr<U>&);
-        template <typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&);
+#if !HAVE(NULLPTR)
+        RefPtr& operator=(std::nullptr_t) { clear(); return *this; }
+#endif
+        template<typename U> RefPtr& operator=(const RefPtr<U>&);
+        template<typename U> RefPtr& operator=(const PassRefPtr<U>&);
+        template<typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&);
 
         void swap(RefPtr&);
 
@@ -87,17 +90,24 @@ namespace WTF {
         T* m_ptr;
     };
     
-    template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o)
-        : m_ptr(o.releaseRef())
+    template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o)
+        : m_ptr(o.leakRef())
     {
     }
 
-    template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o)
-        : m_ptr(o.releaseRef())
+    template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o)
+        : m_ptr(o.leakRef())
     {
     }
 
-    template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
+    template<typename T> inline void RefPtr<T>::clear()
+    {
+        T* ptr = m_ptr;
+        m_ptr = 0;
+        derefIfNotNull(ptr);
+    }
+
+    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
     {
         T* optr = o.get();
         refIfNotNull(optr);
@@ -107,7 +117,7 @@ namespace WTF {
         return *this;
     }
     
-    template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
+    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
     {
         T* optr = o.get();
         refIfNotNull(optr);
@@ -117,7 +127,7 @@ namespace WTF {
         return *this;
     }
     
-    template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
+    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
     {
         refIfNotNull(optr);
         T* ptr = m_ptr;
@@ -126,89 +136,89 @@ namespace WTF {
         return *this;
     }
 
-    template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
+    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
-    template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o)
+    template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o)
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
-    template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
+    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
-    template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o)
+    template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o)
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
-    template <class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
+    template<class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
     {
         std::swap(m_ptr, o.m_ptr);
     }
 
-    template <class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
+    template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
     {
         a.swap(b);
     }
 
-    template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
+    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
     { 
         return a.get() == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
     { 
         return a.get() == b; 
     }
     
-    template <typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) 
     {
         return a == b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
+    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
     { 
         return a.get() != b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
     {
         return a.get() != b; 
     }
 
-    template <typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
+    template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
     { 
         return a != b.get(); 
     }
     
-    template <typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
+    template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
     { 
         return RefPtr<T>(static_cast<T*>(p.get())); 
     }
 
-    template <typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p)
+    template<typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p)
     { 
         return RefPtr<T>(const_cast<T*>(p.get())); 
     }
 
-    template <typename T> inline T* getPtr(const RefPtr<T>& p)
+    template<typename T> inline T* getPtr(const RefPtr<T>& p)
     {
         return p.get();
     }
index 7f6ebfeaddae442097f3d692cf72203e5decbbe9..dbeabfaea5db460d93f8b81b98f04e5eea6b83b7 100644 (file)
@@ -18,6 +18,9 @@
  *
  */
 
+#ifndef RefPtrHashMap_h
+#define RefPtrHashMap_h
+
 namespace WTF {
 
     // This specialization is a direct copy of HashMap, with overloaded functions
@@ -42,7 +45,8 @@ namespace WTF {
     };
 
     template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
-    class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> : public FastAllocBase {
+    class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> {
+        WTF_MAKE_FAST_ALLOCATED;
     private:
         typedef KeyTraitsArg KeyTraits;
         typedef MappedTraitsArg MappedTraits;
@@ -334,3 +338,5 @@ namespace WTF {
     }
 
 } // namespace WTF
+
+#endif // RefPtrHashMap_h
index 77f25e05f921556bea30f180a9eb5b6eccaa7a4c..a71639012b7229134694808821978015fa0ac5d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2005, 2006, 2007, 2008, 2010 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
 #ifndef RetainPtr_h
 #define RetainPtr_h
 
+#include "HashTraits.h"
+#include "NullPtr.h"
 #include "TypeTraits.h"
 #include <algorithm>
+
+#if USE(CF)
 #include <CoreFoundation/CoreFoundation.h>
+#endif
 
 #ifdef __OBJC__
 #import <Foundation/Foundation.h>
@@ -47,7 +52,7 @@ namespace WTF {
     }
 #endif
 
-    template <typename T> class RetainPtr {
+    template<typename T> class RetainPtr {
     public:
         typedef typename RemovePointer<T>::Type ValueType;
         typedef ValueType* PtrType;
@@ -60,14 +65,19 @@ namespace WTF {
         
         RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
 
+        // Hash table deleted values, which are only constructed and never copied or destroyed.
+        RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+        bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+        
         ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); }
         
-        template <typename U> RetainPtr(const RetainPtr<U>& o) : m_ptr(o.get()) { if (PtrType ptr = m_ptr) CFRetain(ptr); }
+        template<typename U> RetainPtr(const RetainPtr<U>&);
         
         PtrType get() const { return m_ptr; }
-        
-        PtrType releaseRef() { PtrType tmp = m_ptr; m_ptr = 0; return tmp; }
-        
+
+        void clear();
+        PtrType leakRef() WARN_UNUSED_RETURN;
+
         PtrType operator->() const { return m_ptr; }
         
         bool operator!() const { return !m_ptr; }
@@ -77,20 +87,50 @@ namespace WTF {
         operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; }
         
         RetainPtr& operator=(const RetainPtr&);
-        template <typename U> RetainPtr& operator=(const RetainPtr<U>&);
+        template<typename U> RetainPtr& operator=(const RetainPtr<U>&);
         RetainPtr& operator=(PtrType);
-        template <typename U> RetainPtr& operator=(U*);
+        template<typename U> RetainPtr& operator=(U*);
+#if !HAVE(NULLPTR)
+        RetainPtr& operator=(std::nullptr_t) { clear(); return *this; }
+#endif
 
         void adoptCF(PtrType);
         void adoptNS(PtrType);
         
         void swap(RetainPtr&);
 
+        // FIXME: Remove releaseRef once we change all callers to call leakRef instead.
+        PtrType releaseRef() { return leakRef(); }
+
     private:
+        static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
         PtrType m_ptr;
     };
     
-    template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
+    template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o)
+        : m_ptr(o.get())
+    {
+        if (PtrType ptr = m_ptr)
+            CFRetain(ptr);
+    }
+
+    template<typename T> inline void RetainPtr<T>::clear()
+    {
+        if (PtrType ptr = m_ptr) {
+            m_ptr = 0;
+            CFRelease(ptr);
+        }
+    }
+
+    template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef()
+    {
+        PtrType ptr = m_ptr;
+        m_ptr = 0;
+        return ptr;
+    }
+
+    template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o)
     {
         PtrType optr = o.get();
         if (optr)
@@ -102,7 +142,7 @@ namespace WTF {
         return *this;
     }
     
-    template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
+    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o)
     {
         PtrType optr = o.get();
         if (optr)
@@ -114,7 +154,7 @@ namespace WTF {
         return *this;
     }
     
-    template <typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
+    template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr)
     {
         if (optr)
             CFRetain(optr);
@@ -125,7 +165,7 @@ namespace WTF {
         return *this;
     }
 
-    template <typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
+    template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr)
     {
         PtrType ptr = m_ptr;
         m_ptr = optr;
@@ -133,7 +173,7 @@ namespace WTF {
             CFRelease(ptr);
     }
 
-    template <typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
+    template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
     {
         adoptNSReference(optr);
         
@@ -143,7 +183,7 @@ namespace WTF {
             CFRelease(ptr);
     }
     
-    template <typename T> template <typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
+    template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr)
     {
         if (optr)
             CFRetain(optr);
@@ -154,45 +194,58 @@ namespace WTF {
         return *this;
     }
 
-    template <class T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
+    template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o)
     {
         std::swap(m_ptr, o.m_ptr);
     }
 
-    template <class T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
+    template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b)
     {
         a.swap(b);
     }
 
-    template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
+    template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
     { 
         return a.get() == b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
     { 
         return a.get() == b; 
     }
     
-    template <typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) 
+    template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) 
     {
         return a == b.get(); 
     }
     
-    template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
+    template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
     { 
         return a.get() != b.get(); 
     }
 
-    template <typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
+    template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
     {
         return a.get() != b; 
     }
 
-    template <typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
+    template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
     { 
         return a != b.get(); 
     }
+    
+    template<typename P> struct HashTraits<RetainPtr<P> > : SimpleClassHashTraits<RetainPtr<P> > { };
+    
+    template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<P*> {
+        using PtrHash<P*>::hash;
+        static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); }
+        using PtrHash<P*>::equal;
+        static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; }
+        static bool equal(P* a, const RetainPtr<P>& b) { return a == b; }
+        static bool equal(const RetainPtr<P>& a, P* b) { return a == b; }
+    };
+    
+    template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; };
 
 } // namespace WTF
 
diff --git a/wtf/SHA1.cpp b/wtf/SHA1.cpp
new file mode 100644 (file)
index 0000000..e76f6ac
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+// A straightforward SHA-1 implementation based on RFC 3174.
+// http://www.ietf.org/rfc/rfc3174.txt
+// The names of functions and variables (such as "a", "b", and "f") follow notations in RFC 3174.
+
+#include "config.h"
+#include "SHA1.h"
+
+#include "Assertions.h"
+#ifndef NDEBUG
+#include "StringExtras.h"
+#include "text/CString.h"
+#endif
+
+namespace WTF {
+
+#ifdef NDEBUG
+static inline void testSHA1() { }
+#else
+static bool isTestSHA1Done;
+
+static void expectSHA1(CString input, int repeat, CString expected)
+{
+    SHA1 sha1;
+    for (int i = 0; i < repeat; ++i)
+        sha1.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length());
+    Vector<uint8_t, 20> digest;
+    sha1.computeHash(digest);
+    char* buffer = 0;
+    CString actual = CString::newUninitialized(40, buffer);
+    for (size_t i = 0; i < 20; ++i) {
+        snprintf(buffer, 3, "%02X", digest.at(i));
+        buffer += 2;
+    }
+    ASSERT_WITH_MESSAGE(actual == expected, "input: %s, repeat: %d, actual: %s, expected: %s", input.data(), repeat, actual.data(), expected.data());
+}
+
+static void testSHA1()
+{
+    if (isTestSHA1Done)
+        return;
+    isTestSHA1Done = true;
+
+    // Examples taken from sample code in RFC 3174.
+    expectSHA1("abc", 1, "A9993E364706816ABA3E25717850C26C9CD0D89D");
+    expectSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, "84983E441C3BD26EBAAE4AA1F95129E5E54670F1");
+    expectSHA1("a", 1000000, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F");
+    expectSHA1("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452");
+}
+#endif
+
+static inline uint32_t f(int t, uint32_t b, uint32_t c, uint32_t d)
+{
+    ASSERT(t >= 0 && t < 80);
+    if (t < 20)
+        return (b & c) | ((~b) & d);
+    if (t < 40)
+        return b ^ c ^ d;
+    if (t < 60)
+        return (b & c) | (b & d) | (c & d);
+    return b ^ c ^ d;
+}
+
+static inline uint32_t k(int t)
+{
+    ASSERT(t >= 0 && t < 80);
+    if (t < 20)
+        return 0x5a827999;
+    if (t < 40)
+        return 0x6ed9eba1;
+    if (t < 60)
+        return 0x8f1bbcdc;
+    return 0xca62c1d6;
+}
+
+static inline uint32_t rotateLeft(int n, uint32_t x)
+{
+    ASSERT(n >= 0 && n < 32);
+    return (x << n) | (x >> (32 - n));
+}
+
+SHA1::SHA1()
+{
+    // FIXME: Move unit tests somewhere outside the constructor. See bug 55853.
+    testSHA1();
+    reset();
+}
+
+void SHA1::addBytes(const uint8_t* input, size_t length)
+{
+    while (length--) {
+        ASSERT(m_cursor < 64);
+        m_buffer[m_cursor++] = *input++;
+        ++m_totalBytes;
+        if (m_cursor == 64)
+            processBlock();
+    }
+}
+
+void SHA1::computeHash(Vector<uint8_t, 20>& digest)
+{
+    finalize();
+
+    digest.clear();
+    digest.resize(20);
+    for (size_t i = 0; i < 5; ++i) {
+        // Treat hashValue as a big-endian value.
+        uint32_t hashValue = m_hash[i];
+        for (int j = 0; j < 4; ++j) {
+            digest[4 * i + (3 - j)] = hashValue & 0xFF;
+            hashValue >>= 8;
+        }
+    }
+
+    reset();
+}
+
+void SHA1::finalize()
+{
+    ASSERT(m_cursor < 64);
+    m_buffer[m_cursor++] = 0x80;
+    if (m_cursor > 56) {
+        // Pad out to next block.
+        while (m_cursor < 64)
+            m_buffer[m_cursor++] = 0x00;
+        processBlock();
+    }
+
+    for (size_t i = m_cursor; i < 56; ++i)
+        m_buffer[i] = 0x00;
+
+    // Write the length as a big-endian 64-bit value.
+    uint64_t bits = m_totalBytes * 8;
+    for (int i = 0; i < 8; ++i) {
+        m_buffer[56 + (7 - i)] = bits & 0xFF;
+        bits >>= 8;
+    }
+    m_cursor = 64;
+    processBlock();
+}
+
+void SHA1::processBlock()
+{
+    ASSERT(m_cursor == 64);
+
+    uint32_t w[80] = { 0 };
+    for (int t = 0; t < 16; ++t)
+        w[t] = (m_buffer[t * 4] << 24) | (m_buffer[t * 4 + 1] << 16) | (m_buffer[t * 4 + 2] << 8) | m_buffer[t * 4 + 3];
+    for (int t = 16; t < 80; ++t)
+        w[t] = rotateLeft(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]);
+
+    uint32_t a = m_hash[0];
+    uint32_t b = m_hash[1];
+    uint32_t c = m_hash[2];
+    uint32_t d = m_hash[3];
+    uint32_t e = m_hash[4];
+
+    for (int t = 0; t < 80; ++t) {
+        uint32_t temp = rotateLeft(5, a) + f(t, b, c, d) + e + w[t] + k(t);
+        e = d;
+        d = c;
+        c = rotateLeft(30, b);
+        b = a;
+        a = temp;
+    }
+
+    m_hash[0] += a;
+    m_hash[1] += b;
+    m_hash[2] += c;
+    m_hash[3] += d;
+    m_hash[4] += e;
+
+    m_cursor = 0;
+}
+
+void SHA1::reset()
+{
+    m_cursor = 0;
+    m_totalBytes = 0;
+    m_hash[0] = 0x67452301;
+    m_hash[1] = 0xefcdab89;
+    m_hash[2] = 0x98badcfe;
+    m_hash[3] = 0x10325476;
+    m_hash[4] = 0xc3d2e1f0;
+
+    // Clear the buffer after use in case it's sensitive.
+    memset(m_buffer, 0, sizeof(m_buffer));
+}
+
+} // namespace WTF
diff --git a/wtf/SHA1.h b/wtf/SHA1.h
new file mode 100644 (file)
index 0000000..dad6dc8
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 WTF_SHA1_h
+#define WTF_SHA1_h
+
+#include <wtf/Vector.h>
+
+namespace WTF {
+
+class SHA1 {
+public:
+    SHA1();
+
+    void addBytes(const Vector<uint8_t>& input)
+    {
+        addBytes(input.data(), input.size());
+    }
+    void addBytes(const uint8_t* input, size_t length);
+
+    // computeHash has a side effect of resetting the state of the object.
+    void computeHash(Vector<uint8_t, 20>&);
+
+private:
+    void finalize();
+    void processBlock();
+    void reset();
+
+    uint8_t m_buffer[64];
+    size_t m_cursor; // Number of bytes filled in m_buffer (0-64).
+    uint64_t m_totalBytes; // Number of bytes added so far.
+    uint32_t m_hash[5];
+};
+
+} // namespace WTF
+
+using WTF::SHA1;
+
+#endif // WTF_SHA1_h
diff --git a/wtf/SentinelLinkedList.h b/wtf/SentinelLinkedList.h
new file mode 100644 (file)
index 0000000..610d2d2
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+//    A SentinelLinkedList is a linked list with dummy head and tail sentinels,
+//    which allow for branch-less insertion and removal, and removal without a
+//    pointer to the list.
+//    
+//    Requires: Node is a concrete class with:
+//        Node(SentinelTag);
+//        void setPrev(Node*);
+//        Node* prev();
+//        void setNext(Node*);
+//        Node* next();
+
+#ifndef SentinelLinkedList_h
+#define SentinelLinkedList_h
+
+namespace WTF {
+
+enum SentinelTag { Sentinel };
+
+template <typename Node> class SentinelLinkedList {
+public:
+    typedef Node* iterator;
+
+    SentinelLinkedList();
+
+    void push(Node*);
+    static void remove(Node*);
+
+    iterator begin();
+    iterator end();
+
+private:
+    Node m_headSentinel;
+    Node m_tailSentinel;
+};
+
+template <typename Node> inline SentinelLinkedList<Node>::SentinelLinkedList()
+    : m_headSentinel(Sentinel)
+    , m_tailSentinel(Sentinel)
+{
+    m_headSentinel.setNext(&m_tailSentinel);
+    m_headSentinel.setPrev(0);
+
+    m_tailSentinel.setPrev(&m_headSentinel);
+    m_tailSentinel.setNext(0);
+}
+
+template <typename Node> inline typename SentinelLinkedList<Node>::iterator SentinelLinkedList<Node>::begin()
+{
+    return m_headSentinel.next();
+}
+
+template <typename Node> inline typename SentinelLinkedList<Node>::iterator SentinelLinkedList<Node>::end()
+{
+    return &m_tailSentinel;
+}
+
+template <typename Node> inline void SentinelLinkedList<Node>::push(Node* node)
+{
+    ASSERT(node);
+    Node* prev = &m_headSentinel;
+    Node* next = m_headSentinel.next();
+
+    node->setPrev(prev);
+    node->setNext(next);
+
+    prev->setNext(node);
+    next->setPrev(node);
+}
+
+template <typename Node> inline void SentinelLinkedList<Node>::remove(Node* node)
+{
+    Node* prev = node->prev();
+    Node* next = node->next();
+
+    prev->setNext(next);
+    next->setPrev(prev);
+}
+
+}
+
+using WTF::SentinelLinkedList;
+
+#endif
+
diff --git a/wtf/SinglyLinkedList.h b/wtf/SinglyLinkedList.h
new file mode 100644 (file)
index 0000000..c00bf36
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``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 ITS 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 SinglyLinkedList_h
+#define SinglyLinkedList_h
+
+namespace WTF {
+
+template <typename Node> class SinglyLinkedList {
+public:
+    SinglyLinkedList();
+    
+    bool isEmpty();
+
+    void push(Node*);
+    Node* pop();
+
+private:
+    Node* m_head;
+};
+
+template <typename Node> inline SinglyLinkedList<Node>::SinglyLinkedList()
+    : m_head(0)
+{
+}
+
+template <typename Node> inline bool SinglyLinkedList<Node>::isEmpty()
+{
+    return !m_head;
+}
+
+template <typename Node> inline void SinglyLinkedList<Node>::push(Node* node)
+{
+    ASSERT(node);
+    node->setNext(m_head);
+    m_head = node;
+}
+
+template <typename Node> inline Node* SinglyLinkedList<Node>::pop()
+{
+    Node* tmp = m_head;
+    m_head = m_head->next();
+    return tmp;
+}
+
+}
+
+using WTF::SinglyLinkedList;
+
+#endif
diff --git a/wtf/SizeLimits.cpp b/wtf/SizeLimits.cpp
new file mode 100644 (file)
index 0000000..4e481bb
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#include "config.h"
+
+#include <wtf/Assertions.h>
+#include <wtf/CrossThreadRefCounted.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+
+#ifndef NDEBUG
+struct StructWithIntAndTwoBools { int a; bool b; bool c; };
+static const size_t refCountedExtraDebugSize = sizeof(StructWithIntAndTwoBools) - sizeof(int);
+#else
+static const size_t refCountedExtraDebugSize = 0;
+#endif
+
+COMPILE_ASSERT(sizeof(OwnPtr<int>) == sizeof(int*), OwnPtr_should_stay_small);
+COMPILE_ASSERT(sizeof(PassRefPtr<RefCounted<int> >) == sizeof(int*), PassRefPtr_should_stay_small);
+COMPILE_ASSERT(sizeof(RefCounted<int>) == sizeof(int) + refCountedExtraDebugSize, RefCounted_should_stay_small);
+COMPILE_ASSERT(sizeof(RefCountedCustomAllocated<int>) == sizeof(int) + refCountedExtraDebugSize, RefCountedCustomAllocated_should_stay_small);
+COMPILE_ASSERT(sizeof(RefPtr<RefCounted<int> >) == sizeof(int*), RefPtr_should_stay_small);
+COMPILE_ASSERT(sizeof(Vector<int>) == 3 * sizeof(int*), Vector_should_stay_small);
+
+}
diff --git a/wtf/StackBounds.cpp b/wtf/StackBounds.cpp
new file mode 100644 (file)
index 0000000..f2ed57d
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "StackBounds.h"
+
+#if OS(DARWIN)
+
+#include <mach/task.h>
+#include <mach/thread_act.h>
+#include <pthread.h>
+
+#elif OS(WINDOWS)
+
+#include <windows.h>
+
+#elif OS(HAIKU)
+
+#include <OS.h>
+
+#elif OS(SOLARIS)
+
+#include <thread.h>
+
+#elif OS(QNX)
+
+#include <fcntl.h>
+#include <sys/procfs.h>
+#include <stdio.h>
+#include <errno.h>
+
+#elif OS(UNIX)
+
+#include <pthread.h>
+#if HAVE(PTHREAD_NP_H)
+#include <pthread_np.h>
+#endif
+
+#endif
+
+#include <WTFThreadData.h>
+
+namespace WTF {
+
+// Bug 26276 - Need a mechanism to determine stack extent
+//
+// These platforms should now be working correctly:
+//     DARWIN, QNX, UNIX, SYMBIAN
+// These platforms are not:
+//     WINDOWS, SOLARIS, OPENBSD, HAIKU, WINCE
+//
+// FIXME: remove this! - this code unsafely guesses at stack sizes!
+#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD) || OS(HAIKU)
+// Based on the current limit used by the JSC parser, guess the stack size.
+static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024;
+// This method assumes the stack is growing downwards.
+static void* estimateStackBound(void* origin)
+{
+    return static_cast<char*>(origin) - estimatedStackSize;
+}
+#endif
+
+#if OS(DARWIN)
+
+void StackBounds::initialize()
+{
+    pthread_t thread = pthread_self();
+    m_origin = pthread_get_stackaddr_np(thread);
+    m_bound = static_cast<char*>(m_origin) - pthread_get_stacksize_np(thread);
+}
+
+void StackBounds::checkConsistency() const
+{
+#if !ASSERT_DISABLED
+    // Skip consistency check if this StackBounds was initialized
+    // on a different thread than the current thread.
+    const StackBounds* stack = &wtfThreadData().stack();
+    if (stack != this)
+        return;
+
+    void* currentPosition = &currentPosition;
+    ASSERT(m_origin != m_bound);
+    ASSERT(isGrowingDownward()
+           ? (currentPosition < m_origin && currentPosition > m_bound)
+           : (currentPosition > m_origin && currentPosition < m_bound));
+#endif
+}
+
+#elif OS(QNX)
+
+void StackBounds::initialize()
+{
+    void* stackBase = 0;
+    size_t stackSize = 0;
+    pthread_t thread = pthread_self();
+
+    struct _debug_thread_info threadInfo;
+    memset(&threadInfo, 0, sizeof(threadInfo));
+    threadInfo.tid = pthread_self();
+    int fd = open("/proc/self", O_RDONLY);
+    if (fd == -1) {
+        LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);
+        CRASH();
+    }
+    devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
+    close(fd);
+    stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
+    stackSize = threadInfo.stksize;
+    ASSERT(stackBase);
+
+    m_bound = stackBase;
+    m_origin = static_cast<char*>(stackBase) + stackSize;
+}
+
+#elif OS(SOLARIS)
+
+void StackBounds::initialize()
+{
+    stack_t s;
+    thr_stksegment(&s);
+    m_origin = s.ss_sp;
+    m_bound = estimateStackBound(m_origin);
+}
+
+#elif OS(OPENBSD)
+
+void StackBounds::initialize()
+{
+    pthread_t thread = pthread_self();
+    stack_t stack;
+    pthread_stackseg_np(thread, &stack);
+    m_origin = stack.ss_sp;
+    m_bound = estimateStackBound(m_origin);
+}
+
+#elif OS(SYMBIAN)
+
+void StackBounds::initialize()
+{
+    TThreadStackInfo info;
+    RThread thread;
+    thread.StackInfo(info);
+    m_origin = (void*)info.iBase;
+    m_bound = (void*)info.iLimit;
+}
+
+#elif OS(HAIKU)
+
+void StackBounds::initialize()
+{
+    thread_info threadInfo;
+    get_thread_info(find_thread(NULL), &threadInfo);
+    m_origin = threadInfo.stack_end;
+    m_bound = estimateStackBound(m_origin);
+}
+
+#elif OS(UNIX)
+
+void StackBounds::initialize()
+{
+    void* stackBase = 0;
+    size_t stackSize = 0;
+
+    pthread_t thread = pthread_self();
+    pthread_attr_t sattr;
+    pthread_attr_init(&sattr);
+#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
+    // e.g. on FreeBSD 5.4, neundorf@kde.org
+    pthread_attr_get_np(thread, &sattr);
+#else
+    // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
+    pthread_getattr_np(thread, &sattr);
+#endif
+    int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+    (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
+    ASSERT(stackBase);
+    pthread_attr_destroy(&sattr);
+    m_bound = stackBase;
+    m_origin = static_cast<char*>(stackBase) + stackSize;
+}
+
+#elif OS(WINCE)
+
+static bool detectGrowingDownward(void* previousFrame)
+{
+    // Find the address of this stack frame by taking the address of a local variable.
+    int thisFrame;
+    return previousFrame > &thisFrame;
+}
+
+static inline bool isPageWritable(void* page)
+{
+    MEMORY_BASIC_INFORMATION memoryInformation;
+    DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
+
+    // return false on error, including ptr outside memory
+    if (result != sizeof(memoryInformation))
+        return false;
+
+    DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
+    return protect == PAGE_READWRITE
+        || protect == PAGE_WRITECOPY
+        || protect == PAGE_EXECUTE_READWRITE
+        || protect == PAGE_EXECUTE_WRITECOPY;
+}
+
+static inline void* getLowerStackBound(char* currentPage, DWORD pageSize)
+{
+    while (currentPage > 0) {
+        // check for underflow
+        if (currentPage >= reinterpret_cast<char*>(pageSize))
+            currentPage -= pageSize;
+        else
+            currentPage = 0;
+
+        if (!isPageWritable(currentPage))
+            return currentPage + pageSize;
+    }
+
+    return 0;
+}
+
+static inline void* getUpperStackBound(char* currentPage, DWORD pageSize)
+{
+    do {
+        // guaranteed to complete because isPageWritable returns false at end of memory
+        currentPage += pageSize;
+    } while (isPageWritable(currentPage));
+
+    return currentPage - pageSize;
+}
+
+void StackBounds::initialize()
+{
+    // find the address of this stack frame by taking the address of a local variable
+    void* thisFrame = &thisFrame;
+    bool isGrowingDownward = detectGrowingDownward(thisFrame);
+
+    SYSTEM_INFO systemInfo;
+    GetSystemInfo(&systemInfo);
+    DWORD pageSize = systemInfo.dwPageSize;
+
+    // scan all of memory starting from this frame, and return the last writeable page found
+    char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1));
+    void* lowerStackBound = getLowerStackBound(currentPage, pageSize);
+    void* upperStackBound = getUpperStackBound(currentPage, pageSize);
+
+    m_origin = isGrowingDownward ? upperStackBound : lowerStackBound;
+    m_bound = isGrowingDownward ? lowerStackBound : upperStackBound;
+}
+
+#elif OS(WINDOWS)
+
+void StackBounds::initialize()
+{
+#if CPU(X86) && COMPILER(MSVC)
+    // offset 0x18 from the FS segment register gives a pointer to
+    // the thread information block for the current thread
+    NT_TIB* pTib;
+    __asm {
+        MOV EAX, FS:[18h]
+        MOV pTib, EAX
+    }
+    m_origin = static_cast<void*>(pTib->StackBase);
+#elif CPU(X86) && COMPILER(GCC)
+    // offset 0x18 from the FS segment register gives a pointer to
+    // the thread information block for the current thread
+    NT_TIB* pTib;
+    asm ( "movl %%fs:0x18, %0\n"
+          : "=r" (pTib)
+        );
+    m_origin = static_cast<void*>(pTib->StackBase);
+#elif CPU(X86_64)
+    PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
+    m_origin = reinterpret_cast<void*>(pTib->StackBase);
+#else
+#error Need a way to get the stack bounds on this platform (Windows)
+#endif
+    // Looks like we should be able to get pTib->StackLimit
+    m_bound = estimateStackBound(m_origin);
+}
+
+#else
+#error Need a way to get the stack bounds on this platform
+#endif
+
+} // namespace WTF
diff --git a/wtf/StackBounds.h b/wtf/StackBounds.h
new file mode 100644 (file)
index 0000000..dc93f90
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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 COMPUTER, 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 StackBounds_h
+#define StackBounds_h
+
+namespace WTF {
+
+class StackBounds {
+    // recursionCheck() / recursionLimit() tests (by default)
+    // that we are at least this far from the end of the stack.
+    const static size_t s_defaultAvailabilityDelta = 4096;
+
+public:
+    StackBounds()
+        : m_origin(0)
+        , m_bound(0)
+    {
+    }
+
+    static StackBounds currentThreadStackBounds()
+    {
+        StackBounds bounds;
+        bounds.initialize();
+        bounds.checkConsistency();
+        return bounds;
+    }
+
+    void* origin() const
+    {
+        ASSERT(m_origin);
+        return m_origin;
+    }
+
+    void* current() const
+    {
+        checkConsistency();
+        void* currentPosition = &currentPosition;
+        return currentPosition;
+    }
+
+    void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
+    {
+        checkConsistency();
+        return isGrowingDownward()
+            ? static_cast<char*>(m_bound) + minAvailableDelta
+            : static_cast<char*>(m_bound) - minAvailableDelta;
+    }
+
+    bool recursionCheck(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
+    {
+        checkConsistency();
+        return isGrowingDownward()
+            ? current() >= recursionLimit(minAvailableDelta)
+            : current() <= recursionLimit(minAvailableDelta);
+    }
+
+private:
+    void initialize();
+
+
+    bool isGrowingDownward() const
+    {
+        ASSERT(m_origin && m_bound);
+#if OS(WINCE)
+        return m_origin > m_bound;
+#else
+        return true;
+#endif
+    }
+
+    void checkConsistency() const;
+
+    void* m_origin;
+    void* m_bound;
+};
+
+} // namespace WTF
+
+using WTF::StackBounds;
+
+#endif
index 96a929c7ed03d065b88b72551334d821605d1009..a8582e9c29658915d9c17c6cb3603de88a383c72 100644 (file)
 #define STRINGIZE(exp) #exp
 #define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp)
 
+/*
+ * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where
+ * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC:
+ * increases required alignment of target type.
+ *
+ * An implicit or an extra static_cast<void*> bypasses the warning.
+ * For more info see the following bugzilla entries:
+ * - https://bugs.webkit.org/show_bug.cgi?id=38045
+ * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976
+ */
+#if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC)
+template<typename Type>
+bool isPointerTypeAlignmentOkay(Type* ptr)
+{
+    return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type));
+}
+
+template<typename TypePtr>
+TypePtr reinterpret_cast_ptr(void* ptr)
+{
+    ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
+    return reinterpret_cast<TypePtr>(ptr);
+}
+
+template<typename TypePtr>
+TypePtr reinterpret_cast_ptr(const void* ptr)
+{
+    ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr)));
+    return reinterpret_cast<TypePtr>(ptr);
+}
+#else
+#define reinterpret_cast_ptr reinterpret_cast
+#endif
+
 namespace WTF {
 
-    /*
-     * C++'s idea of a reinterpret_cast lacks sufficient cojones.
-     */
-    template<typename TO, typename FROM>
-    TO bitwise_cast(FROM from)
-    {
-        COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal);
-        union {
-            FROM from;
-            TO to;
-        } u;
-        u.from = from;
-        return u.to;
-    }
+/*
+ * C++'s idea of a reinterpret_cast lacks sufficient cojones.
+ */
+template<typename TO, typename FROM>
+inline TO bitwise_cast(FROM from)
+{
+    COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal);
+    union {
+        FROM from;
+        TO to;
+    } u;
+    u.from = from;
+    return u.to;
+}
+
+// Returns a count of the number of bits set in 'bits'.
+inline size_t bitCount(unsigned bits)
+{
+    bits = bits - ((bits >> 1) & 0x55555555);
+    bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
+    return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+}
+
+// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array.
+template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size];
+#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array))
+
+// Efficient implementation that takes advantage of powers of two.
+template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x)
+{
+    COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two);
 
-    // Returns a count of the number of bits set in 'bits'.
-    inline size_t bitCount(unsigned bits)
-    {
-        bits = bits - ((bits >> 1) & 0x55555555);
-        bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
-        return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+    size_t remainderMask = divisor - 1;
+    return (x + remainderMask) & ~remainderMask;
+}
+
+// Binary search algorithm, calls extractKey on pre-sorted elements in array,
+// compares result with key (KeyTypes should be comparable with '--', '<', '>').
+// Optimized for cases where the array contains the key, checked by assertions.
+template<typename ArrayType, typename KeyType, KeyType(*extractKey)(ArrayType*)>
+inline ArrayType* binarySearch(ArrayType* array, size_t size, KeyType key)
+{
+    // The array must contain at least one element (pre-condition, array does conatin key).
+    // If the array only contains one element, no need to do the comparison.
+    while (size > 1) {
+        // Pick an element to check, half way through the array, and read the value.
+        int pos = (size - 1) >> 1;
+        KeyType val = extractKey(&array[pos]);
+        
+        // If the key matches, success!
+        if (val == key)
+            return &array[pos];
+        // The item we are looking for is smaller than the item being check; reduce the value of 'size',
+        // chopping off the right hand half of the array.
+        else if (key < val)
+            size = pos;
+        // Discard all values in the left hand half of the array, up to and including the item at pos.
+        else {
+            size -= (pos + 1);
+            array += (pos + 1);
+        }
+
+        // 'size' should never reach zero.
+        ASSERT(size);
     }
+    
+    // If we reach this point we've chopped down to one element, no need to check it matches
+    ASSERT(size == 1);
+    ASSERT(key == extractKey(&array[0]));
+    return &array[0];
+}
 
 } // namespace WTF
 
-#endif
+using WTF::binarySearch;
+using WTF::bitwise_cast;
+
+#endif // WTF_StdLibExtras_h
index 28e80b8369f3ea4e772d7095e451e7f093eab5f6..371e33bf98ad055c2e233a50ec1fc1c524c7d92c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2010 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 #if HAVE(STRINGS_H) 
 #include <strings.h> 
@@ -43,17 +44,30 @@ inline int snprintf(char* buffer, size_t count, const char* format, ...)
     va_start(args, format);
     result = _vsnprintf(buffer, count, format, args);
     va_end(args);
+
+    // In the case where the string entirely filled the buffer, _vsnprintf will not
+    // null-terminate it, but snprintf must.
+    if (count > 0)
+        buffer[count - 1] = '\0';
+
     return result;
 }
 
-#if COMPILER(MSVC7_OR_LOWER) || OS(WINCE)
-
-inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args)
+inline double wtf_vsnprintf(char* buffer, size_t count, const char* format, va_list args)
 {
-    return _vsnprintf(buffer, count, format, args);
+    int result = _vsnprintf(buffer, count, format, args);
+
+    // In the case where the string entirely filled the buffer, _vsnprintf will not
+    // null-terminate it, but vsnprintf must.
+    if (count > 0)
+        buffer[count - 1] = '\0';
+
+    return result;
 }
 
-#endif
+// Work around a difference in Microsoft's implementation of vsnprintf, where 
+// vsnprintf does not null terminate the buffer. WebKit can rely on the null termination.
+#define vsnprintf(buffer, count, format, args) wtf_vsnprintf(buffer, count, format, args)
 
 #if OS(WINCE)
 
@@ -86,8 +100,7 @@ inline int strcasecmp(const char* s1, const char* s2)
 
 #endif
 
-#if OS(WINDOWS) || OS(LINUX) || OS(SOLARIS)
-// FIXME: should check HAVE_STRNSTR
+#if !HAVE(STRNSTR)
 
 inline char* strnstr(const char* buffer, const char* target, size_t bufferLength)
 {
diff --git a/wtf/StringHashFunctions.h b/wtf/StringHashFunctions.h
deleted file mode 100644 (file)
index 07f117f..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2005, 2006, 2008, 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef WTF_StringHashFunctions_h
-#define WTF_StringHashFunctions_h
-
-#include <wtf/unicode/Unicode.h>
-
-namespace WTF {
-
-// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
-static const unsigned stringHashingStartValue = 0x9e3779b9U;
-
-// stringHash methods based on Paul Hsieh's SuperFastHash.
-// http://www.azillionmonkeys.com/qed/hash.html
-// char* data is interpreted as latin-encoded (zero extended to 16 bits).
-
-inline unsigned stringHash(const UChar* data, unsigned length)
-{
-    unsigned hash = WTF::stringHashingStartValue;
-    unsigned rem = length & 1;
-    length >>= 1;
-
-    // Main loop
-    for (; length > 0; length--) {
-        hash += data[0];
-        unsigned tmp = (data[1] << 11) ^ hash;
-        hash = (hash << 16) ^ tmp;
-        data += 2;
-        hash += hash >> 11;
-    }
-
-    // Handle end case
-    if (rem) {
-        hash += data[0];
-        hash ^= hash << 11;
-        hash += hash >> 17;
-    }
-
-    // Force "avalanching" of final 127 bits
-    hash ^= hash << 3;
-    hash += hash >> 5;
-    hash ^= hash << 2;
-    hash += hash >> 15;
-    hash ^= hash << 10;
-
-    hash &= 0x7fffffff;
-
-    // this avoids ever returning a hash code of 0, since that is used to
-    // signal "hash not computed yet", using a value that is likely to be
-    // effectively the same as 0 when the low bits are masked
-    if (hash == 0)
-        hash = 0x40000000;
-
-    return hash;
-}
-
-inline unsigned stringHash(const char* data, unsigned length)
-{
-    unsigned hash = WTF::stringHashingStartValue;
-    unsigned rem = length & 1;
-    length >>= 1;
-
-    // Main loop
-    for (; length > 0; length--) {
-        hash += static_cast<unsigned char>(data[0]);
-        unsigned tmp = (static_cast<unsigned char>(data[1]) << 11) ^ hash;
-        hash = (hash << 16) ^ tmp;
-        data += 2;
-        hash += hash >> 11;
-    }
-
-    // Handle end case
-    if (rem) {
-        hash += static_cast<unsigned char>(data[0]);
-        hash ^= hash << 11;
-        hash += hash >> 17;
-    }
-
-    // Force "avalanching" of final 127 bits
-    hash ^= hash << 3;
-    hash += hash >> 5;
-    hash ^= hash << 2;
-    hash += hash >> 15;
-    hash ^= hash << 10;
-
-    hash &= 0x7fffffff;
-
-    // this avoids ever returning a hash code of 0, since that is used to
-    // signal "hash not computed yet", using a value that is likely to be
-    // effectively the same as 0 when the low bits are masked
-    if (hash == 0)
-        hash = 0x40000000;
-
-    return hash;
-}
-
-inline unsigned stringHash(const char* data)
-{
-    unsigned hash = WTF::stringHashingStartValue;
-
-    // Main loop
-    for (;;) {
-        unsigned char b0 = data[0];
-        if (!b0)
-            break;
-        unsigned char b1 = data[1];
-        if (!b1) {
-            hash += b0;
-            hash ^= hash << 11;
-            hash += hash >> 17;
-            break;
-        }
-        hash += b0;
-        unsigned tmp = (b1 << 11) ^ hash;
-        hash = (hash << 16) ^ tmp;
-        data += 2;
-        hash += hash >> 11;
-    }
-
-    // Force "avalanching" of final 127 bits.
-    hash ^= hash << 3;
-    hash += hash >> 5;
-    hash ^= hash << 2;
-    hash += hash >> 15;
-    hash ^= hash << 10;
-
-    hash &= 0x7fffffff;
-
-    // This avoids ever returning a hash code of 0, since that is used to
-    // signal "hash not computed yet", using a value that is likely to be
-    // effectively the same as 0 when the low bits are masked.
-    if (hash == 0)
-        hash = 0x40000000;
-
-    return hash;
-}
-
-} // namespace WTF
-
-#endif // WTF_StringHashFunctions_h
diff --git a/wtf/StringHasher.h b/wtf/StringHasher.h
new file mode 100644 (file)
index 0000000..5a2c36c
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2005, 2006, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef WTF_StringHasher_h
+#define WTF_StringHasher_h
+
+#include <wtf/unicode/Unicode.h>
+
+namespace WTF {
+
+// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's
+static const unsigned stringHashingStartValue = 0x9e3779b9U;
+
+// Paul Hsieh's SuperFastHash
+// http://www.azillionmonkeys.com/qed/hash.html
+// char* data is interpreted as latin-encoded (zero extended to 16 bits).
+class StringHasher {
+public:
+    inline StringHasher()
+        : m_hash(stringHashingStartValue)
+        , m_hasPendingCharacter(false)
+        , m_pendingCharacter(0)
+    {
+    }
+
+    inline void addCharacters(UChar a, UChar b)
+    {
+        ASSERT(!m_hasPendingCharacter);
+        addCharactersToHash(a, b);
+    }
+
+    inline void addCharacter(UChar ch)
+    {
+        if (m_hasPendingCharacter) {
+            addCharactersToHash(m_pendingCharacter, ch);
+            m_hasPendingCharacter = false;
+            return;
+        }
+
+        m_pendingCharacter = ch;
+        m_hasPendingCharacter = true;
+    }
+
+    inline unsigned hash() const
+    {
+        unsigned result = m_hash;
+
+        // Handle end case.
+        if (m_hasPendingCharacter) {
+            result += m_pendingCharacter;
+            result ^= result << 11;
+            result += result >> 17;
+        }
+
+        // Force "avalanching" of final 31 bits.
+        result ^= result << 3;
+        result += result >> 5;
+        result ^= result << 2;
+        result += result >> 15;
+        result ^= result << 10;
+
+        // First bit is used in UStringImpl for m_isIdentifier.
+        result &= 0x7fffffff;
+
+        // This avoids ever returning a hash code of 0, since that is used to
+        // signal "hash not computed yet", using a value that is likely to be
+        // effectively the same as 0 when the low bits are masked.
+        if (!result)
+            return 0x40000000;
+
+        return result;
+    }
+
+    template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data, unsigned length)
+    {
+        StringHasher hasher;
+        bool rem = length & 1;
+        length >>= 1;
+
+        while (length--) {
+            hasher.addCharacters(Converter(data[0]), Converter(data[1]));
+            data += 2;
+        }
+
+        if (rem)
+            hasher.addCharacter(Converter(*data));
+
+        return hasher.hash();
+    }
+
+    template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data)
+    {
+        StringHasher hasher;
+
+        while (true) {
+            UChar b0 = Converter(*data++);
+            if (!b0)
+                break;
+            UChar b1 = Converter(*data++);
+            if (!b1) {
+                hasher.addCharacter(b0);
+                break;
+            }
+
+            hasher.addCharacters(b0, b1);
+        }
+
+        return hasher.hash();
+    }
+
+    template<typename T> static inline unsigned computeHash(const T* data, unsigned length)
+    {
+        return computeHash<T, defaultCoverter>(data, length);
+    }
+
+    template<typename T> static inline unsigned computeHash(const T* data)
+    {
+        return computeHash<T, defaultCoverter>(data);
+    }
+
+    template<size_t length> static inline unsigned hashMemory(const void* data)
+    {
+        COMPILE_ASSERT(!(length % 4), length_must_be_a_multible_of_four);
+        return computeHash<UChar>(static_cast<const UChar*>(data), length / sizeof(UChar));
+    }
+
+    static inline unsigned hashMemory(const void* data, unsigned size)
+    {
+        ASSERT(!(size % 2));
+        return computeHash<UChar>(static_cast<const UChar*>(data), size / sizeof(UChar));
+    }
+
+private:
+    static inline UChar defaultCoverter(UChar ch)
+    {
+        return ch;
+    }
+
+    static inline UChar defaultCoverter(char ch)
+    {
+        return static_cast<unsigned char>(ch);
+    }
+
+    inline void addCharactersToHash(UChar a, UChar b)
+    {
+        m_hash += a;
+        unsigned tmp = (b << 11) ^ m_hash;
+        m_hash = (m_hash << 16) ^ tmp;
+        m_hash += m_hash >> 11;
+    }
+
+    unsigned m_hash;
+    bool m_hasPendingCharacter;
+    UChar m_pendingCharacter;
+};
+
+} // namespace WTF
+
+using WTF::StringHasher;
+
+#endif // WTF_StringHasher_h
index 3f56c24bbe1038a5e54abbebc9f174a8be323a1e..99bdc400e7299a81edd1306e68da82769f09ab0c 100644 (file)
@@ -72,7 +72,7 @@ class TCMalloc_PageMap1 {
 
   // Ensure that the map contains initialized entries "x .. x+n-1".
   // Returns true if successful, false if we could not allocate memory.
-  bool Ensure(Number x, size_t n) {
+  bool Ensure(Number, size_t) {
     // Nothing to do since flat array was allocate at start
     return true;
   }
index 8a73e135fb7d03f279d396744eada6fbdb8f2918..81b7d0cae94a02739e0a0f912e51cbf7151a4a4e 100644 (file)
@@ -1,4 +1,5 @@
 // Copyright (c) 2005, 2006, Google Inc.
+// Copyright (c) 2010, Patrick Gansterer <paroga@paroga.com>
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
@@ -37,8 +38,6 @@
 
 #include <time.h>       /* For nanosleep() */
 
-#include <sched.h>      /* For sched_yield() */
-
 #if HAVE(STDINT_H)
 #include <stdint.h>
 #elif HAVE(INTTYPES_H)
@@ -52,6 +51,8 @@
 #define WIN32_LEAN_AND_MEAN
 #endif
 #include <windows.h>
+#else
+#include <sched.h>      /* For sched_yield() */
 #endif
 
 static void TCMalloc_SlowLock(volatile unsigned int* lockword);
@@ -134,7 +135,12 @@ struct TCMalloc_SpinLock {
 #define SPINLOCK_INITIALIZER { 0 }
 
 static void TCMalloc_SlowLock(volatile unsigned int* lockword) {
-  sched_yield();        // Yield immediately since fast path failed
+// Yield immediately since fast path failed
+#if OS(WINDOWS)
+  Sleep(0);
+#else
+  sched_yield();
+#endif
   while (true) {
     int r;
 #if COMPILER(GCC)
@@ -189,6 +195,44 @@ static void TCMalloc_SlowLock(volatile unsigned int* lockword) {
   }
 }
 
+#elif OS(WINDOWS)
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+static void TCMalloc_SlowLock(LPLONG lockword);
+
+// The following is a struct so that it can be initialized at compile time
+struct TCMalloc_SpinLock {
+
+    inline void Lock() {
+        if (InterlockedExchange(&m_lockword, 1))
+            TCMalloc_SlowLock(&m_lockword);
+    }
+
+    inline void Unlock() {
+        InterlockedExchange(&m_lockword, 0);
+    }
+
+    inline bool IsHeld() const {
+        return m_lockword != 0;
+    }
+
+    inline void Init() { m_lockword = 0; }
+
+    LONG m_lockword;
+};
+
+#define SPINLOCK_INITIALIZER { 0 }
+
+static void TCMalloc_SlowLock(LPLONG lockword) {
+    Sleep(0);        // Yield immediately since fast path failed
+    while (InterlockedExchange(lockword, 1))
+        Sleep(2);
+}
+
 #else
 
 #include <pthread.h>
index c46ff311f1cfd29bd11d1b5768de3908ae824d7f..3cb59e8808ecee7b041427233e7925d9c7b71150 100644 (file)
 // Author: Sanjay Ghemawat
 
 #include "config.h"
+#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
 #include "TCSystemAlloc.h"
 
 #include <algorithm>
-#include <fcntl.h>
 #include "Assertions.h"
 #include "TCSpinLock.h"
 #include "UnusedParam.h"
@@ -520,3 +520,6 @@ void TCMalloc_SystemCommit(void* start, size_t length)
 // declared in TCSystemAlloc.h
 
 #endif
+
+#endif // #if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
+
diff --git a/wtf/ThreadFunctionInvocation.h b/wtf/ThreadFunctionInvocation.h
new file mode 100644 (file)
index 0000000..f1e1472
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007, 2008 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 ThreadFunctionInvocation_h
+#define ThreadFunctionInvocation_h
+
+namespace WTF {
+
+typedef void* (*ThreadFunction)(void* argument);
+
+struct ThreadFunctionInvocation {
+    ThreadFunctionInvocation(ThreadFunction function, void* data)
+        : function(function)
+        , data(data)
+    {
+    }
+
+    ThreadFunction function;
+    void* data;
+};
+
+} // namespace WTF
+
+#endif // ThreadFunctionInvocation_h
index 3af87a8aa3cae7067d156786f44c2976f451611d..ed1ba2cc0285af2b196e66c77bcb9cd3b62cb18e 100644 (file)
 #ifndef ThreadIdentifierDataPthreads_h
 #define ThreadIdentifierDataPthreads_h
 
-#include <wtf/Noncopyable.h>
 #include <wtf/Threading.h>
 
 namespace WTF {
 
 // Holds ThreadIdentifier in the thread-specific storage and employs pthreads-specific 2-pass destruction to reliably remove
 // ThreadIdentifier from threadMap. It assumes regular ThreadSpecific types don't use multiple-pass destruction.
-class ThreadIdentifierData : public Noncopyable {
+class ThreadIdentifierData {
+    WTF_MAKE_NONCOPYABLE(ThreadIdentifierData);
 public:
     ~ThreadIdentifierData();
 
diff --git a/wtf/ThreadSafeRefCounted.h b/wtf/ThreadSafeRefCounted.h
new file mode 100644 (file)
index 0000000..ca11db3
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
+ *
+ * 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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.
+ *
+ *
+ * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
+ * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
+ * is virtually identical to the Apple license above but is included here for completeness.
+ *
+ * Boost Software License - Version 1.0 - August 17th, 2003
+ * 
+ * Permission is hereby granted, free of charge, to any person or organization
+ * obtaining a copy of the software and accompanying documentation covered by
+ * this license (the "Software") to use, reproduce, display, distribute,
+ * execute, and transmit the Software, and to prepare derivative works of the
+ * Software, and to permit third-parties to whom the Software is furnished to
+ * do so, all subject to the following:
+ * 
+ * The copyright notices in the Software and this entire statement, including
+ * the above license grant, this restriction and the following disclaimer,
+ * must be included in all copies of the Software, in whole or in part, and
+ * all derivative works of the Software, unless such copies or derivative
+ * works are solely in the form of machine-executable object code generated by
+ * a source language processor.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef ThreadSafeRefCounted_h
+#define ThreadSafeRefCounted_h
+
+#include "Platform.h"
+
+#include <wtf/Atomics.h>
+#include <wtf/DynamicAnnotations.h>
+#include <wtf/ThreadingPrimitives.h>
+
+namespace WTF {
+
+class ThreadSafeRefCountedBase {
+    WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ThreadSafeRefCountedBase(int initialRefCount = 1)
+        : m_refCount(initialRefCount)
+    {
+    }
+
+    void ref()
+    {
+#if USE(LOCKFREE_THREADSAFEREFCOUNTED)
+        atomicIncrement(&m_refCount);
+#else
+        MutexLocker locker(m_mutex);
+        ++m_refCount;
+#endif
+    }
+
+    bool hasOneRef()
+    {
+        return refCount() == 1;
+    }
+
+    int refCount() const
+    {
+#if !USE(LOCKFREE_THREADSAFEREFCOUNTED)
+        MutexLocker locker(m_mutex);
+#endif
+        return static_cast<int const volatile &>(m_refCount);
+    }
+
+protected:
+    // Returns whether the pointer should be freed or not.
+    bool derefBase()
+    {
+#if USE(LOCKFREE_THREADSAFEREFCOUNTED)
+        WTF_ANNOTATE_HAPPENS_BEFORE(&m_refCount);
+        if (atomicDecrement(&m_refCount) <= 0) {
+            WTF_ANNOTATE_HAPPENS_AFTER(&m_refCount);
+            return true;
+        }
+#else
+        int refCount;
+        {
+            MutexLocker locker(m_mutex);
+            --m_refCount;
+            refCount = m_refCount;
+        }
+        if (refCount <= 0)
+            return true;
+#endif
+        return false;
+    }
+
+private:
+    template<class T>
+    friend class CrossThreadRefCounted;
+
+    int m_refCount;
+#if !USE(LOCKFREE_THREADSAFEREFCOUNTED)
+    mutable Mutex m_mutex;
+#endif
+};
+
+template<class T> class ThreadSafeRefCounted : public ThreadSafeRefCountedBase {
+public:
+    void deref()
+    {
+        if (derefBase())
+            delete static_cast<T*>(this);
+    }
+
+protected:
+    ThreadSafeRefCounted()
+    {
+    }
+};
+
+} // namespace WTF
+
+using WTF::ThreadSafeRefCounted;
+
+#endif // ThreadSafeRefCounted_h
diff --git a/wtf/ThreadSafeShared.h b/wtf/ThreadSafeShared.h
deleted file mode 100644 (file)
index 688747e..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com)
- *
- * 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. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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.
- *
- *
- * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based
- * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license
- * is virtually identical to the Apple license above but is included here for completeness.
- *
- * Boost Software License - Version 1.0 - August 17th, 2003
- * 
- * Permission is hereby granted, free of charge, to any person or organization
- * obtaining a copy of the software and accompanying documentation covered by
- * this license (the "Software") to use, reproduce, display, distribute,
- * execute, and transmit the Software, and to prepare derivative works of the
- * Software, and to permit third-parties to whom the Software is furnished to
- * do so, all subject to the following:
- * 
- * The copyright notices in the Software and this entire statement, including
- * the above license grant, this restriction and the following disclaimer,
- * must be included in all copies of the Software, in whole or in part, and
- * all derivative works of the Software, unless such copies or derivative
- * works are solely in the form of machine-executable object code generated by
- * a source language processor.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
- * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
- * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef ThreadSafeShared_h
-#define ThreadSafeShared_h
-
-#include "Platform.h"
-
-#include <wtf/Atomics.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/ThreadingPrimitives.h>
-
-namespace WTF {
-
-class ThreadSafeSharedBase : public Noncopyable {
-public:
-    ThreadSafeSharedBase(int initialRefCount = 1)
-        : m_refCount(initialRefCount)
-    {
-    }
-
-    void ref()
-    {
-#if USE(LOCKFREE_THREADSAFESHARED)
-        atomicIncrement(&m_refCount);
-#else
-        MutexLocker locker(m_mutex);
-        ++m_refCount;
-#endif
-    }
-
-    bool hasOneRef()
-    {
-        return refCount() == 1;
-    }
-
-    int refCount() const
-    {
-#if !USE(LOCKFREE_THREADSAFESHARED)
-        MutexLocker locker(m_mutex);
-#endif
-        return static_cast<int const volatile &>(m_refCount);
-    }
-
-protected:
-    // Returns whether the pointer should be freed or not.
-    bool derefBase()
-    {
-#if USE(LOCKFREE_THREADSAFESHARED)
-        if (atomicDecrement(&m_refCount) <= 0)
-            return true;
-#else
-        int refCount;
-        {
-            MutexLocker locker(m_mutex);
-            --m_refCount;
-            refCount = m_refCount;
-        }
-        if (refCount <= 0)
-            return true;
-#endif
-        return false;
-    }
-
-private:
-    template<class T>
-    friend class CrossThreadRefCounted;
-
-    int m_refCount;
-#if !USE(LOCKFREE_THREADSAFESHARED)
-    mutable Mutex m_mutex;
-#endif
-};
-
-template<class T> class ThreadSafeShared : public ThreadSafeSharedBase {
-public:
-    ThreadSafeShared(int initialRefCount = 1)
-        : ThreadSafeSharedBase(initialRefCount)
-    {
-    }
-
-    void deref()
-    {
-        if (derefBase())
-            delete static_cast<T*>(this);
-    }
-};
-
-} // namespace WTF
-
-using WTF::ThreadSafeShared;
-
-#endif // ThreadSafeShared_h
index 7e5679f9649ffcef42ebaa7e9779c8383f329fc8..0aeee132beb98c2ec37b411dfd6bef1855b05d81 100644 (file)
 #include <pthread.h>
 #elif PLATFORM(QT)
 #include <QThreadStorage>
+#elif PLATFORM(GTK)
+#include <glib.h>
 #elif OS(WINDOWS)
 #include <windows.h>
 #endif
 
 namespace WTF {
 
-#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
 // ThreadSpecificThreadExit should be called each time when a thread is detached.
 // This is done automatically for threads created with WTF::createThread.
 void ThreadSpecificThreadExit();
 #endif
 
-template<typename T> class ThreadSpecific : public Noncopyable {
+template<typename T> class ThreadSpecific {
+    WTF_MAKE_NONCOPYABLE(ThreadSpecific);
 public:
     ThreadSpecific();
     T* operator->();
     operator T*();
     T& operator*();
-    ~ThreadSpecific();
+
+    void replace(T*);
 
 private:
-#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
     friend void ThreadSpecificThreadExit();
 #endif
+
+    // Not implemented. It's technically possible to destroy a thread specific key, but one would need
+    // to make sure that all values have been destroyed already (usually, that all threads that used it
+    // have exited). It's unlikely that any user of this call will be in that situation - and having
+    // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly.
+    ~ThreadSpecific();
     
     T* get();
     void set(T*);
     void static destroy(void* ptr);
 
-#if USE(PTHREADS) || PLATFORM(QT) || OS(WINDOWS)
-    struct Data : Noncopyable {
+#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(GTK) || OS(WINDOWS)
+    struct Data {
+        WTF_MAKE_NONCOPYABLE(Data);
+    public:
         Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {}
 #if PLATFORM(QT)
         ~Data() { owner->destroy(this); }
@@ -85,7 +97,7 @@ private:
 
         T* value;
         ThreadSpecific<T>* owner;
-#if !USE(PTHREADS) && !PLATFORM(QT)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK)
         void (*destructor)(void*);
 #endif
     };
@@ -98,6 +110,8 @@ private:
     pthread_key_t m_key;
 #elif PLATFORM(QT)
     QThreadStorage<Data*> m_key;
+#elif PLATFORM(GTK)
+    GStaticPrivate m_key;
 #elif OS(WINDOWS)
     int m_index;
 #endif
@@ -111,11 +125,6 @@ inline ThreadSpecific<T>::ThreadSpecific()
 {
 }
 
-template<typename T>
-inline ThreadSpecific<T>::~ThreadSpecific()
-{
-}
-
 template<typename T>
 inline T* ThreadSpecific<T>::get()
 {
@@ -138,12 +147,6 @@ inline ThreadSpecific<T>::ThreadSpecific()
         CRASH();
 }
 
-template<typename T>
-inline ThreadSpecific<T>::~ThreadSpecific()
-{
-    pthread_key_delete(m_key); // Does not invoke destructor functions.
-}
-
 template<typename T>
 inline T* ThreadSpecific<T>::get()
 {
@@ -166,15 +169,32 @@ inline ThreadSpecific<T>::ThreadSpecific()
 }
 
 template<typename T>
-inline ThreadSpecific<T>::~ThreadSpecific()
+inline T* ThreadSpecific<T>::get()
+{
+    Data* data = static_cast<Data*>(m_key.localData());
+    return data ? data->value : 0;
+}
+
+template<typename T>
+inline void ThreadSpecific<T>::set(T* ptr)
+{
+    ASSERT(!get());
+    Data* data = new Data(ptr, this);
+    m_key.setLocalData(data);
+}
+
+#elif PLATFORM(GTK)
+
+template<typename T>
+inline ThreadSpecific<T>::ThreadSpecific()
 {
-    // Does not invoke destructor functions. QThreadStorage will do it
+    g_static_private_init(&m_key);
 }
 
 template<typename T>
 inline T* ThreadSpecific<T>::get()
 {
-    Data* data = static_cast<Data*>(m_key.localData());
+    Data* data = static_cast<Data*>(g_static_private_get(&m_key));
     return data ? data->value : 0;
 }
 
@@ -183,7 +203,7 @@ inline void ThreadSpecific<T>::set(T* ptr)
 {
     ASSERT(!get());
     Data* data = new Data(ptr, this);
-    m_key.setLocalData(data);
+    g_static_private_set(&m_key, data, destroy);
 }
 
 #elif OS(WINDOWS)
@@ -253,6 +273,9 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
     // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor.
     // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it.
     pthread_setspecific(data->owner->m_key, ptr);
+#elif PLATFORM(GTK)
+    // See comment as above
+    g_static_private_set(&data->owner->m_key, data, 0);
 #endif
 #if PLATFORM(QT)
     // See comment as above
@@ -266,6 +289,8 @@ inline void ThreadSpecific<T>::destroy(void* ptr)
     pthread_setspecific(data->owner->m_key, 0);
 #elif PLATFORM(QT)
     // Do nothing here
+#elif PLATFORM(GTK)
+    g_static_private_set(&data->owner->m_key, 0, 0);
 #elif OS(WINDOWS)
     TlsSetValue(tlsKeys()[data->owner->m_index], 0);
 #else
@@ -285,7 +310,7 @@ inline ThreadSpecific<T>::operator T*()
     if (!ptr) {
         // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls
         // needs to access the value, to avoid recursion.
-        ptr = static_cast<T*>(fastMalloc(sizeof(T)));
+        ptr = static_cast<T*>(fastZeroedMalloc(sizeof(T)));
         set(ptr);
         new (ptr) T;
     }
@@ -304,6 +329,17 @@ inline T& ThreadSpecific<T>::operator*()
     return *operator T*();
 }
 
+template<typename T>
+inline void ThreadSpecific<T>::replace(T* newPtr)
+{
+    ASSERT(newPtr);
+    Data* data = static_cast<Data*>(pthread_getspecific(m_key));
+    ASSERT(data);
+    data->value->~T();
+    fastFree(data->value);
+    data->value = newPtr;
+}
+
 }
 
 #endif
index f2c0cad95766558f0f69e2457490fea8bf558e45..d72996a7a0ca0239a146118d3e05b1e681ad5631 100644 (file)
@@ -21,7 +21,6 @@
 #include "config.h"
 
 #include "ThreadSpecific.h"
-#include <wtf/Noncopyable.h>
 
 #if USE(PTHREADS)
 #error This file should not be compiled by ports that do not use Windows native ThreadSpecific implementation.
index 49de59ec00ae509abaa56b757fdf953532f7697b..f2e0565e996258f7886e03ad44f890d2d7b6ceec 100644 (file)
@@ -30,7 +30,9 @@
 
 namespace WTF {
 
-struct NewThreadContext : FastAllocBase {
+struct NewThreadContext {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
         : entryPoint(entryPoint)
         , data(data)
index 415a8fc83f6d8157ea4c8a396062c03eb444a670..b6f8c241681ee3232bac3211d450e5bd13a8305d 100644 (file)
@@ -67,7 +67,7 @@
 #include <wtf/Locker.h>
 #include <wtf/MainThread.h>
 #include <wtf/Noncopyable.h>
-#include <wtf/ThreadSafeShared.h>
+#include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/ThreadingPrimitives.h>
 
 // For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc).
@@ -101,6 +101,7 @@ ThreadIdentifier currentThread();
 int waitForThreadCompletion(ThreadIdentifier, void**);
 void detachThread(ThreadIdentifier);
 
+void yield();
 
 void lockAtomicallyInitializedStaticMutex();
 void unlockAtomicallyInitializedStaticMutex();
@@ -112,5 +113,6 @@ using WTF::createThread;
 using WTF::currentThread;
 using WTF::detachThread;
 using WTF::waitForThreadCompletion;
+using WTF::yield;
 
 #endif // Threading_h
index 66801c0b8466baf112f05cec7812ab9515c60c9b..831a99e26ff5e43e98b9b88435d41a0284acdab0 100644 (file)
@@ -34,6 +34,7 @@
 #include "Platform.h"
 
 #include <wtf/Assertions.h>
+#include <wtf/FastAllocBase.h>
 #include <wtf/Locker.h>
 #include <wtf/Noncopyable.h>
 
@@ -45,8 +46,6 @@
 #include <pthread.h>
 #elif PLATFORM(GTK)
 #include "GOwnPtr.h"
-typedef struct _GMutex GMutex;
-typedef struct _GCond GCond;
 #endif
 
 #if PLATFORM(QT)
@@ -98,7 +97,8 @@ typedef void* PlatformReadWriteLock;
 typedef void* PlatformCondition;
 #endif
     
-class Mutex : public Noncopyable {
+class Mutex {
+    WTF_MAKE_NONCOPYABLE(Mutex); WTF_MAKE_FAST_ALLOCATED;
 public:
     Mutex();
     ~Mutex();
@@ -115,7 +115,8 @@ private:
 
 typedef Locker<Mutex> MutexLocker;
 
-class ReadWriteLock : public Noncopyable {
+class ReadWriteLock {
+    WTF_MAKE_NONCOPYABLE(ReadWriteLock);
 public:
     ReadWriteLock();
     ~ReadWriteLock();
@@ -132,7 +133,8 @@ private:
     PlatformReadWriteLock m_readWriteLock;
 };
 
-class ThreadCondition : public Noncopyable {
+class ThreadCondition {
+    WTF_MAKE_NONCOPYABLE(ThreadCondition);
 public:
     ThreadCondition();
     ~ThreadCondition();
@@ -148,10 +150,20 @@ private:
     PlatformCondition m_condition;
 };
 
+#if OS(WINDOWS)
+// The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime().
+// Returns an interval in milliseconds suitable for passing to one of the Win32 wait functions (e.g., ::WaitForSingleObject).
+DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime);
+#endif
+
 } // namespace WTF
 
 using WTF::Mutex;
 using WTF::MutexLocker;
 using WTF::ThreadCondition;
 
+#if OS(WINDOWS)
+using WTF::absoluteTimeToWaitTimeoutInterval;
+#endif
+
 #endif // ThreadingPrimitives_h
index f468ce2d72350e6f13483e48f6a7e73105c423e4..916aa3656dbac7f383f63e743ffeb6e2810ddec5 100644 (file)
 
 #if !COMPILER(MSVC)
 #include <limits.h>
+#include <sched.h>
 #include <sys/time.h>
 #endif
 
 #if OS(ANDROID)
-#include "jni_utility.h"
+#include "JNIUtility.h"
+#include "ThreadFunctionInvocation.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#endif
+
+#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD)
+#include <objc/objc-auto.h>
 #endif
 
 namespace WTF {
@@ -135,38 +143,34 @@ void clearPthreadHandleForIdentifier(ThreadIdentifier id)
 }
 
 #if OS(ANDROID)
-// On the Android platform, threads must be registered with the VM before they run.
-struct ThreadData {
-    ThreadFunction entryPoint;
-    void* arg;
-};
-
 static void* runThreadWithRegistration(void* arg)
 {
-    ThreadData* data = static_cast<ThreadData*>(arg);
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(arg));
     JavaVM* vm = JSC::Bindings::getJavaVM();
     JNIEnv* env;
     void* ret = 0;
     if (vm->AttachCurrentThread(&env, 0) == JNI_OK) {
-        ret = data->entryPoint(data->arg);
+        ret = invocation->function(invocation->data);
         vm->DetachCurrentThread();
     }
-    delete data;
     return ret;
 }
 
 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
 {
     pthread_t threadHandle;
-    ThreadData* threadData = new ThreadData();
-    threadData->entryPoint = entryPoint;
-    threadData->arg = data;
 
-    if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) {
+    // On the Android platform, threads must be registered with the VM before they run.
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
+
+    if (pthread_create(&threadHandle, 0, runThreadWithRegistration, invocation.get())) {
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
-        delete threadData;
         return 0;
     }
+
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
+
     return establishIdentifierForPthreadHandle(threadHandle);
 }
 #else
@@ -190,6 +194,12 @@ void initializeCurrentThreadInternal(const char* threadName)
     UNUSED_PARAM(threadName);
 #endif
 
+#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD)
+    // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C
+    // garbage collector in case API implementations use garbage-collected memory.
+    objc_registerThreadWithCollector();
+#endif
+
     ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
     ASSERT(id);
     ThreadIdentifierData::initialize(id);
@@ -221,6 +231,11 @@ void detachThread(ThreadIdentifier threadID)
     pthread_detach(pthreadHandle);
 }
 
+void yield()
+{
+    sched_yield();
+}
+
 ThreadIdentifier currentThread()
 {
     ThreadIdentifier id = ThreadIdentifierData::identifier();
@@ -235,7 +250,13 @@ ThreadIdentifier currentThread()
 
 Mutex::Mutex()
 {
-    pthread_mutex_init(&m_mutex, NULL);
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
+
+    pthread_mutex_init(&m_mutex, &attr);
+
+    pthread_mutexattr_destroy(&attr);
 }
 
 Mutex::~Mutex()
index c16be5aa86de3c8b1ad7de92bbfe19568bd7a8ee..c452205c55cc213a6f91e9ab5c6cc6824d19cf26 100644 (file)
 #include "Threading.h"
 
 #include "MainThread.h"
+#include "ThreadFunctionInvocation.h"
+#include <windows.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/HashMap.h>
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RandomNumberSeed.h>
+
 #if !USE(PTHREADS) && OS(WINDOWS)
 #include "ThreadSpecific.h"
 #endif
+
 #if !OS(WINCE)
 #include <process.h>
 #endif
+
 #if HAVE(ERRNO_H)
 #include <errno.h>
-#else
-#define NO_ERRNO
 #endif
-#include <windows.h>
-#include <wtf/CurrentTime.h>
-#include <wtf/HashMap.h>
-#include <wtf/MathExtras.h>
-#include <wtf/RandomNumberSeed.h>
 
 namespace WTF {
 
@@ -187,19 +191,10 @@ static void clearThreadHandleForIdentifier(ThreadIdentifier id)
     threadMap().remove(id);
 }
 
-struct ThreadFunctionInvocation {
-    ThreadFunctionInvocation(ThreadFunction function, void* data) : function(function), data(data) {}
-
-    ThreadFunction function;
-    void* data;
-};
-
 static unsigned __stdcall wtfThreadEntryPoint(void* param)
 {
-    ThreadFunctionInvocation invocation = *static_cast<ThreadFunctionInvocation*>(param);
-    delete static_cast<ThreadFunctionInvocation*>(param);
-
-    void* result = invocation.function(invocation.data);
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param));
+    void* result = invocation->function(invocation->data);
 
 #if !USE(PTHREADS) && OS(WINDOWS)
     // Do the TLS cleanup.
@@ -213,18 +208,18 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
 {
     unsigned threadIdentifier = 0;
     ThreadIdentifier threadID = 0;
-    ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data);
+    OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data));
 #if OS(WINCE)
     // This is safe on WINCE, since CRT is in the core and innately multithreaded.
     // On desktop Windows, need to use _beginthreadex (not available on WinCE) if using any CRT functions
-    HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation, 0, (LPDWORD)&threadIdentifier);
+    HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation.get(), 0, (LPDWORD)&threadIdentifier);
 #else
-    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier));
+    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation.get(), 0, &threadIdentifier));
 #endif
     if (!threadHandle) {
 #if OS(WINCE)
         LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, ::GetLastError());
-#elif defined(NO_ERRNO)
+#elif !HAVE(ERRNO_H)
         LOG_ERROR("Failed to create thread at entry point %p with data %p.", entryPoint, data);
 #else
         LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno);
@@ -232,6 +227,9 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con
         return 0;
     }
 
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
+
     threadID = static_cast<ThreadIdentifier>(threadIdentifier);
     storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
 
@@ -266,6 +264,11 @@ void detachThread(ThreadIdentifier threadID)
     clearThreadHandleForIdentifier(threadID);
 }
 
+void yield()
+{
+    ::Sleep(1);
+}
+
 ThreadIdentifier currentThread()
 {
     return static_cast<ThreadIdentifier>(GetCurrentThreadId());
@@ -329,6 +332,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
     res = ReleaseSemaphore(m_blockLock, 1, 0);
     ASSERT(res);
 
+    --mutex.m_recursionCount;
     LeaveCriticalSection(&mutex.m_internalMutex);
 
     // Main wait - use timeout.
@@ -362,6 +366,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
     }
 
     EnterCriticalSection (&mutex.m_internalMutex);
+    ++mutex.m_recursionCount;
 
     return !timedOut;
 }
@@ -455,20 +460,15 @@ void ThreadCondition::wait(Mutex& mutex)
 
 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
 {
-    double currentTime = WTF::currentTime();
+    DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime);
 
-    // Time is in the past - return immediately.
-    if (absoluteTime < currentTime)
+    if (!interval) {
+        // Consider the wait to have timed out, even if our condition has already been signaled, to
+        // match the pthreads implementation.
         return false;
-
-    // Time is too far in the future (and would overflow unsigned long) - wait forever.
-    if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) {
-        wait(mutex);
-        return true;
     }
 
-    double intervalMilliseconds = (absoluteTime - currentTime) * 1000.0;
-    return m_condition.timedWait(mutex.impl(), static_cast<unsigned long>(intervalMilliseconds));
+    return m_condition.timedWait(mutex.impl(), interval);
 }
 
 void ThreadCondition::signal()
@@ -481,4 +481,19 @@ void ThreadCondition::broadcast()
     m_condition.signal(true); // Unblock all threads.
 }
 
+DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime)
+{
+    double currentTime = WTF::currentTime();
+
+    // Time is in the past - return immediately.
+    if (absoluteTime < currentTime)
+        return 0;
+
+    // Time is too far in the future (and would overflow unsigned long) - wait forever.
+    if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0)
+        return INFINITE;
+
+    return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0);
+}
+
 } // namespace WTF
index 9e51ad0813419d1559848764f7c4de75da19e26b..afeaa5e4cd8ead3a2715bfcb1485ad9ce3cb7ee6 100644 (file)
@@ -47,6 +47,11 @@ COMPILE_ASSERT(!IsInteger<volatile char*>::value, WTF_IsInteger_volatile_char_po
 COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false);
 COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false);
 
+COMPILE_ASSERT(IsFloatingPoint<float>::value, WTF_IsFloatingPoint_float_true);
+COMPILE_ASSERT(IsFloatingPoint<double>::value, WTF_IsFloatingPoint_double_true);
+COMPILE_ASSERT(IsFloatingPoint<long double>::value, WTF_IsFloatingPoint_long_double_true);
+COMPILE_ASSERT(!IsFloatingPoint<int>::value, WTF_IsFloatingPoint_int_false);
+
 COMPILE_ASSERT(IsPod<bool>::value, WTF_IsPod_bool_true);
 COMPILE_ASSERT(IsPod<char>::value, WTF_IsPod_char_true);
 COMPILE_ASSERT(IsPod<signed char>::value, WTF_IsPod_signed_char_true);
@@ -131,4 +136,7 @@ COMPILE_ASSERT((IsSameType<int, RemovePointer<int>::Type>::value), WTF_Test_Remo
 COMPILE_ASSERT((IsSameType<int, RemovePointer<int*>::Type>::value), WTF_Test_RemovePointer_int_pointer);
 COMPILE_ASSERT((!IsSameType<int, RemovePointer<int**>::Type>::value), WTF_Test_RemovePointer_int_pointer_pointer);
 
+COMPILE_ASSERT((IsSameType<int, RemoveReference<int>::Type>::value), WTF_Test_RemoveReference_int);
+COMPILE_ASSERT((IsSameType<int, RemoveReference<int&>::Type>::value), WTF_Test_RemoveReference_int_reference);
+
 } // namespace WTF
index 62dbc4926c1c131731cec9db333e2e25803a1384..6c7466acc3508308943e4815870bb9b71ad34f17 100644 (file)
@@ -26,6 +26,9 @@
 
 #if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
 #include <type_traits>
+#if defined(__GXX_EXPERIMENTAL_CXX0X__)
+#include <tr1/memory>
+#endif
 #endif
 
 namespace WTF {
@@ -39,6 +42,7 @@ namespace WTF {
     //   IsSameType<T, U>::value
     //
     //   RemovePointer<T>::Type
+    //   RemoveReference<T>::Type
     //   RemoveConst<T>::Type
     //   RemoveVolatile<T>::Type
     //   RemoveConstVolatile<T>::Type
@@ -62,12 +66,16 @@ namespace WTF {
     template<> struct IsInteger<wchar_t>            { static const bool value = true; };
 #endif
 
+    template<typename T> struct IsFloatingPoint     { static const bool value = false; };
+    template<> struct IsFloatingPoint<float>        { static const bool value = true; };
+    template<> struct IsFloatingPoint<double>       { static const bool value = true; };
+    template<> struct IsFloatingPoint<long double>  { static const bool value = true; };
+
+    template<typename T> struct IsArithmetic     { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; };
+
     // IsPod is misnamed as it doesn't cover all plain old data (pod) types.
     // Specifically, it doesn't allow for enums or for structs.
-    template <typename T> struct IsPod           { static const bool value = IsInteger<T>::value; };
-    template <> struct IsPod<float>              { static const bool value = true; };
-    template <> struct IsPod<double>             { static const bool value = true; };
-    template <> struct IsPod<long double>        { static const bool value = true; };
+    template <typename T> struct IsPod           { static const bool value = IsArithmetic<T>::value; };
     template <typename P> struct IsPod<P*>       { static const bool value = true; };
 
     template<typename T> class IsConvertibleToInteger {
@@ -166,6 +174,14 @@ namespace WTF {
         typedef T Type;
     };
 
+    template <typename T> struct RemoveReference {
+        typedef T Type;
+    };
+
+    template <typename T> struct RemoveReference<T&> {
+        typedef T Type;
+    };
+
 #if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600))
 
     // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace.
index 996f5c8564217133b239c30b0ed1df11aeb39988..6ff6fd8958eb8c51d77aff396ef0a084d542b4b3 100644 (file)
 /* don't use this for C++, it should only be used in plain C files or
    ObjC methods, where leaving off the parameter name is not allowed. */
 
-#define UNUSED_PARAM(x) (void)x
+#include "Platform.h"
+
+#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT)
+template<typename T>
+inline void unusedParam(T& x) { (void)x; }
+#define UNUSED_PARAM(variable) unusedParam(variable)
+#else
+#define UNUSED_PARAM(variable) (void)variable
+#endif
 
 #endif /* WTF_UnusedParam_h */
index 6600050a1827996453e2379662df117810ecf6c0..117bc3721eacfdde13b6495f43696398f5ad8c7e 100644 (file)
@@ -32,8 +32,6 @@
 
 #include <mach/vm_statistics.h>
 
-#if !defined(TARGETING_TIGER)
-
 #if defined(VM_MEMORY_TCMALLOC)
 #define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(VM_MEMORY_TCMALLOC)
 #else
 #define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65)
 #endif // defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE)
 
-#else // !defined(TARGETING_TIGER)
-
-// mmap on Tiger fails with tags that work on Leopard, so fall
-// back to Tiger-compatible tags (that also work on Leopard)
-// when targeting Tiger.
-#define VM_TAG_FOR_TCMALLOC_MEMORY -1
-#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1
-#define VM_TAG_FOR_REGISTERFILE_MEMORY -1
-
-#endif // !defined(TARGETING_TIGER)
-
-// Tags for vm_map and vm_allocate work on both Tiger and Leopard.
-
 #if defined(VM_MEMORY_JAVASCRIPT_CORE)
 #define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE)
 #else
index dafa12ade997316a3c9c7cb931847b13d39fe26d..d5805cc7233412cc2e08423ec250be664160f81e 100644 (file)
 #include "FastAllocBase.h"
 #include "Noncopyable.h"
 #include "NotFound.h"
+#include "StdLibExtras.h"
 #include "ValueCheck.h"
 #include "VectorTraits.h"
 #include <limits>
 #include <utility>
+#include <wtf/Alignment.h>
 
 #if PLATFORM(QT)
 #include <QDataStream>
@@ -38,18 +40,7 @@ namespace WTF {
     using std::min;
     using std::max;
 
-    // WTF_ALIGN_OF / WTF_ALIGNED
-    #if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(WINSCW)
-        #define WTF_ALIGN_OF(type) __alignof__(type)
-        #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n)))
-    #elif COMPILER(MSVC)
-        #define WTF_ALIGN_OF(type) __alignof(type)
-        #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable
-    #else
-        #error WTF_ALIGN macros need alignment control.
-    #endif
-
-    #if COMPILER(GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
+    #if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303)
         typedef char __attribute__((__may_alias__)) AlignedBufferChar; 
     #else
         typedef char AlignedBufferChar; 
@@ -128,7 +119,11 @@ namespace WTF {
         {
             while (src != srcEnd) {
                 new (dst) T(*src);
+#if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590
+                const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compiler bug.
+#else
                 src->~T();
+#endif
                 ++dst;
                 ++src;
             }
@@ -276,10 +271,12 @@ namespace WTF {
     };
 
     template<typename T>
-    class VectorBufferBase : public Noncopyable {
+    class VectorBufferBase {
+        WTF_MAKE_NONCOPYABLE(VectorBufferBase);
     public:
         void allocateBuffer(size_t newCapacity)
         {
+            ASSERT(newCapacity);
             m_capacity = newCapacity;
             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
                 CRASH();
@@ -288,6 +285,7 @@ namespace WTF {
 
         bool tryAllocateBuffer(size_t newCapacity)
         {
+            ASSERT(newCapacity);
             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
                 return false;
 
@@ -358,7 +356,10 @@ namespace WTF {
 
         VectorBuffer(size_t capacity)
         {
-            allocateBuffer(capacity);
+            // Calling malloc(0) might take a lock and may actually do an
+            // allocation on some systems (e.g. Brew).
+            if (capacity)
+                allocateBuffer(capacity);
         }
 
         ~VectorBuffer()
@@ -390,6 +391,7 @@ namespace WTF {
 
     template<typename T, size_t inlineCapacity>
     class VectorBuffer : private VectorBufferBase<T> {
+        WTF_MAKE_NONCOPYABLE(VectorBuffer);
     private:
         typedef VectorBufferBase<T> Base;
     public:
@@ -412,6 +414,7 @@ namespace WTF {
 
         void allocateBuffer(size_t newCapacity)
         {
+            // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
             if (newCapacity > inlineCapacity)
                 Base::allocateBuffer(newCapacity);
             else {
@@ -481,18 +484,14 @@ namespace WTF {
         using Base::m_capacity;
 
         static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
-#if PLATFORM(ARM)
-        // FIXME: <rdar://problem/6546253&6546260>
-        T* inlineBuffer() { return reinterpret_cast<T*>(static_cast<void*>(m_inlineBuffer.buffer)); }
-#else
-        T* inlineBuffer() { return reinterpret_cast<T*>(m_inlineBuffer.buffer); }
-#endif
+        T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
 
         AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
     };
 
     template<typename T, size_t inlineCapacity = 0>
-    class Vector : public FastAllocBase {
+    class Vector {
+        WTF_MAKE_FAST_ALLOCATED;
     private:
         typedef VectorBuffer<T, inlineCapacity> Buffer;
         typedef VectorTypeOperations<T> TypeOperations;
@@ -561,7 +560,9 @@ namespace WTF {
         T& last() { return at(size() - 1); }
         const T& last() const { return at(size() - 1); }
 
+        template<typename U> bool contains(const U&) const;
         template<typename U> size_t find(const U&) const;
+        template<typename U> size_t reverseFind(const U&) const;
 
         void shrink(size_t size);
         void grow(size_t size);
@@ -618,6 +619,8 @@ namespace WTF {
             m_buffer.swap(other.m_buffer);
         }
 
+        void reverse();
+
         void checkConsistency();
 
     private:
@@ -691,6 +694,12 @@ namespace WTF {
                 return *this;
         }
         
+// Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
+#if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
+        if (!begin())
+            return *this;
+#endif
+
         std::copy(other.begin(), other.begin() + size(), begin());
         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
         m_size = other.size();
@@ -698,13 +707,17 @@ namespace WTF {
         return *this;
     }
 
+    inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
+
     template<typename T, size_t inlineCapacity>
     template<size_t otherCapacity> 
     Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other)
     {
-        if (&other == this)
-            return *this;
-        
+        // If the inline capacities match, we should call the more specific
+        // template.  If the inline capacities don't match, the two objects
+        // shouldn't be allocated the same address.
+        ASSERT(!typelessPointersAreEqual(&other, this));
+
         if (size() > other.size())
             shrink(other.size());
         else if (other.size() > capacity()) {
@@ -714,6 +727,12 @@ namespace WTF {
                 return *this;
         }
         
+// Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last
+#if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL
+        if (!begin())
+            return *this;
+#endif
+
         std::copy(other.begin(), other.begin() + size(), begin());
         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
         m_size = other.size();
@@ -721,6 +740,13 @@ namespace WTF {
         return *this;
     }
 
+    template<typename T, size_t inlineCapacity>
+    template<typename U>
+    bool Vector<T, inlineCapacity>::contains(const U& value) const
+    {
+        return find(value) != notFound;
+    }
     template<typename T, size_t inlineCapacity>
     template<typename U>
     size_t Vector<T, inlineCapacity>::find(const U& value) const
@@ -732,6 +758,18 @@ namespace WTF {
         return notFound;
     }
 
+    template<typename T, size_t inlineCapacity>
+    template<typename U>
+    size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const
+    {
+        for (size_t i = 1; i <= size(); ++i) {
+            const size_t index = size() - i;
+            if (at(index) == value)
+                return index;
+        }
+        return notFound;
+    }
+
     template<typename T, size_t inlineCapacity>
     void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize)
     {
@@ -1060,6 +1098,13 @@ namespace WTF {
         m_size -= length;
     }
 
+    template<typename T, size_t inlineCapacity>
+    inline void Vector<T, inlineCapacity>::reverse()
+    {
+        for (size_t i = 0; i < m_size / 2; ++i)
+            std::swap(at(i), at(m_size - 1 - i));
+    }
+
     template<typename T, size_t inlineCapacity>
     inline T* Vector<T, inlineCapacity>::releaseBuffer()
     {
diff --git a/wtf/Vector3.h b/wtf/Vector3.h
deleted file mode 100644 (file)
index 3c40b61..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2010 Google 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.
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 Vector3_h
-#define Vector3_h
-
-#include <math.h>
-
-namespace WebCore {
-
-class Vector3 {
-public:
-    Vector3()
-        : m_x(0.0)
-        , m_y(0.0)
-        , m_z(0.0)
-    {
-    }
-
-    Vector3(double x, double y, double z)
-        : m_x(x)
-        , m_y(y)
-        , m_z(z)
-    {
-    }
-
-    Vector3(const float p[3])
-        : m_x(p[0])
-        , m_y(p[1])
-        , m_z(p[2])
-    {
-    }
-
-    Vector3(const double p[3])
-        : m_x(p[0])
-        , m_y(p[1])
-        , m_z(p[2])
-    {
-    }
-
-    double abs() const
-    {
-        return sqrt(m_x * m_x + m_y * m_y + m_z * m_z);
-    }
-
-    bool isZero() const
-    {
-        return !m_x && !m_y && !m_z;
-    }
-
-    void normalize()
-    {
-        double absValue = abs();
-        if (!absValue)
-            return;
-
-        double k = 1.0 / absValue;
-        m_x *= k;
-        m_y *= k;
-        m_z *= k;
-    }
-
-    double x() const { return m_x; }
-    double y() const { return m_y; }
-    double z() const { return m_z; }
-
-private:
-    double m_x;
-    double m_y;
-    double m_z;
-};
-
-inline Vector3 operator+(const Vector3& v1, const Vector3& v2)
-{
-    return Vector3(v1.x() + v2.x(), v1.y() + v2.y(), v1.z() + v2.z());
-}
-
-inline Vector3 operator-(const Vector3& v1, const Vector3& v2)
-{
-    return Vector3(v1.x() - v2.x(), v1.y() - v2.y(), v1.z() - v2.z());
-}
-
-inline Vector3 operator*(double k, const Vector3& v)
-{
-    return Vector3(k * v.x(), k * v.y(), k * v.z());
-}
-
-inline Vector3 operator*(const Vector3& v, double k)
-{
-    return Vector3(k * v.x(), k * v.y(), k * v.z());
-}
-
-inline double dot(const Vector3& v1, const Vector3& v2)
-{
-    return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z();
-}
-
-inline Vector3 cross(const Vector3& v1, const Vector3& v2)
-{
-    double x3 = v1.y() * v2.z() - v1.z() * v2.y();
-    double y3 = v1.z() * v2.x() - v1.x() * v2.z();
-    double z3 = v1.x() * v2.y() - v1.y() * v2.x();
-    return Vector3(x3, y3, z3);
-}
-
-inline double distance(const Vector3& v1, const Vector3& v2)
-{
-    return (v1 - v2).abs();
-}
-
-} // WebCore
-
-#endif // Vector3_h
index 3f33b290d97c6055265241c3d524069562c04dd7..6777c9ebfa13257ae6a516dbe7251298ddf7c15b 100644 (file)
@@ -61,14 +61,10 @@ namespace WTF {
     template<typename T>
     struct VectorTraits : VectorTraitsBase<IsPod<T>::value, T> { };
 
-    struct SimpleClassVectorTraits
+    struct SimpleClassVectorTraits : VectorTraitsBase<false, void>
     {
-        static const bool needsDestruction = true;
-        static const bool needsInitialization = true;
         static const bool canInitializeWithMemset = true;
         static const bool canMoveWithMemcpy = true;
-        static const bool canCopyWithMemcpy = false;
-        static const bool canFillWithMemset = false;
         static const bool canCompareWithMemcmp = true;
     };
 
index 70fbda61454589e11b9bc5eae5da2b6e6f5c1078..64624b5c55e369cbc4da2539440a0128b447c15d 100644 (file)
@@ -38,7 +38,11 @@ WTFThreadData* WTFThreadData::staticData;
 WTFThreadData::WTFThreadData()
     : m_atomicStringTable(0)
     , m_atomicStringTableDestructor(0)
+#if USE(JSC)
+    , m_stackBounds(StackBounds::currentThreadStackBounds())
+#endif
 {
+#if USE(JSC)
     static JSC::IdentifierTable* sharedIdentifierTable = new JSC::IdentifierTable();
     if (pthread_main_np() || isWebThread())
         m_defaultIdentifierTable = sharedIdentifierTable;
@@ -46,13 +50,16 @@ WTFThreadData::WTFThreadData()
         m_defaultIdentifierTable = new JSC::IdentifierTable();
 
     m_currentIdentifierTable = m_defaultIdentifierTable;
+#endif
 }
 
 WTFThreadData::~WTFThreadData()
 {
     if (m_atomicStringTableDestructor)
         m_atomicStringTableDestructor(m_atomicStringTable);
+#if USE(JSC)
     delete m_defaultIdentifierTable;
+#endif
 }
 
-} // namespace WebCore
+}
index 510a0e0e65c0d9bc8073fe41a87f13159f776589..243aa91aa46f8e9d6ce03495e1996fc857f82b07 100644 (file)
@@ -30,6 +30,7 @@
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/StackBounds.h>
 #include <wtf/text/StringHash.h>
 
 // This was ENABLE(WORKERS) in WebCore, but this is not defined when compiling JSC.
 #include <wtf/Threading.h>
 #endif
 
-// FIXME: This is a temporary layering violation while we move more string code to WTF.
-namespace WebCore {
-class AtomicStringTable;
-class StringImpl;
-}
-using WebCore::StringImpl;
-
-typedef void (*AtomicStringTableDestructor)(WebCore::AtomicStringTable*);
-
 #if USE(JSC)
 // FIXME: This is a temporary layering violation while we move more string code to WTF.
 namespace JSC {
 
 typedef HashMap<const char*, RefPtr<StringImpl>, PtrHash<const char*> > LiteralIdentifierTable;
 
-class IdentifierTable : public FastAllocBase {
+class IdentifierTable {
+    WTF_MAKE_FAST_ALLOCATED;
 public:
     ~IdentifierTable();
 
@@ -68,7 +61,14 @@ public:
     template<typename U, typename V>
     std::pair<HashSet<StringImpl*>::iterator, bool> add(U value);
 
-    void remove(StringImpl* r) { m_table.remove(r); }
+    bool remove(StringImpl* r)
+    {
+        HashSet<StringImpl*>::iterator iter = m_table.find(r);
+        if (iter == m_table.end())
+            return false;
+        m_table.remove(iter);
+        return true;
+    }
 
     LiteralIdentifierTable& literalTable() { return m_literalTable; }
 
@@ -82,18 +82,22 @@ private:
 
 namespace WTF {
 
-class WTFThreadData : public Noncopyable {
+class AtomicStringTable;
+
+typedef void (*AtomicStringTableDestructor)(AtomicStringTable*);
+
+class WTFThreadData {
+    WTF_MAKE_NONCOPYABLE(WTFThreadData);
 public:
     WTFThreadData();
     ~WTFThreadData();
 
-    WebCore::AtomicStringTable* atomicStringTable()
+    AtomicStringTable* atomicStringTable()
     {
         return m_atomicStringTable;
     }
 
 #if USE(JSC)
-
     JSC::IdentifierTable* currentIdentifierTable()
     {
         return m_currentIdentifierTable;
@@ -110,15 +114,21 @@ public:
     {
         m_currentIdentifierTable = m_defaultIdentifierTable;
     }
+
+    const StackBounds& stack() const
+    {
+        return m_stackBounds;
+    }
 #endif
 
 private:
-    WebCore::AtomicStringTable* m_atomicStringTable;
+    AtomicStringTable* m_atomicStringTable;
     AtomicStringTableDestructor m_atomicStringTableDestructor;
 
 #if USE(JSC)
     JSC::IdentifierTable* m_defaultIdentifierTable;
     JSC::IdentifierTable* m_currentIdentifierTable;
+    StackBounds m_stackBounds;
 #endif
 
 #if WTFTHREADDATA_MULTITHREADED
@@ -127,7 +137,7 @@ private:
     static JS_EXPORTDATA WTFThreadData* staticData;
 #endif
     friend WTFThreadData& wtfThreadData();
-    friend class WebCore::AtomicStringTable;
+    friend class AtomicStringTable;
 };
 
 inline WTFThreadData& wtfThreadData()
index c8384e1d0aa56f7269006c8ed313123bbe84d525..ce10fc3646365776f2346b9b9c8636087f1b0c2d 100644 (file)
 
 #include <AEEBitmap.h>
 #include <AEEFile.h>
+#include <AEEIMemGroup.h>
+#include <AEEIMemSpace.h>
+#include <AEENet.h>
+#include <AEESSL.h>
 #include <AEEStdLib.h>
 
 namespace WTF {
@@ -50,4 +54,28 @@ void deleteOwnedPtr(IBitmap* ptr)
         IBitmap_Release(ptr);
 }
 
+void deleteOwnedPtr(ISSL* ptr)
+{
+    if (ptr)
+        ISSL_Release(ptr);
+}
+
+void deleteOwnedPtr(IMemGroup* ptr)
+{
+    if (ptr)
+        IMemGroup_Release(ptr);
+}
+
+void deleteOwnedPtr(IMemSpace* ptr)
+{
+    if (ptr)
+        IMemSpace_Release(ptr);
+}
+
+void deleteOwnedPtr(ISocket* ptr)
+{
+    if (ptr)
+        ISOCKET_Release(ptr);
+}
+
 }
diff --git a/wtf/brew/RefPtrBrew.h b/wtf/brew/RefPtrBrew.h
new file mode 100644 (file)
index 0000000..40e257b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008 Collabora Ltd.
+ *  Copyright (C) 2009 Martin Robinson
+ *  Copyright (C) 2010 Company 100, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RefPtrBrew_h
+#define RefPtrBrew_h
+
+#include "RefPtr.h"
+#include <AEEIBase.h>
+
+namespace WTF {
+
+// All Brew MP classes are derived from either IBase or IQI.
+template<> void refIfNotNull(IBase* ptr)
+{
+    if (LIKELY(ptr != 0))
+        IBase_AddRef(ptr);
+}
+
+template<> void derefIfNotNull(IBase* ptr)
+{
+    if (LIKELY(ptr != 0))
+        IBase_Release(ptr);
+}
+
+template<> void refIfNotNull(IQI* ptr)
+{
+    if (LIKELY(ptr != 0))
+        IQI_AddRef(ptr);
+}
+
+template<> void derefIfNotNull(IQI* ptr)
+{
+    if (LIKELY(ptr != 0))
+        IQI_Release(ptr);
+}
+
+} // namespace WTF
+
+#endif // RefPtrBrew_h
index 7416eca27b0fc9aab081225e09f67adbe53f0de2..80476314c0f8471bd2782a0d189fd75c5d27b218 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <wtf/Assertions.h>
 #include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
 
 namespace WTF {
 
@@ -49,8 +50,21 @@ static inline PassOwnPtr<T> createInstance(AEECLSID cls)
     return instance;
 }
 
+template <typename T>
+static inline RefPtr<T> createRefPtrInstance(AEECLSID cls)
+{
+    T* instance = 0;
+
+    IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell;
+    ISHELL_CreateInstance(shell, cls, reinterpret_cast<void**>(&instance));
+    ASSERT(instance);
+
+    return adoptRef(instance);
+}
+
 } // namespace WTF
 
 using WTF::createInstance;
+using WTF::createRefPtrInstance;
 
 #endif // ShellBrew_h
diff --git a/wtf/brew/StringBrew.cpp b/wtf/brew/StringBrew.cpp
new file mode 100644 (file)
index 0000000..d8f2e59
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 Company 100, 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 COMPUTER, 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 COMPUTER, 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.
+ */
+
+#include "config.h"
+#include "PlatformString.h"
+
+#include <AEEstd.h>
+
+namespace WTF {
+
+// String conversions
+String::String(const AECHAR* string)
+{
+    // It is safe to cast AECHAR to UChar as both of them use 16 bits representation.
+    const UChar* str = reinterpret_cast<const UChar*>(string);
+    const size_t len = std_wstrlen(string);
+
+    m_impl = StringImpl::create(str, len);
+}
+
+} // namespace WTF
index e63be907451a00bb6aa5262d2ce832b92e413339..b162543e9169acb230297defa6d405ca806e0858 100644 (file)
@@ -3,7 +3,7 @@
  * The author of this software is David M. Gay.
  *
  * Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
- * Copyright (C) 2002, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose without fee is hereby granted, provided that this entire notice
  *
  ***************************************************************/
 
-/* Please send bug reports to
-    David M. Gay
-    Bell Laboratories, Room 2C-463
-    600 Mountain Avenue
-    Murray Hill, NJ 07974-0636
-    U.S.A.
-    dmg@bell-labs.com
- */
+/* Please send bug reports to David M. Gay (dmg at acm dot org,
+ * with " at " changed at "@" and " dot " changed to ".").    */
 
 /* On a machine with IEEE extended-precision registers, it is
  * necessary to specify double-precision (53-bit) rounding precision
@@ -50,7 +44,7 @@
  *
  * Modifications:
  *
- *    1. We only require IEEE.
+ *    1. We only require IEEE double-precision arithmetic (not IEEE double-extended).
  *    2. We get by with floating-point arithmetic in a case that
  *        Clinger missed -- when we're computing d * 10^n
  *        for a small integer d and the integer n is not too
  *        for 0 <= k <= 22).
  */
 
-/*
- * #define IEEE_8087 for IEEE-arithmetic machines where the least
- *    significant byte has the lowest address.
- * #define IEEE_MC68k for IEEE-arithmetic machines where the most
- *    significant byte has the lowest address.
- * #define No_leftright to omit left-right logic in fast floating-point
- *    computation of dtoa.
- * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3
- *    and Honor_FLT_ROUNDS is not #defined.
- * #define Inaccurate_Divide for IEEE-format with correctly rounded
- *    products but inaccurate quotients, e.g., for Intel i860.
- * #define USE_LONG_LONG on machines that have a "long long"
- *    integer type (of >= 64 bits), and performance testing shows that
- *    it is faster than 32-bit fallback (which is often not the case
- *    on 32-bit machines). On such machines, you can #define Just_16
- *    to store 16 bits per 32-bit int32_t when doing high-precision integer
- *    arithmetic.  Whether this speeds things up or slows things down
- *    depends on the machine and the number being converted.
- * #define Bad_float_h if your system lacks a float.h or if it does not
- *    define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
- *    FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
- * #define INFNAN_CHECK on IEEE systems to cause strtod to check for
- *    Infinity and NaN (case insensitively).  On some systems (e.g.,
- *    some HP systems), it may be necessary to #define NAN_WORD0
- *    appropriately -- to the most significant word of a quiet NaN.
- *    (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.)
- *    When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined,
- *    strtod also accepts (case insensitively) strings of the form
- *    NaN(x), where x is a string of hexadecimal digits and spaces;
- *    if there is only one string of hexadecimal digits, it is taken
- *    for the 52 fraction bits of the resulting NaN; if there are two
- *    or more strings of hex digits, the first is for the high 20 bits,
- *    the second and subsequent for the low 32 bits, with intervening
- *    white space ignored; but if this results in none of the 52
- *    fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0
- *    and NAN_WORD1 are used instead.
- * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that
- *    avoids underflows on inputs whose result does not underflow.
- *    If you #define NO_IEEE_Scale on a machine that uses IEEE-format
- *    floating-point numbers and flushes underflows to zero rather
- *    than implementing gradual underflow, then you must also #define
- *    Sudden_Underflow.
- * #define YES_ALIAS to permit aliasing certain double values with
- *    arrays of ULongs.  This leads to slightly better code with
- *    some compilers and was always used prior to 19990916, but it
- *    is not strictly legal and can cause trouble with aggressively
- *    optimizing compilers (e.g., gcc 2.95.1 under -O2).
- * #define SET_INEXACT if IEEE arithmetic is being used and extra
- *    computation should be done to set the inexact flag when the
- *    result is inexact and avoid setting inexact when the result
- *    is exact.  In this case, dtoa.c must be compiled in
- *    an environment, perhaps provided by #include "dtoa.c" in a
- *    suitable wrapper, that defines two functions,
- *        int get_inexact(void);
- *        void clear_inexact(void);
- *    such that get_inexact() returns a nonzero value if the
- *    inexact bit is already set, and clear_inexact() sets the
- *    inexact bit to 0.  When SET_INEXACT is #defined, strtod
- *    also does extra computations to set the underflow and overflow
- *    flags when appropriate (i.e., when the result is tiny and
- *    inexact or when it is a numeric value rounded to +-infinity).
- * #define NO_ERRNO if strtod should not assign errno = ERANGE when
- *    the result overflows to +-Infinity or underflows to 0.
- */
-
 #include "config.h"
 #include "dtoa.h"
 
 #if HAVE(ERRNO_H)
 #include <errno.h>
-#else
-#define NO_ERRNO
 #endif
+#include <float.h>
 #include <math.h>
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wtf/AlwaysInline.h>
 #include <wtf/Assertions.h>
+#include <wtf/DecimalNumber.h>
 #include <wtf/FastMalloc.h>
 #include <wtf/MathExtras.h>
-#include <wtf/Vector.h>
 #include <wtf/Threading.h>
-
-#include <stdio.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
 
 #if COMPILER(MSVC)
 #pragma warning(disable: 4244)
 #pragma warning(disable: 4554)
 #endif
 
-#if CPU(BIG_ENDIAN)
-#define IEEE_MC68k
-#elif CPU(MIDDLE_ENDIAN)
-#define IEEE_ARM
-#else
-#define IEEE_8087
-#endif
-
-#define INFNAN_CHECK
-#define No_Hex_NaN
-
-#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(IEEE_ARM) != 1
-Exactly one of IEEE_8087, IEEE_ARM or IEEE_MC68k should be defined.
-#endif
-
 namespace WTF {
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
 Mutex* s_dtoaP5Mutex;
 #endif
 
-typedef union { double d; uint32_t L[2]; } U;
+typedef union {
+    double d;
+    uint32_t L[2];
+} U;
 
-#ifdef YES_ALIAS
-#define dval(x) x
-#ifdef IEEE_8087
-#define word0(x) ((uint32_t*)&x)[1]
-#define word1(x) ((uint32_t*)&x)[0]
-#else
-#define word0(x) ((uint32_t*)&x)[0]
-#define word1(x) ((uint32_t*)&x)[1]
-#endif
+#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
+#define word0(x) (x)->L[0]
+#define word1(x) (x)->L[1]
 #else
-#ifdef IEEE_8087
 #define word0(x) (x)->L[1]
 #define word1(x) (x)->L[0]
-#else
-#define word0(x) (x)->L[0]
-#define word1(x) (x)->L[1]
 #endif
 #define dval(x) (x)->d
-#endif
 
 /* The following definition of Storeinc is appropriate for MIPS processors.
  * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ *  *p++ = high << 16 | low & 0xffff;
  */
-#if defined(IEEE_8087) || defined(IEEE_ARM)
-#define Storeinc(a,b,c) (((unsigned short*)a)[1] = (unsigned short)b, ((unsigned short*)a)[0] = (unsigned short)c, a++)
+static ALWAYS_INLINE uint32_t* storeInc(uint32_t* p, uint16_t high, uint16_t low)
+{
+    uint16_t* p16 = reinterpret_cast<uint16_t*>(p);
+#if CPU(BIG_ENDIAN)
+    p16[0] = high;
+    p16[1] = low;
 #else
-#define Storeinc(a,b,c) (((unsigned short*)a)[0] = (unsigned short)b, ((unsigned short*)a)[1] = (unsigned short)c, a++)
+    p16[1] = high;
+    p16[0] = low;
 #endif
+    return p + 1;
+}
 
 #define Exp_shift  20
 #define Exp_shift1 20
@@ -237,51 +150,18 @@ typedef union { double d; uint32_t L[2]; } U;
 #define Quick_max 14
 #define Int_max 14
 
-#if !defined(NO_IEEE_Scale)
-#undef Avoid_Underflow
-#define Avoid_Underflow
-#endif
-
-#if !defined(Flt_Rounds)
-#if defined(FLT_ROUNDS)
-#define Flt_Rounds FLT_ROUNDS
-#else
-#define Flt_Rounds 1
-#endif
-#endif /*Flt_Rounds*/
-
-
-#define rounded_product(a,b) a *= b
-#define rounded_quotient(a,b) a /= b
+#define rounded_product(a, b) a *= b
+#define rounded_quotient(a, b) a /= b
 
 #define Big0 (Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias - 1))
 #define Big1 0xffffffff
 
-
-// FIXME: we should remove non-Pack_32 mode since it is unused and unmaintained
-#ifndef Pack_32
-#define Pack_32
-#endif
-
 #if CPU(PPC64) || CPU(X86_64)
 // FIXME: should we enable this on all 64-bit CPUs?
 // 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware.
 #define USE_LONG_LONG
 #endif
 
-#ifndef USE_LONG_LONG
-#ifdef Just_16
-#undef Pack_32
-/* When Pack_32 is not defined, we store 16 bits per 32-bit int32_t.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower.  Hence the default is now to store 32 bits per int32_t.
- */
-#endif
-#endif
-
-#define Kmax 15
-
 struct BigInt {
     BigInt() : sign(0) { }
     int sign;
@@ -291,7 +171,7 @@ struct BigInt {
         sign = 0;
         m_words.clear();
     }
-    
+
     size_t size() const
     {
         return m_words.size();
@@ -301,7 +181,7 @@ struct BigInt {
     {
         m_words.resize(s);
     }
-            
+
     uint32_t* words()
     {
         return m_words.data();
@@ -311,12 +191,12 @@ struct BigInt {
     {
         return m_words.data();
     }
-    
+
     void append(uint32_t w)
     {
         m_words.append(w);
     }
-    
+
     Vector<uint32_t, 16> m_words;
 };
 
@@ -338,17 +218,11 @@ static void multadd(BigInt& b, int m, int a)    /* multiply by m and add a */
         carry = y >> 32;
         *x++ = (uint32_t)y & 0xffffffffUL;
 #else
-#ifdef Pack_32
         uint32_t xi = *x;
         uint32_t y = (xi & 0xffff) * m + carry;
         uint32_t z = (xi >> 16) * m + (y >> 16);
         carry = z >> 16;
         *x++ = (z << 16) + (y & 0xffff);
-#else
-        uint32_t y = *x * m + carry;
-        carry = y >> 16;
-        *x++ = y & 0xffff;
-#endif
 #endif
     } while (++i < wds);
 
@@ -358,20 +232,9 @@ static void multadd(BigInt& b, int m, int a)    /* multiply by m and add a */
 
 static void s2b(BigInt& b, const char* s, int nd0, int nd, uint32_t y9)
 {
-    int k;
-    int32_t y;
-    int32_t x = (nd + 8) / 9;
-
-    for (k = 0, y = 1; x > y; y <<= 1, k++) { }
-#ifdef Pack_32
     b.sign = 0;
     b.resize(1);
     b.words()[0] = y9;
-#else
-    b.sign = 0;
-    b.resize((b->x[1] = y9 >> 16) ? 2 : 1);
-    b.words()[0] = y9 & 0xffff;
-#endif
 
     int i = 9;
     if (9 < nd0) {
@@ -414,7 +277,7 @@ static int hi0bits(uint32_t x)
     return k;
 }
 
-static int lo0bits (uint32_t* y)
+static int lo0bits(uint32_t* y)
 {
     int k;
     uint32_t x = *y;
@@ -449,7 +312,7 @@ static int lo0bits (uint32_t* y)
     if (!(x & 1)) {
         k++;
         x >>= 1;
-        if (!x & 1)
+        if (!x)
             return 32;
     }
     *y = x;
@@ -469,8 +332,13 @@ static void mult(BigInt& aRef, const BigInt& bRef)
     const BigInt* b = &bRef;
     BigInt c;
     int wa, wb, wc;
-    const uint32_t *x = 0, *xa, *xb, *xae, *xbe;
-    uint32_t *xc, *xc0;
+    const uint32_t* x = 0;
+    const uint32_t* xa;
+    const uint32_t* xb;
+    const uint32_t* xae;
+    const uint32_t* xbe;
+    uint32_t* xc;
+    uint32_t* xc0;
     uint32_t y;
 #ifdef USE_LONG_LONG
     unsigned long long carry, z;
@@ -483,7 +351,7 @@ static void mult(BigInt& aRef, const BigInt& bRef)
         a = b;
         b = tmp;
     }
-    
+
     wa = a->size();
     wb = b->size();
     wc = wa + wb;
@@ -511,7 +379,6 @@ static void mult(BigInt& aRef, const BigInt& bRef)
         }
     }
 #else
-#ifdef Pack_32
     for (; xb < xbe; xb++, xc0++) {
         if ((y = *xb & 0xffff)) {
             x = xa;
@@ -522,7 +389,7 @@ static void mult(BigInt& aRef, const BigInt& bRef)
                 carry = z >> 16;
                 uint32_t z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
                 carry = z2 >> 16;
-                Storeinc(xc, z2, z);
+                xc = storeInc(xc, z2, z);
             } while (x < xae);
             *xc = carry;
         }
@@ -534,41 +401,29 @@ static void mult(BigInt& aRef, const BigInt& bRef)
             do {
                 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
                 carry = z >> 16;
-                Storeinc(xc, z, z2);
+                xc = storeInc(xc, z, z2);
                 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
                 carry = z2 >> 16;
             } while (x < xae);
             *xc = z2;
         }
     }
-#else
-    for(; xb < xbe; xc0++) {
-        if ((y = *xb++)) {
-            x = xa;
-            xc = xc0;
-            carry = 0;
-            do {
-                z = *x++ * y + *xc + carry;
-                carry = z >> 16;
-                *xc++ = z & 0xffff;
-            } while (x < xae);
-            *xc = carry;
-        }
-    }
-#endif
 #endif
     for (xc0 = c.words(), xc = xc0 + wc; wc > 0 && !*--xc; --wc) { }
     c.resize(wc);
     aRef = c;
 }
 
-struct P5Node : Noncopyable {
+struct P5Node {
+    WTF_MAKE_NONCOPYABLE(P5Node); WTF_MAKE_FAST_ALLOCATED;
+public:
+    P5Node() { }
     BigInt val;
     P5Node* next;
 };
-    
+
 static P5Node* p5s;
-static int p5s_count;
+static int p5sCount;
 
 static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
 {
@@ -580,7 +435,7 @@ static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
     if (!(k >>= 2))
         return;
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
     s_dtoaP5Mutex->lock();
 #endif
     P5Node* p5 = p5s;
@@ -591,14 +446,14 @@ static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
         i2b(p5->val, 625);
         p5->next = 0;
         p5s = p5;
-        p5s_count = 1;
+        p5sCount = 1;
     }
 
-    int p5s_count_local = p5s_count;
-#if ENABLE(JSC_MULTIPLE_THREADS)
+    int p5sCountLocal = p5sCount;
+#if ENABLE(WTF_MULTIPLE_THREADS)
     s_dtoaP5Mutex->unlock();
 #endif
-    int p5s_used = 0;
+    int p5sUsed = 0;
 
     for (;;) {
         if (k & 1)
@@ -607,21 +462,21 @@ static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
         if (!(k >>= 1))
             break;
 
-        if (++p5s_used == p5s_count_local) {
-#if ENABLE(JSC_MULTIPLE_THREADS)
+        if (++p5sUsed == p5sCountLocal) {
+#if ENABLE(WTF_MULTIPLE_THREADS)
             s_dtoaP5Mutex->lock();
 #endif
-            if (p5s_used == p5s_count) {
+            if (p5sUsed == p5sCount) {
                 ASSERT(!p5->next);
                 p5->next = new P5Node;
                 p5->next->next = 0;
                 p5->next->val = p5->val;
                 mult(p5->next->val, p5->next->val);
-                ++p5s_count;
+                ++p5sCount;
             }
-            
-            p5s_count_local = p5s_count;
-#if ENABLE(JSC_MULTIPLE_THREADS)
+
+            p5sCountLocal = p5sCount;
+#if ENABLE(WTF_MULTIPLE_THREADS)
             s_dtoaP5Mutex->unlock();
 #endif
         }
@@ -631,11 +486,7 @@ static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
 
 static ALWAYS_INLINE void lshift(BigInt& b, int k)
 {
-#ifdef Pack_32
     int n = k >> 5;
-#else
-    int n = k >> 4;
-#endif
 
     int origSize = b.size();
     int n1 = n + origSize + 1;
@@ -649,7 +500,6 @@ static ALWAYS_INLINE void lshift(BigInt& b, int k)
     uint32_t* dstStart = b.words();
     const uint32_t* src = srcStart + origSize - 1;
     uint32_t* dst = dstStart + n1 - 1;
-#ifdef Pack_32
     if (k) {
         uint32_t hiSubword = 0;
         int s = 32 - k;
@@ -660,21 +510,8 @@ static ALWAYS_INLINE void lshift(BigInt& b, int k)
         *dst = hiSubword;
         ASSERT(dst == dstStart + n);
 
-        b.resize(origSize + n + (b.words()[n1 - 1] != 0));
+        b.resize(origSize + n + !!b.words()[n1 - 1]);
     }
-#else
-    if (k &= 0xf) {
-        uint32_t hiSubword = 0;
-        int s = 16 - k;
-        for (; src >= srcStart; --src) {
-            *dst-- = hiSubword | *src >> s;
-            hiSubword = (*src << k) & 0xffff;
-        }
-        *dst = hiSubword;
-        ASSERT(dst == dstStart + n);
-        result->wds = b->wds + n + (result->x[n1 - 1] != 0);
-     }
- #endif
     else {
         do {
             *--dst = *src--;
@@ -715,7 +552,7 @@ static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef
     const BigInt* a = &aRef;
     const BigInt* b = &bRef;
     int i, wa, wb;
-    uint32_t *xc;
+    uint32_txc;
 
     i = cmp(*a, *b);
     if (!i) {
@@ -756,33 +593,20 @@ static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef
     }
 #else
     uint32_t borrow = 0;
-#ifdef Pack_32
     do {
         uint32_t y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
         borrow = (y & 0x10000) >> 16;
         uint32_t z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
         borrow = (z & 0x10000) >> 16;
-        Storeinc(xc, z, y);
+        xc = storeInc(xc, z, y);
     } while (xb < xbe);
     while (xa < xae) {
         uint32_t y = (*xa & 0xffff) - borrow;
         borrow = (y & 0x10000) >> 16;
         uint32_t z = (*xa++ >> 16) - borrow;
         borrow = (z & 0x10000) >> 16;
-        Storeinc(xc, z, y);
-    }
-#else
-    do {
-        uint32_t y = *xa++ - *xb++ - borrow;
-        borrow = (y & 0x10000) >> 16;
-        *xc++ = y & 0xffff;
-    } while (xb < xbe);
-    while (xa < xae) {
-        uint32_t y = *xa++ - borrow;
-        borrow = (y & 0x10000) >> 16;
-        *xc++ = y & 0xffff;
+        xc = storeInc(xc, z, y);
     }
-#endif
 #endif
     while (!*--xc)
         wa--;
@@ -795,28 +619,8 @@ static double ulp(U *x)
     U u;
 
     L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
-    if (L > 0) {
-#endif
-#endif
         word0(&u) = L;
         word1(&u) = 0;
-#ifndef Avoid_Underflow
-#ifndef Sudden_Underflow
-    } else {
-        L = -L >> Exp_shift;
-        if (L < Exp_shift) {
-            word0(&u) = 0x80000 >> L;
-            word1(&u) = 0;
-        } else {
-            word0(&u) = 0;
-            L -= Exp_shift;
-            word1(&u) = L >= 31 ? 1 : 1 << 31 - L;
-        }
-    }
-#endif
-#endif
     return dval(&u);
 }
 
@@ -839,12 +643,11 @@ static double b2d(const BigInt& a, int* e)
     ASSERT(y);
     k = hi0bits(y);
     *e = 32 - k;
-#ifdef Pack_32
     if (k < Ebits) {
         d0 = Exp_1 | (y >> (Ebits - k));
         w = xa > xa0 ? *--xa : 0;
         d1 = (y << (32 - Ebits + k)) | (w >> (Ebits - k));
-        goto ret_d;
+        goto returnD;
     }
     z = xa > xa0 ? *--xa : 0;
     if (k -= Ebits) {
@@ -855,23 +658,7 @@ static double b2d(const BigInt& a, int* e)
         d0 = Exp_1 | y;
         d1 = z;
     }
-#else
-    if (k < Ebits + 16) {
-        z = xa > xa0 ? *--xa : 0;
-        d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
-        w = xa > xa0 ? *--xa : 0;
-        y = xa > xa0 ? *--xa : 0;
-        d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
-        goto ret_d;
-    }
-    z = xa > xa0 ? *--xa : 0;
-    w = xa > xa0 ? *--xa : 0;
-    k -= Ebits + 16;
-    d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
-    y = xa > xa0 ? *--xa : 0;
-    d1 = w << k + 16 | y << k;
-#endif
-ret_d:
+returnD:
 #undef d0
 #undef d1
     return dval(&d);
@@ -880,105 +667,46 @@ ret_d:
 static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits)
 {
     int de, k;
-    uint32_t *x, y, z;
-#ifndef Sudden_Underflow
+    uint32_t* x;
+    uint32_t y, z;
     int i;
-#endif
 #define d0 word0(d)
 #define d1 word1(d)
 
     b.sign = 0;
-#ifdef Pack_32
     b.resize(1);
-#else
-    b.resize(2);
-#endif
     x = b.words();
 
     z = d0 & Frac_mask;
     d0 &= 0x7fffffff;    /* clear sign bit, which we ignore */
-#ifdef Sudden_Underflow
-    de = (int)(d0 >> Exp_shift);
-#else
     if ((de = (int)(d0 >> Exp_shift)))
         z |= Exp_msk1;
-#endif
-#ifdef Pack_32
     if ((y = d1)) {
         if ((k = lo0bits(&y))) {
             x[0] = y | (z << (32 - k));
             z >>= k;
         } else
             x[0] = y;
-            if (z) {
-                b.resize(2);
-                x[1] = z;
-            }
+        if (z) {
+            b.resize(2);
+            x[1] = z;
+        }
 
-#ifndef Sudden_Underflow
         i = b.size();
-#endif
     } else {
         k = lo0bits(&z);
         x[0] = z;
-#ifndef Sudden_Underflow
         i = 1;
-#endif
         b.resize(1);
         k += 32;
     }
-#else
-    if ((y = d1)) {
-        if ((k = lo0bits(&y))) {
-            if (k >= 16) {
-                x[0] = y | z << 32 - k & 0xffff;
-                x[1] = z >> k - 16 & 0xffff;
-                x[2] = z >> k;
-                i = 2;
-            } else {
-                x[0] = y & 0xffff;
-                x[1] = y >> 16 | z << 16 - k & 0xffff;
-                x[2] = z >> k & 0xffff;
-                x[3] = z >> k + 16;
-                i = 3;
-            }
-        } else {
-            x[0] = y & 0xffff;
-            x[1] = y >> 16;
-            x[2] = z & 0xffff;
-            x[3] = z >> 16;
-            i = 3;
-        }
-    } else {
-        k = lo0bits(&z);
-        if (k >= 16) {
-            x[0] = z;
-            i = 0;
-        } else {
-            x[0] = z & 0xffff;
-            x[1] = z >> 16;
-            i = 1;
-        }
-        k += 32;
-    } while (!x[i])
-        --i;
-    b->resize(i + 1);
-#endif
-#ifndef Sudden_Underflow
     if (de) {
-#endif
         *e = de - Bias - (P - 1) + k;
         *bits = P - k;
-#ifndef Sudden_Underflow
     } else {
         *e = de - Bias - (P - 1) + 1 + k;
-#ifdef Pack_32
         *bits = (32 * i) - hi0bits(x[i - 1]);
-#else
-        *bits = (i + 2) * 16 - hi0bits(x[i]);
-#endif
     }
-#endif
 }
 #undef d0
 #undef d1
@@ -990,11 +718,7 @@ static double ratio(const BigInt& a, const BigInt& b)
 
     dval(&da) = b2d(a, &ka);
     dval(&db) = b2d(b, &kb);
-#ifdef Pack_32
     k = ka - kb + 32 * (a.size() - b.size());
-#else
-    k = ka - kb + 16 * (a.size() - b.size());
-#endif
     if (k > 0)
         word0(&da) += k * Exp_msk1;
     else {
@@ -1005,19 +729,15 @@ static double ratio(const BigInt& a, const BigInt& b)
 }
 
 static const double tens[] = {
-        1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-        1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-        1e20, 1e21, 1e22
+    1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+    1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+    1e20, 1e21, 1e22
 };
 
 static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
 static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
-#ifdef Avoid_Underflow
-        9007199254740992. * 9007199254740992.e-256
-        /* = 2^106 * 1e-53 */
-#else
-        1e-256
-#endif
+    9007199254740992. * 9007199254740992.e-256
+    /* = 2^106 * 1e-256 */
 };
 
 /* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */
@@ -1025,118 +745,42 @@ static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
 #define Scale_Bit 0x10
 #define n_bigtens 5
 
-#if defined(INFNAN_CHECK)
-
-#ifndef NAN_WORD0
-#define NAN_WORD0 0x7ff80000
-#endif
-
-#ifndef NAN_WORD1
-#define NAN_WORD1 0
-#endif
-
-static int match(const char** sp, const char* t)
-{
-    int c, d;
-    const char* s = *sp;
-
-    while ((d = *t++)) {
-        if ((c = *++s) >= 'A' && c <= 'Z')
-            c += 'a' - 'A';
-        if (c != d)
-            return 0;
-    }
-    *sp = s + 1;
-    return 1;
-}
-
-#ifndef No_Hex_NaN
-static void hexnan(U* rvp, const char** sp)
-{
-    uint32_t c, x[2];
-    const char* s;
-    int havedig, udx0, xshift;
-
-    x[0] = x[1] = 0;
-    havedig = xshift = 0;
-    udx0 = 1;
-    s = *sp;
-    while ((c = *(const unsigned char*)++s)) {
-        if (c >= '0' && c <= '9')
-            c -= '0';
-        else if (c >= 'a' && c <= 'f')
-            c += 10 - 'a';
-        else if (c >= 'A' && c <= 'F')
-            c += 10 - 'A';
-        else if (c <= ' ') {
-            if (udx0 && havedig) {
-                udx0 = 0;
-                xshift = 1;
-            }
-            continue;
-        } else if (/*(*/ c == ')' && havedig) {
-            *sp = s + 1;
-            break;
-        } else
-            return;    /* invalid form: don't change *sp */
-        havedig = 1;
-        if (xshift) {
-            xshift = 0;
-            x[0] = x[1];
-            x[1] = 0;
-        }
-        if (udx0)
-            x[0] = (x[0] << 4) | (x[1] >> 28);
-        x[1] = (x[1] << 4) | c;
-    }
-    if ((x[0] &= 0xfffff) || x[1]) {
-        word0(rvp) = Exp_mask | x[0];
-        word1(rvp) = x[1];
-    }
-}
-#endif /*No_Hex_NaN*/
-#endif /* INFNAN_CHECK */
-
 double strtod(const char* s00, char** se)
 {
-#ifdef Avoid_Underflow
     int scale;
-#endif
     int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
-         e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+        e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
     const char *s, *s0, *s1;
     double aadj, aadj1;
     U aadj2, adj, rv, rv0;
     int32_t L;
     uint32_t y, z;
     BigInt bb, bb1, bd, bd0, bs, delta;
-#ifdef SET_INEXACT
-    int inexact, oldinexact;
-#endif
 
     sign = nz0 = nz = 0;
     dval(&rv) = 0;
-    for (s = s00; ; s++)
+    for (s = s00; ; s++) {
         switch (*s) {
-            case '-':
-                sign = 1;
-                /* no break */
-            case '+':
-                if (*++s)
-                    goto break2;
-                /* no break */
-            case 0:
-                goto ret0;
-            case '\t':
-            case '\n':
-            case '\v':
-            case '\f':
-            case '\r':
-            case ' ':
-                continue;
-            default:
+        case '-':
+            sign = 1;
+            /* no break */
+        case '+':
+            if (*++s)
                 goto break2;
+            /* no break */
+        case 0:
+            goto ret0;
+        case '\t':
+        case '\n':
+        case '\v':
+        case '\f':
+        case '\r':
+        case ' ':
+            continue;
+        default:
+            goto break2;
         }
+    }
 break2:
     if (*s == '0') {
         nz0 = 1;
@@ -1161,12 +805,12 @@ break2:
                 s0 = s;
                 nf += nz;
                 nz = 0;
-                goto have_dig;
+                goto haveDig;
             }
-            goto dig_done;
+            goto digDone;
         }
         for (; c >= '0' && c <= '9'; c = *++s) {
-have_dig:
+haveDig:
             nz++;
             if (c -= '0') {
                 nf += nz;
@@ -1183,19 +827,18 @@ have_dig:
             }
         }
     }
-dig_done:
+digDone:
     e = 0;
     if (c == 'e' || c == 'E') {
-        if (!nd && !nz && !nz0) {
+        if (!nd && !nz && !nz0)
             goto ret0;
-        }
         s00 = s;
         esign = 0;
         switch (c = *++s) {
-            case '-':
-                esign = 1;
-            case '+':
-                c = *++s;
+        case '-':
+            esign = 1;
+        case '+':
+            c = *++s;
         }
         if (c >= '0' && c <= '9') {
             while (c == '0')
@@ -1221,33 +864,6 @@ dig_done:
     }
     if (!nd) {
         if (!nz && !nz0) {
-#ifdef INFNAN_CHECK
-            /* Check for Nan and Infinity */
-            switch(c) {
-                case 'i':
-                case 'I':
-                    if (match(&s,"nf")) {
-                        --s;
-                        if (!match(&s,"inity"))
-                            ++s;
-                        word0(&rv) = 0x7ff00000;
-                        word1(&rv) = 0;
-                        goto ret;
-                    }
-                    break;
-                case 'n':
-                case 'N':
-                    if (match(&s, "an")) {
-                        word0(&rv) = NAN_WORD0;
-                        word1(&rv) = NAN_WORD1;
-#ifndef No_Hex_NaN
-                        if (*s == '(') /*)*/
-                            hexnan(&rv, &s);
-#endif
-                        goto ret;
-                    }
-            }
-#endif /* INFNAN_CHECK */
 ret0:
             s = s00;
             sign = 0;
@@ -1265,14 +881,9 @@ ret0:
         nd0 = nd;
     k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
     dval(&rv) = y;
-    if (k > 9) {
-#ifdef SET_INEXACT
-        if (k > DBL_DIG)
-            oldinexact = get_inexact();
-#endif
+    if (k > 9)
         dval(&rv) = tens[k - 9] * dval(&rv) + z;
-    }
-    if (nd <= DBL_DIG && Flt_Rounds == 1) {
+    if (nd <= DBL_DIG) {
         if (!e)
             goto ret;
         if (e > 0) {
@@ -1290,24 +901,14 @@ ret0:
                 /* rv = */ rounded_product(dval(&rv), tens[e]);
                 goto ret;
             }
-        }
-#ifndef Inaccurate_Divide
-        else if (e >= -Ten_pmax) {
+        } else if (e >= -Ten_pmax) {
             /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
             goto ret;
         }
-#endif
     }
     e1 += nd - k;
 
-#ifdef SET_INEXACT
-    inexact = 1;
-    if (k <= DBL_DIG)
-        oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
     scale = 0;
-#endif
 
     /* Get starting approximation = rv * 10**e1 */
 
@@ -1317,17 +918,12 @@ ret0:
         if (e1 &= ~15) {
             if (e1 > DBL_MAX_10_EXP) {
 ovfl:
-#ifndef NO_ERRNO
+#if HAVE(ERRNO_H)
                 errno = ERANGE;
 #endif
                 /* Can't trust HUGE_VAL */
                 word0(&rv) = Exp_mask;
                 word1(&rv) = 0;
-#ifdef SET_INEXACT
-                /* set overflow bit */
-                dval(&rv0) = 1e300;
-                dval(&rv0) *= dval(&rv0);
-#endif
                 goto ret;
             }
             e1 >>= 4;
@@ -1354,50 +950,30 @@ ovfl:
         if (e1 >>= 4) {
             if (e1 >= 1 << n_bigtens)
                 goto undfl;
-#ifdef Avoid_Underflow
             if (e1 & Scale_Bit)
                 scale = 2 * P;
             for (j = 0; e1 > 0; j++, e1 >>= 1)
                 if (e1 & 1)
                     dval(&rv) *= tinytens[j];
             if (scale && (j = (2 * P) + 1 - ((word0(&rv) & Exp_mask) >> Exp_shift)) > 0) {
-                /* scaled rv is denormal; zap j low bits */
+                /* scaled rv is denormal; clear j low bits */
                 if (j >= 32) {
                     word1(&rv) = 0;
                     if (j >= 53)
-                       word0(&rv) = (P + 2) * Exp_msk1;
+                        word0(&rv) = (P + 2) * Exp_msk1;
                     else
-                       word0(&rv) &= 0xffffffff << (j - 32);
+                        word0(&rv) &= 0xffffffff << (j - 32);
                 } else
                     word1(&rv) &= 0xffffffff << j;
             }
-#else
-            for (j = 0; e1 > 1; j++, e1 >>= 1)
-                if (e1 & 1)
-                    dval(&rv) *= tinytens[j];
-            /* The last multiplication could underflow. */
-            dval(&rv0) = dval(&rv);
-            dval(&rv) *= tinytens[j];
-            if (!dval(&rv)) {
-                dval(&rv) = 2. * dval(&rv0);
-                dval(&rv) *= tinytens[j];
-#endif
                 if (!dval(&rv)) {
 undfl:
                     dval(&rv) = 0.;
-#ifndef NO_ERRNO
+#if HAVE(ERRNO_H)
                     errno = ERANGE;
 #endif
                     goto ret;
                 }
-#ifndef Avoid_Underflow
-                word0(&rv) = Tiny0;
-                word1(&rv) = Tiny1;
-                /* The refinement below will clean
-                 * this approximation up.
-                 */
-            }
-#endif
         }
     }
 
@@ -1424,30 +1000,15 @@ undfl:
         else
             bd2 -= bbe;
         bs2 = bb2;
-#ifdef Avoid_Underflow
         j = bbe - scale;
         i = j + bbbits - 1;    /* logb(rv) */
         if (i < Emin)    /* denormal */
             j += P - Emin;
         else
             j = P + 1 - bbbits;
-#else /*Avoid_Underflow*/
-#ifdef Sudden_Underflow
-        j = P + 1 - bbbits;
-#else /*Sudden_Underflow*/
-        j = bbe;
-        i = j + bbbits - 1;    /* logb(rv) */
-        if (i < Emin)    /* denormal */
-            j += P - Emin;
-        else
-            j = P + 1 - bbbits;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
         bb2 += j;
         bd2 += j;
-#ifdef Avoid_Underflow
         bd2 += scale;
-#endif
         i = bb2 < bd2 ? bb2 : bd2;
         if (i > bs2)
             i = bs2;
@@ -1478,62 +1039,36 @@ undfl:
              * special case of mantissa a power of two.
              */
             if (dsign || word1(&rv) || word0(&rv) & Bndry_mask
-#ifdef Avoid_Underflow
              || (word0(&rv) & Exp_mask) <= (2 * P + 1) * Exp_msk1
-#else
-             || (word0(&rv) & Exp_mask) <= Exp_msk1
-#endif
                 ) {
-#ifdef SET_INEXACT
-                if (!delta->words()[0] && delta->size() <= 1)
-                    inexact = 0;
-#endif
                 break;
             }
             if (!delta.words()[0] && delta.size() <= 1) {
                 /* exact result */
-#ifdef SET_INEXACT
-                inexact = 0;
-#endif
                 break;
             }
             lshift(delta, Log2P);
             if (cmp(delta, bs) > 0)
-                goto drop_down;
+                goto dropDown;
             break;
         }
-        if (i == 0) {
+        if (!i) {
             /* exactly half-way between */
             if (dsign) {
                 if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
                  &&  word1(&rv) == (
-#ifdef Avoid_Underflow
             (scale && (y = word0(&rv) & Exp_mask) <= 2 * P * Exp_msk1)
         ? (0xffffffff & (0xffffffff << (2 * P + 1 - (y >> Exp_shift)))) :
-#endif
                            0xffffffff)) {
                     /*boundary case -- increment exponent*/
                     word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1;
                     word1(&rv) = 0;
-#ifdef Avoid_Underflow
                     dsign = 0;
-#endif
                     break;
                 }
             } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
-drop_down:
+dropDown:
                 /* boundary case -- decrement exponent */
-#ifdef Sudden_Underflow /*{{*/
-                L = word0(&rv) & Exp_mask;
-#ifdef Avoid_Underflow
-                if (L <= (scale ? (2 * P + 1) * Exp_msk1 : Exp_msk1))
-#else
-                if (L <= Exp_msk1)
-#endif /*Avoid_Underflow*/
-                    goto undfl;
-                L -= Exp_msk1;
-#else /*Sudden_Underflow}{*/
-#ifdef Avoid_Underflow
                 if (scale) {
                     L = word0(&rv) & Exp_mask;
                     if (L <= (2 * P + 1) * Exp_msk1) {
@@ -1545,9 +1080,7 @@ drop_down:
                         goto undfl;
                     }
                 }
-#endif /*Avoid_Underflow*/
                 L = (word0(&rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
                 word0(&rv) = L | Bndry_mask1;
                 word1(&rv) = 0xffffffff;
                 break;
@@ -1558,24 +1091,18 @@ drop_down:
                 dval(&rv) += ulp(&rv);
             else {
                 dval(&rv) -= ulp(&rv);
-#ifndef Sudden_Underflow
                 if (!dval(&rv))
                     goto undfl;
-#endif
             }
-#ifdef Avoid_Underflow
             dsign = 1 - dsign;
-#endif
             break;
         }
         if ((aadj = ratio(delta, bs)) <= 2.) {
             if (dsign)
                 aadj = aadj1 = 1.;
             else if (word1(&rv) || word0(&rv) & Bndry_mask) {
-#ifndef Sudden_Underflow
                 if (word1(&rv) == Tiny1 && !word0(&rv))
                     goto undfl;
-#endif
                 aadj = 1.;
                 aadj1 = -1.;
             } else {
@@ -1591,19 +1118,6 @@ drop_down:
         } else {
             aadj *= 0.5;
             aadj1 = dsign ? aadj : -aadj;
-#ifdef Check_FLT_ROUNDS
-            switch (Rounding) {
-                case 2: /* towards +infinity */
-                    aadj1 -= 0.5;
-                    break;
-                case 0: /* towards 0 */
-                case 3: /* towards -infinity */
-                    aadj1 += 0.5;
-            }
-#else
-            if (Flt_Rounds == 0)
-                aadj1 += 0.5;
-#endif /*Check_FLT_ROUNDS*/
         }
         y = word0(&rv) & Exp_mask;
 
@@ -1620,10 +1134,9 @@ drop_down:
                 word0(&rv) = Big0;
                 word1(&rv) = Big1;
                 goto cont;
-            } else
-                word0(&rv) += P * Exp_msk1;
+            }
+            word0(&rv) += P * Exp_msk1;
         } else {
-#ifdef Avoid_Underflow
             if (scale && y <= 2 * P * Exp_msk1) {
                 if (aadj <= 0x7fffffff) {
                     if ((z = (uint32_t)aadj) <= 0)
@@ -1637,51 +1150,9 @@ drop_down:
             }
             adj.d = aadj1 * ulp(&rv);
             dval(&rv) += adj.d;
-#else
-#ifdef Sudden_Underflow
-            if ((word0(&rv) & Exp_mask) <= P * Exp_msk1) {
-                dval(&rv0) = dval(&rv);
-                word0(&rv) += P * Exp_msk1;
-                adj.d = aadj1 * ulp(&rv);
-                dval(&rv) += adj.d;
-                if ((word0(&rv) & Exp_mask) <= P * Exp_msk1)
-                {
-                    if (word0(&rv0) == Tiny0 && word1(&rv0) == Tiny1)
-                        goto undfl;
-                    word0(&rv) = Tiny0;
-                    word1(&rv) = Tiny1;
-                    goto cont;
-                }
-                else
-                    word0(&rv) -= P * Exp_msk1;
-            } else {
-                adj.d = aadj1 * ulp(&rv);
-                dval(&rv) += adj.d;
-            }
-#else /*Sudden_Underflow*/
-            /* Compute adj so that the IEEE rounding rules will
-             * correctly round rv + adj in some half-way cases.
-             * If rv * ulp(rv) is denormalized (i.e.,
-             * y <= (P - 1) * Exp_msk1), we must adjust aadj to avoid
-             * trouble from bits lost to denormalization;
-             * example: 1.2e-307 .
-             */
-            if (y <= (P - 1) * Exp_msk1 && aadj > 1.) {
-                aadj1 = (double)(int)(aadj + 0.5);
-                if (!dsign)
-                    aadj1 = -aadj1;
-            }
-            adj.d = aadj1 * ulp(&rv);
-            dval(&rv) += adj.d;
-#endif /*Sudden_Underflow*/
-#endif /*Avoid_Underflow*/
         }
         z = word0(&rv) & Exp_mask;
-#ifndef SET_INEXACT
-#ifdef Avoid_Underflow
-        if (!scale)
-#endif
-        if (y == z) {
+        if (!scale && y == z) {
             /* Can we stop now? */
             L = (int32_t)aadj;
             aadj -= L;
@@ -1692,39 +1163,19 @@ drop_down:
             } else if (aadj < .4999999 / FLT_RADIX)
                 break;
         }
-#endif
 cont:
-        ;
-    }
-#ifdef SET_INEXACT
-    if (inexact) {
-        if (!oldinexact) {
-            word0(&rv0) = Exp_1 + (70 << Exp_shift);
-            word1(&rv0) = 0;
-            dval(&rv0) += 1.;
-        }
-    } else if (!oldinexact)
-        clear_inexact();
-#endif
-#ifdef Avoid_Underflow
+        {}
+    }
     if (scale) {
         word0(&rv0) = Exp_1 - 2 * P * Exp_msk1;
         word1(&rv0) = 0;
         dval(&rv) *= dval(&rv0);
-#ifndef NO_ERRNO
+#if HAVE(ERRNO_H)
         /* try to avoid the bug of testing an 8087 register value */
-        if (word0(&rv) == 0 && word1(&rv) == 0)
+        if (!word0(&rv) && !word1(&rv))
             errno = ERANGE;
 #endif
     }
-#endif /* Avoid_Underflow */
-#ifdef SET_INEXACT
-    if (inexact && !(word0(&rv) & Exp_mask)) {
-        /* set underflow bit */
-        dval(&rv0) = 1e-300;
-        dval(&rv0) *= dval(&rv0);
-    }
-#endif
 ret:
     if (se)
         *se = const_cast<char*>(s);
@@ -1734,14 +1185,16 @@ ret:
 static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
 {
     size_t n;
-    uint32_t *bx, *bxe, q, *sx, *sxe;
+    uint32_t* bx;
+    uint32_t* bxe;
+    uint32_t q;
+    uint32_t* sx;
+    uint32_t* sxe;
 #ifdef USE_LONG_LONG
     unsigned long long borrow, carry, y, ys;
 #else
     uint32_t borrow, carry, y, ys;
-#ifdef Pack_32
     uint32_t si, z, zs;
-#endif
 #endif
     ASSERT(b.size() <= 1 || b.words()[b.size() - 1]);
     ASSERT(S.size() <= 1 || S.words()[S.size() - 1]);
@@ -1767,7 +1220,6 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
             borrow = y >> 32 & (uint32_t)1;
             *bx++ = (uint32_t)y & 0xffffffffUL;
 #else
-#ifdef Pack_32
             si = *sx++;
             ys = (si & 0xffff) * q + carry;
             zs = (si >> 16) * q + (ys >> 16);
@@ -1776,14 +1228,7 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
             borrow = (y & 0x10000) >> 16;
             z = (*bx >> 16) - (zs & 0xffff) - borrow;
             borrow = (z & 0x10000) >> 16;
-            Storeinc(bx, z, y);
-#else
-            ys = *sx++ * q + carry;
-            carry = ys >> 16;
-            y = *bx - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            *bx++ = y & 0xffff;
-#endif
+            bx = storeInc(bx, z, y);
 #endif
         } while (sx <= sxe);
         if (!*bxe) {
@@ -1807,7 +1252,6 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
             borrow = y >> 32 & (uint32_t)1;
             *bx++ = (uint32_t)y & 0xffffffffUL;
 #else
-#ifdef Pack_32
             si = *sx++;
             ys = (si & 0xffff) + carry;
             zs = (si >> 16) + (ys >> 16);
@@ -1816,14 +1260,7 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
             borrow = (y & 0x10000) >> 16;
             z = (*bx >> 16) - (zs & 0xffff) - borrow;
             borrow = (z & 0x10000) >> 16;
-            Storeinc(bx, z, y);
-#else
-            ys = *sx++ + carry;
-            carry = ys >> 16;
-            y = *bx - (ys & 0xffff) - borrow;
-            borrow = (y & 0x10000) >> 16;
-            *bx++ = y & 0xffff;
-#endif
+            bx = storeInc(bx, z, y);
 #endif
         } while (sx <= sxe);
         bx = b.words();
@@ -1840,7 +1277,7 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
 /* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
  *
  * Inspired by "How to Print Floating-Point Numbers Accurately" by
- * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126].
  *
  * Modifications:
  *    1. Rather than iterating, we use a simple numeric overestimate
@@ -1869,78 +1306,54 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S)
  *       "uniformly" distributed input, the probability is
  *       something like 10^(k-15) that we must resort to the int32_t
  *       calculation.
+ *
+ * Note: 'leftright' translates to 'generate shortest possible string'.
  */
-
-void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char** rve)
+template<bool roundingNone, bool roundingSignificantFigures, bool roundingDecimalPlaces, bool leftright>
+void dtoa(DtoaBuffer result, double dd, int ndigits, bool& signOut, int& exponentOut, unsigned& precisionOut)
 {
-    /*
-        Arguments ndigits, decpt, sign are similar to those
-    of ecvt and fcvt; trailing zeros are suppressed from
-    the returned string.  If not null, *rve is set to point
-    to the end of the return value.  If d is +-Infinity or NaN,
-    then *decpt is set to 9999.
+    // Exactly one rounding mode must be specified.
+    ASSERT(roundingNone + roundingSignificantFigures + roundingDecimalPlaces == 1);
+    // roundingNone only allowed (only sensible?) with leftright set.
+    ASSERT(!roundingNone || leftright);
 
-    */
+    ASSERT(!isnan(dd) && !isinf(dd));
 
     int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0,
-        j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
-        spec_case, try_quick;
+        j, j1, k, k0, k_check, m2, m5, s2, s5,
+        spec_case;
     int32_t L;
-#ifndef Sudden_Underflow
     int denorm;
     uint32_t x;
-#endif
-    BigInt b, b1, delta, mlo, mhi, S;
+    BigInt b, delta, mlo, mhi, S;
     U d2, eps, u;
     double ds;
-    char *s, *s0;
-#ifdef SET_INEXACT
-    int inexact, oldinexact;
-#endif
+    char* s;
+    char* s0;
 
     u.d = dd;
-    if (word0(&u) & Sign_bit) {
-        /* set sign for everything, including 0's and NaNs */
-        *sign = 1;
-        word0(&u) &= ~Sign_bit;    /* clear sign bit */
-    } else
-        *sign = 0;
 
-    if ((word0(&u) & Exp_mask) == Exp_mask)
-    {
-        /* Infinity or NaN */
-        *decpt = 9999;
-        if (!word1(&u) && !(word0(&u) & 0xfffff)) {
-            strcpy(result, "Infinity");
-            if (rve)
-                *rve = result + 8;
-        } else {
-            strcpy(result, "NaN");
-            if (rve)
-                *rve = result + 3;
-        }
-        return;
-    }
+    /* Infinity or NaN */
+    ASSERT((word0(&u) & Exp_mask) != Exp_mask);
+
+    // JavaScript toString conversion treats -0 as 0.
     if (!dval(&u)) {
-        *decpt = 1;
+        signOut = false;
+        exponentOut = 0;
+        precisionOut = 1;
         result[0] = '0';
         result[1] = '\0';
-        if (rve)
-            *rve = result + 1;
         return;
     }
 
-#ifdef SET_INEXACT
-    try_quick = oldinexact = get_inexact();
-    inexact = 1;
-#endif
+    if (word0(&u) & Sign_bit) {
+        signOut = true;
+        word0(&u) &= ~Sign_bit; // clear sign bit
+    } else
+        signOut = false;
 
     d2b(b, &u, &be, &bbits);
-#ifdef Sudden_Underflow
-    i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1));
-#else
     if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
-#endif
         dval(&d2) = dval(&u);
         word0(&d2) &= Frac_mask1;
         word0(&d2) |= Exp_11;
@@ -1968,7 +1381,6 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
          */
 
         i -= Bias;
-#ifndef Sudden_Underflow
         denorm = 0;
     } else {
         /* d is denormalized */
@@ -1981,7 +1393,6 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
         i -= (Bias + (P - 1) - 1) + 1;
         denorm = 1;
     }
-#endif
     ds = (dval(&d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981);
     k = (int)ds;
     if (ds < 0. && ds != k)
@@ -2010,22 +1421,27 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
         s5 = 0;
     }
 
-#ifndef SET_INEXACT
-#ifdef Check_FLT_ROUNDS
-    try_quick = Rounding == 1;
-#else
-    try_quick = 1;
-#endif
-#endif /*SET_INEXACT*/
+    if (roundingNone) {
+        ilim = ilim1 = -1;
+        i = 18;
+        ndigits = 0;
+    }
+    if (roundingSignificantFigures) {
+        if (ndigits <= 0)
+            ndigits = 1;
+        ilim = ilim1 = i = ndigits;
+    }
+    if (roundingDecimalPlaces) {
+        i = ndigits + k + 1;
+        ilim = i;
+        ilim1 = i - 1;
+        if (i <= 0)
+            i = 1;
+    }
 
-    leftright = 1;
-    ilim = ilim1 = -1;
-    i = 18;
-    ndigits = 0;
     s = s0 = result;
 
-    if (ilim >= 0 && ilim <= Quick_max && try_quick) {
-
+    if (ilim >= 0 && ilim <= Quick_max) {
         /* Try to get by with floating-point arithmetic. */
 
         i = 0;
@@ -2060,7 +1476,7 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
         }
         if (k_check && dval(&u) < 1. && ilim > 0) {
             if (ilim1 <= 0)
-                goto fast_failed;
+                goto fastFailed;
             ilim = ilim1;
             k--;
             dval(&u) *= 10.;
@@ -2068,17 +1484,16 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
         }
         dval(&eps) = (ieps * dval(&u)) + 7.;
         word0(&eps) -= (P - 1) * Exp_msk1;
-        if (ilim == 0) {
+        if (!ilim) {
             S.clear();
             mhi.clear();
             dval(&u) -= 5.;
             if (dval(&u) > dval(&eps))
-                goto one_digit;
+                goto oneDigit;
             if (dval(&u) < -dval(&eps))
-                goto no_digits;
-            goto fast_failed;
+                goto noDigits;
+            goto fastFailed;
         }
-#ifndef No_leftright
         if (leftright) {
             /* Use Steele & White method of only
              * generating digits needed.
@@ -2091,14 +1506,13 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
                 if (dval(&u) < dval(&eps))
                     goto ret;
                 if (1. - dval(&u) < dval(&eps))
-                    goto bump_up;
+                    goto bumpUp;
                 if (++i >= ilim)
                     break;
                 dval(&eps) *= 10.;
                 dval(&u) *= 10.;
             }
         } else {
-#endif
             /* Generate ilim digits, then fix them up. */
             dval(&eps) *= tens[ilim - 1];
             for (i = 1;; i++, dval(&u) *= 10.) {
@@ -2108,8 +1522,8 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
                 *s++ = '0' + (int)L;
                 if (i == ilim) {
                     if (dval(&u) > 0.5 + dval(&eps))
-                        goto bump_up;
-                    else if (dval(&u) < 0.5 - dval(&eps)) {
+                        goto bumpUp;
+                    if (dval(&u) < 0.5 - dval(&eps)) {
                         while (*--s == '0') { }
                         s++;
                         goto ret;
@@ -2117,10 +1531,8 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
                     break;
                 }
             }
-#ifndef No_leftright
         }
-#endif
-fast_failed:
+fastFailed:
         s = s0;
         dval(&u) = dval(&d2);
         k = k0;
@@ -2136,30 +1548,20 @@ fast_failed:
             S.clear();
             mhi.clear();
             if (ilim < 0 || dval(&u) <= 5 * ds)
-                goto no_digits;
-            goto one_digit;
+                goto noDigits;
+            goto oneDigit;
         }
         for (i = 1;; i++, dval(&u) *= 10.) {
             L = (int32_t)(dval(&u) / ds);
             dval(&u) -= L * ds;
-#ifdef Check_FLT_ROUNDS
-            /* If FLT_ROUNDS == 2, L will usually be high by 1 */
-            if (dval(&u) < 0) {
-                L--;
-                dval(&u) += ds;
-            }
-#endif
             *s++ = '0' + (int)L;
             if (!dval(&u)) {
-#ifdef SET_INEXACT
-                inexact = 0;
-#endif
                 break;
             }
             if (i == ilim) {
                 dval(&u) += dval(&u);
                 if (dval(&u) > ds || (dval(&u) == ds && (L & 1))) {
-bump_up:
+bumpUp:
                     while (*--s == '9')
                         if (s == s0) {
                             k++;
@@ -2179,11 +1581,7 @@ bump_up:
     mhi.clear();
     mlo.clear();
     if (leftright) {
-        i =
-#ifndef Sudden_Underflow
-            denorm ? be + (Bias + (P - 1) - 1 + 1) :
-#endif
-            1 + P - bbits;
+        i = denorm ? be + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits;
         b2 += i;
         s2 += i;
         i2b(mhi, 1);
@@ -2204,7 +1602,7 @@ bump_up:
                 pow5mult(b, j);
         } else
             pow5mult(b, b5);
-        }
+    }
     i2b(S, 1);
     if (s5 > 0)
         pow5mult(S, s5);
@@ -2212,11 +1610,7 @@ bump_up:
     /* Check for special case that d is a normalized power of 2. */
 
     spec_case = 0;
-    if (!word1(&u) && !(word0(&u) & Bndry_mask)
-#ifndef Sudden_Underflow
-     && word0(&u) & (Exp_mask & ~Exp_msk1)
-#endif
-            ) {
+    if ((roundingNone || leftright) && (!word1(&u) && !(word0(&u) & Bndry_mask) && word0(&u) & (Exp_mask & ~Exp_msk1))) {
         /* The special case */
         b2 += Log2P;
         s2 += Log2P;
@@ -2230,13 +1624,8 @@ bump_up:
      * and for all and pass them and a shift to quorem, so it
      * can do shifts and ors to compute the numerator for q.
      */
-#ifdef Pack_32
     if ((i = ((s5 ? 32 - hi0bits(S.words()[S.size() - 1]) : 1) + s2) & 0x1f))
         i = 32 - i;
-#else
-    if ((i = ((s5 ? 32 - hi0bits(S.words()[S.size() - 1]) : 1) + s2) & 0xf))
-        i = 16 - i;
-#endif
     if (i > 4) {
         i -= 4;
         b2 += i;
@@ -2253,7 +1642,7 @@ bump_up:
     if (s2 > 0)
         lshift(S, s2);
     if (k_check) {
-        if (cmp(b,S) < 0) {
+        if (cmp(b, S) < 0) {
             k--;
             multadd(b, 10, 0);    /* we botched the k estimate */
             if (leftright)
@@ -2261,7 +1650,15 @@ bump_up:
             ilim = ilim1;
         }
     }
-
+    if (ilim <= 0 && roundingDecimalPlaces) {
+        if (ilim < 0)
+            goto noDigits;
+        multadd(S, 5, 0);
+        // For IEEE-754 unbiased rounding this check should be <=, such that 0.5 would flush to zero.
+        if (cmp(b, S) < 0)
+            goto noDigits;
+        goto oneDigit;
+    }
     if (leftright) {
         if (m2 > 0)
             lshift(mhi, m2);
@@ -2271,51 +1668,60 @@ bump_up:
          */
 
         mlo = mhi;
-        if (spec_case) {
-            mhi = mlo;
+        if (spec_case)
             lshift(mhi, Log2P);
-        }
 
         for (i = 1;;i++) {
-            dig = quorem(b,S) + '0';
+            dig = quorem(b, S) + '0';
             /* Do we yet have the shortest decimal string
              * that will round to d?
              */
             j = cmp(b, mlo);
             diff(delta, S, mhi);
             j1 = delta.sign ? 1 : cmp(b, delta);
-            if (j1 == 0 && !(word1(&u) & 1)) {
+#ifdef DTOA_ROUND_BIASED
+            if (j < 0 || !j) {
+#else
+            // FIXME: ECMA-262 specifies that equidistant results round away from
+            // zero, which probably means we shouldn't be on the unbiased code path
+            // (the (word1(&u) & 1) clause is looking highly suspicious). I haven't
+            // yet understood this code well enough to make the call, but we should
+            // probably be enabling DTOA_ROUND_BIASED. I think the interesting corner
+            // case to understand is probably "Math.pow(0.5, 24).toString()".
+            // I believe this value is interesting because I think it is precisely
+            // representable in binary floating point, and its decimal representation
+            // has a single digit that Steele & White reduction can remove, with the
+            // value 5 (thus equidistant from the next numbers above and below).
+            // We produce the correct answer using either codepath, and I don't as
+            // yet understand why. :-)
+            if (!j1 && !(word1(&u) & 1)) {
                 if (dig == '9')
-                    goto round_9_up;
+                    goto round9up;
                 if (j > 0)
                     dig++;
-#ifdef SET_INEXACT
-                else if (!b->x[0] && b->wds <= 1)
-                    inexact = 0;
-#endif
                 *s++ = dig;
                 goto ret;
             }
-            if (j < 0 || (j == 0 && !(word1(&u) & 1))) {
-                if (!b.words()[0] && b.size() <= 1) {
-#ifdef SET_INEXACT
-                    inexact = 0;
+            if (j < 0 || (!j && !(word1(&u) & 1))) {
 #endif
-                    goto accept_dig;
-                }
-                if (j1 > 0) {
+                if ((b.words()[0] || b.size() > 1) && (j1 > 0)) {
                     lshift(b, 1);
                     j1 = cmp(b, S);
-                    if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
-                        goto round_9_up;
+                    // For IEEE-754 round-to-even, this check should be (j1 > 0 || (!j1 && (dig & 1))),
+                    // but ECMA-262 specifies that equidistant values (e.g. (.5).toFixed()) should
+                    // be rounded away from zero.
+                    if (j1 >= 0) {
+                        if (dig == '9')
+                            goto round9up;
+                        dig++;
+                    }
                 }
-accept_dig:
                 *s++ = dig;
                 goto ret;
             }
             if (j1 > 0) {
                 if (dig == '9') { /* possible if i == 1 */
-round_9_up:
+round9up:
                     *s++ = '9';
                     goto roundoff;
                 }
@@ -2329,25 +1735,25 @@ round_9_up:
             multadd(mlo, 10, 0);
             multadd(mhi, 10, 0);
         }
-    } else
+    } else {
         for (i = 1;; i++) {
-            *s++ = dig = quorem(b,S) + '0';
-            if (!b.words()[0] && b.size() <= 1) {
-#ifdef SET_INEXACT
-                inexact = 0;
-#endif
+            *s++ = dig = quorem(b, S) + '0';
+            if (!b.words()[0] && b.size() <= 1)
                 goto ret;
-            }
             if (i >= ilim)
                 break;
             multadd(b, 10, 0);
         }
+    }
 
     /* Round off last digit */
 
     lshift(b, 1);
     j = cmp(b, S);
-    if (j > 0 || (j == 0 && (dig & 1))) {
+    // For IEEE-754 round-to-even, this check should be (j > 0 || (!j && (dig & 1))),
+    // but ECMA-262 specifies that equidistant values (e.g. (.5).toFixed()) should
+    // be rounded away from zero.
+    if (j >= 0) {
 roundoff:
         while (*--s == '9')
             if (s == s0) {
@@ -2361,107 +1767,68 @@ roundoff:
         s++;
     }
     goto ret;
-no_digits:
-    k = -1 - ndigits;
-    goto ret;
-one_digit:
+noDigits:
+    exponentOut = 0;
+    precisionOut = 1;
+    result[0] = '0';
+    result[1] = '\0';
+    return;
+oneDigit:
     *s++ = '1';
     k++;
     goto ret;
 ret:
-#ifdef SET_INEXACT
-    if (inexact) {
-        if (!oldinexact) {
-            word0(&u) = Exp_1 + (70 << Exp_shift);
-            word1(&u) = 0;
-            dval(&u) += 1.;
-        }
-    } else if (!oldinexact)
-        clear_inexact();
-#endif
+    ASSERT(s > result);
     *s = 0;
-    *decpt = k + 1;
-    if (rve)
-        *rve = s;
+    exponentOut = k;
+    precisionOut = s - result;
 }
 
-static ALWAYS_INLINE void append(char*& next, const char* src, unsigned size)
+void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision)
 {
-    for (unsigned i = 0; i < size; ++i)
-        *next++ = *src++;
+    // flags are roundingNone, leftright.
+    dtoa<true, false, false, true>(result, dd, 0, sign, exponent, precision);
 }
 
-void doubleToStringInJavaScriptFormat(double d, DtoaBuffer buffer, unsigned* resultLength)
+void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision)
 {
-    ASSERT(buffer);
+    // flag is roundingSignificantFigures.
+    dtoa<false, true, false, false>(result, dd, ndigits, sign, exponent, precision);
+}
 
-    // avoid ever printing -NaN, in JS conceptually there is only one NaN value
-    if (isnan(d)) {
-        append(buffer, "NaN", 3);
-        if (resultLength)
-            *resultLength = 3;
-        return;
-    }
-    // -0 -> "0"
-    if (!d) {
-        buffer[0] = '0';
-        if (resultLength)
-            *resultLength = 1;
-        return;
-    }
+void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision)
+{
+    // flag is roundingDecimalPlaces.
+    dtoa<false, false, true, false>(result, dd, ndigits, sign, exponent, precision);
+}
 
-    int decimalPoint;
-    int sign;
+static ALWAYS_INLINE void copyAsciiToUTF16(UChar* next, const char* src, unsigned size)
+{
+    for (unsigned i = 0; i < size; ++i)
+        *next++ = *src++;
+}
 
-    DtoaBuffer result;
-    char* resultEnd = 0;
-    WTF::dtoa(result, d, 0, &decimalPoint, &sign, &resultEnd);
-    int length = resultEnd - result;
-
-    char* next = buffer;
-    if (sign)
-        *next++ = '-';
-
-    if (decimalPoint <= 0 && decimalPoint > -6) {
-        *next++ = '0';
-        *next++ = '.';
-        for (int j = decimalPoint; j < 0; j++)
-            *next++ = '0';
-        append(next, result, length);
-    } else if (decimalPoint <= 21 && decimalPoint > 0) {
-        if (length <= decimalPoint) {
-            append(next, result, length);
-            for (int j = 0; j < decimalPoint - length; j++)
-                *next++ = '0';
-        } else {
-            append(next, result, decimalPoint);
-            *next++ = '.';
-            append(next, result + decimalPoint, length - decimalPoint);
+unsigned numberToString(double d, NumberToStringBuffer buffer)
+{
+    // Handle NaN and Infinity.
+    if (isnan(d) || isinf(d)) {
+        if (isnan(d)) {
+            copyAsciiToUTF16(buffer, "NaN", 3);
+            return 3;
         }
-    } else if (result[0] < '0' || result[0] > '9')
-        append(next, result, length);
-    else {
-        *next++ = result[0];
-        if (length > 1) {
-            *next++ = '.';
-            append(next, result + 1, length - 1);
+        if (d > 0) {
+            copyAsciiToUTF16(buffer, "Infinity", 8);
+            return 8;
         }
+        copyAsciiToUTF16(buffer, "-Infinity", 9);
+        return 9;
+    }
 
-        *next++ = 'e';
-        *next++ = (decimalPoint >= 0) ? '+' : '-';
-        // decimalPoint can't be more than 3 digits decimal given the
-        // nature of float representation
-        int exponential = decimalPoint - 1;
-        if (exponential < 0)
-            exponential = -exponential;
-        if (exponential >= 100)
-            *next++ = static_cast<char>('0' + exponential / 100);
-        if (exponential >= 10)
-            *next++ = static_cast<char>('0' + (exponential % 100) / 10);
-        *next++ = static_cast<char>('0' + exponential % 10);
-    }
-    if (resultLength)
-        *resultLength = next - buffer;
+    // Convert to decimal with rounding.
+    DecimalNumber number(d);
+    return number.exponent() >= -6 && number.exponent() < 21
+        ? number.toStringDecimal(buffer, NumberToStringBufferLength)
+        : number.toStringExponential(buffer, NumberToStringBufferLength);
 }
 
 } // namespace WTF
index 6127f53972a3180bd3b8c03c7ed3768bb9b26338..3924a1cc405db293b01f6d4bdae657595258172c 100644 (file)
 #ifndef WTF_dtoa_h
 #define WTF_dtoa_h
 
-namespace WTF {
-    class Mutex;
-}
+#include <wtf/unicode/Unicode.h>
 
 namespace WTF {
+class Mutex;
+
+extern WTF::Mutex* s_dtoaP5Mutex;
 
-    extern WTF::Mutex* s_dtoaP5Mutex;
+// s00: input string. Must not be 0 and must be terminated by 0.
+// se: *se will have the last consumed character position + 1.
+double strtod(const char* s00, char** se);
 
-    double strtod(const char* s00, char** se);
+typedef char DtoaBuffer[80];
 
-    typedef char DtoaBuffer[80];
-    void dtoa(DtoaBuffer result, double d, int ndigits, int* decpt, int* sign, char** rve);
+void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision);
+void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
+void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision);
 
-    // dtoa() for ECMA-262 'ToString Applied to the Number Type.'
-    // The *resultLength will have the length of the resultant string in bufer.
-    // The resultant string isn't terminated by 0.
-    void doubleToStringInJavaScriptFormat(double, DtoaBuffer, unsigned* resultLength);
+// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits.
+const unsigned NumberToStringBufferLength = 96;
+typedef UChar NumberToStringBuffer[NumberToStringBufferLength];
+unsigned numberToString(double, NumberToStringBuffer);
 
 } // namespace WTF
 
-using WTF::DtoaBuffer;
-using WTF::doubleToStringInJavaScriptFormat;
+using WTF::NumberToStringBuffer;
+using WTF::numberToString;
 
 #endif // WTF_dtoa_h
index fe32d1b8d1d97aa33de89c50a7551d8ad1714760..8774d20b663e254344fc6d783d0133692bec616c 100644 (file)
@@ -42,7 +42,7 @@ void initializeMainThreadPlatform()
 {
 }
 
-static int timeoutFired(void*)
+static Eina_Bool timeoutFired(void*)
 {
     dispatchFunctionsFromMainThread();
     return ECORE_CALLBACK_CANCEL;
index da0d83996edf75651c63f5368fd208ae81f03501..7c51ee1bd6f3b53bac64bab4846d86c2403fecf0 100644 (file)
@@ -19,6 +19,8 @@
 #include "config.h"
 #include "GOwnPtr.h"
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include <gio/gio.h>
 #include <glib.h>
 
@@ -59,9 +61,6 @@ template <> void freeOwnedGPtr<GDir>(GDir* ptr)
         g_dir_close(ptr);
 }
 
-template <> void freeOwnedGPtr<GFile>(GFile* ptr)
-{
-    if (ptr)
-        g_object_unref(ptr);
-}
 } // namespace WTF
+
+#endif // ENABLE(GLIB_SUPPORT)
index 1fc594c9fa42c246af104bf84012876b6bf7db7e..8c7e8372f73ff790841b59a8f914d0d9a655f8b2 100644 (file)
 #ifndef GOwnPtr_h
 #define GOwnPtr_h
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include <algorithm>
 #include <wtf/Assertions.h>
 #include <wtf/Noncopyable.h>
 
-// Forward delcarations at this point avoid the need to include GLib includes
-// in WTF headers.
-typedef struct _GError GError;
-typedef struct _GList GList;
-typedef struct _GCond GCond;
-typedef struct _GMutex GMutex;
-typedef struct _GPatternSpec GPatternSpec;
-typedef struct _GDir GDir;
-typedef struct _GHashTable GHashTable;
-typedef struct _GFile GFile;
 extern "C" void g_free(void*);
 
 namespace WTF {
@@ -47,10 +39,9 @@ template<> void freeOwnedGPtr<GCond>(GCond*);
 template<> void freeOwnedGPtr<GMutex>(GMutex*);
 template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*);
 template<> void freeOwnedGPtr<GDir>(GDir*);
-template<> void freeOwnedGPtr<GHashTable>(GHashTable*);
-template<> void freeOwnedGPtr<GFile>(GFile*);
 
-template <typename T> class GOwnPtr : public Noncopyable {
+template <typename T> class GOwnPtr {
+    WTF_MAKE_NONCOPYABLE(GOwnPtr);
 public:
     explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
     ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
@@ -78,8 +69,9 @@ public:
 
     void clear()
     {
-        freeOwnedGPtr(m_ptr);
+        T* ptr = m_ptr;
         m_ptr = 0;
+        freeOwnedGPtr(ptr);
     }
 
     T& operator*() const
@@ -145,4 +137,7 @@ template <typename T> inline void freeOwnedGPtr(T* ptr)
 
 using WTF::GOwnPtr;
 
+#endif // ENABLE(GLIB_SUPPORT)
+
 #endif // GOwnPtr_h
+
index e7cf34bd4ee3bac87405a2f6ee9721d425d68661..1cd22c532b674d902ebd5c308c0bb4aeaef5020c 100644 (file)
@@ -19,6 +19,8 @@
 #include "config.h"
 #include "GRefPtr.h"
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include <glib.h>
 
 namespace WTF {
@@ -35,4 +37,50 @@ template <> void derefGPtr(GHashTable* ptr)
     g_hash_table_unref(ptr);
 }
 
+#if GLIB_CHECK_VERSION(2, 24, 0)
+template <> GVariant* refGPtr(GVariant* ptr)
+{
+    if (ptr)
+        g_variant_ref(ptr);
+    return ptr;
+}
+
+template <> void derefGPtr(GVariant* ptr)
+{
+    g_variant_unref(ptr);
+}
+
+#else
+
+// We do this so that we can avoid including the glib.h header in GRefPtr.h.
+typedef struct _GVariant {
+    bool fake;
+} GVariant; 
+
+template <> GVariant* refGPtr(GVariant* ptr)
+{
+    return ptr;
+}
+
+template <> void derefGPtr(GVariant* ptr)
+{
+}
+
+#endif
+
+template <> GSource* refGPtr(GSource* ptr)
+{
+    if (ptr)
+        g_source_ref(ptr);
+    return ptr;
+}
+
+template <> void derefGPtr(GSource* ptr)
+{
+    if (ptr)
+        g_source_unref(ptr);
+}
+
 } // namespace WTF
+
+#endif // ENABLE(GLIB_SUPPORT)
index 3a33605c29746675af5083902c062513bc44285b..10ebf0753dea9b9bd50c2779e7551f1a1a56c435 100644 (file)
 #ifndef WTF_GRefPtr_h
 #define WTF_GRefPtr_h
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include "AlwaysInline.h"
+#include "GRefPtr.h"
+#include "RefPtr.h"
 #include <algorithm>
 
-typedef struct _GHashTable GHashTable;
-typedef void* gpointer;
-extern "C" void g_object_unref(gpointer object);
-extern "C" gpointer  g_object_ref_sink(gpointer object);
+extern "C" void g_object_unref(gpointer);
+extern "C" gpointer g_object_ref_sink(gpointer);
 
 namespace WTF {
 
@@ -38,25 +40,57 @@ template <typename T> inline T* refGPtr(T*);
 template <typename T> inline void derefGPtr(T*);
 template <typename T> class GRefPtr;
 template <typename T> GRefPtr<T> adoptGRef(T*);
-template <> GHashTable* refGPtr(GHashTable* ptr);
-template <> void derefGPtr(GHashTable* ptr);
 
 template <typename T> class GRefPtr {
 public:
     GRefPtr() : m_ptr(0) { }
-    GRefPtr(T* ptr) : m_ptr(ptr) { if (ptr) refGPtr(ptr); }
-    GRefPtr(const GRefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) refGPtr(ptr); }
-    template <typename U> GRefPtr(const GRefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) refGPtr(ptr); }
 
-    ~GRefPtr() { if (T* ptr = m_ptr) derefGPtr(ptr); }
+    GRefPtr(T* ptr)
+        : m_ptr(ptr)
+    {
+        if (ptr)
+            refGPtr(ptr);
+    }
 
-    void clear()
+    GRefPtr(const GRefPtr& o)
+        : m_ptr(o.m_ptr)
+    {
+        if (T* ptr = m_ptr)
+            refGPtr(ptr);
+    }
+
+    template <typename U> GRefPtr(const GRefPtr<U>& o)
+        : m_ptr(o.get())
+    {
+        if (T* ptr = m_ptr)
+            refGPtr(ptr);
+    }
+
+    ~GRefPtr()
     {
         if (T* ptr = m_ptr)
             derefGPtr(ptr);
+    }
+
+    void clear()
+    {
+        T* ptr = m_ptr;
+        m_ptr = 0;
+        if (ptr)
+            derefGPtr(ptr);
+    }
+
+    T* leakRef() WARN_UNUSED_RETURN
+    {
+        T* ptr = m_ptr;
         m_ptr = 0;
+        return ptr;
     }
 
+    // Hash table deleted values, which are only constructed and never copied or destroyed.
+    GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
+    bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
+
     T* get() const { return m_ptr; }
     T& operator*() const { return *m_ptr; }
     ALWAYS_INLINE T* operator->() const { return m_ptr; }
@@ -165,6 +199,13 @@ template <typename T> GRefPtr<T> adoptGRef(T* p)
     return GRefPtr<T>(p, GRefPtrAdopt);
 }
 
+template <> GHashTable* refGPtr(GHashTable* ptr);
+template <> void derefGPtr(GHashTable* ptr);
+template <> GVariant* refGPtr(GVariant* ptr);
+template <> void derefGPtr(GVariant* ptr);
+template <> GSource* refGPtr(GSource* ptr);
+template <> void derefGPtr(GSource* ptr);
+
 template <typename T> inline T* refGPtr(T* ptr)
 {
     if (ptr)
@@ -181,10 +222,8 @@ template <typename T> inline void derefGPtr(T* ptr)
 } // namespace WTF
 
 using WTF::GRefPtr;
-using WTF::refGPtr;
-using WTF::derefGPtr;
 using WTF::adoptGRef;
-using WTF::static_pointer_cast;
-using WTF::const_pointer_cast;
+
+#endif // ENABLE(GLIB_SUPPORT)
 
 #endif // WTF_GRefPtr_h
diff --git a/wtf/gobject/GTypedefs.h b/wtf/gobject/GTypedefs.h
new file mode 100644 (file)
index 0000000..c7f7ac4
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 Igalia, S.L.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef GtkTypedefs_h
+#define GtkTypedefs_h
+
+/* Vanilla C code does not seem to be able to handle forward-declaration typedefs. */
+#ifdef  __cplusplus
+
+typedef char gchar;
+typedef double gdouble;
+typedef float gfloat;
+typedef int gint;
+typedef gint gboolean;
+typedef long glong;
+typedef short gshort;
+typedef unsigned char guchar;
+typedef unsigned int guint;
+typedef unsigned long gulong;
+typedef unsigned short gushort;
+typedef void* gpointer;
+
+typedef struct _GAsyncResult GAsyncResult;
+typedef struct _GCancellable GCancellable;
+typedef struct _GCharsetConverter GCharsetConverter;
+typedef struct _GCond GCond;
+typedef struct _GDir GDir;
+typedef struct _GdkAtom* GdkAtom;
+typedef struct _GdkCursor GdkCursor;
+typedef struct _GdkDragContext GdkDragContext;
+typedef struct _GdkEventConfigure GdkEventConfigure;
+typedef struct _GdkEventExpose GdkEventExpose;
+typedef struct _GdkPixbuf GdkPixbuf;
+typedef struct _GError GError;
+typedef struct _GFile GFile;
+typedef struct _GHashTable GHashTable;
+typedef struct _GInputStream GInputStream;
+typedef struct _GList GList;
+typedef struct _GMutex GMutex;
+typedef struct _GPatternSpec GPatternSpec;
+typedef struct _GPollableOutputStream GPollableOutputStream;
+typedef struct _GSocketClient GSocketClient;
+typedef struct _GSocketConnection GSocketConnection;
+typedef struct _GSource GSource;
+typedef struct _GVariant GVariant;
+typedef union _GdkEvent GdkEvent;
+
+#if USE(CAIRO)
+typedef struct _cairo_surface cairo_surface_t;
+#endif
+
+#if PLATFORM(GTK)
+typedef struct _GtkAction GtkAction;
+typedef struct _GtkAdjustment GtkAdjustment;
+typedef struct _GtkBorder GtkBorder;
+typedef struct _GtkClipboard GtkClipboard;
+typedef struct _GtkContainer GtkContainer;
+typedef struct _GtkIconInfo GtkIconInfo;
+typedef struct _GtkMenu GtkMenu;
+typedef struct _GtkMenuItem GtkMenuItem;
+typedef struct _GtkObject GtkObject;
+typedef struct _GtkSelectionData GtkSelectionData;
+typedef struct _GtkStyle GtkStyle;
+typedef struct _GtkTargetList GtkTargetList;
+typedef struct _GtkThemeParts GtkThemeParts;
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkWindow GtkWindow;
+
+#ifdef GTK_API_VERSION_2
+typedef struct _GdkRectangle GdkRectangle;
+typedef struct _GdkDrawable GdkWindow;
+#else
+typedef struct _GdkWindow GdkWindow;
+typedef struct _cairo_rectangle_int cairo_rectangle_int_t;
+typedef cairo_rectangle_int_t GdkRectangle;
+typedef struct _GtkStyleContext GtkStyleContext;
+#endif
+
+#endif
+
+#endif
+#endif /* GtkTypedefs_h */
index 0c5cf0c98e3cb6cc77c001777d10390072e59171..863ee81d7ca3c3028d5e85de410366d52de45b89 100644 (file)
 #include "HashMap.h"
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
+#include <wtf/StdLibExtras.h>
 
 #include <glib.h>
 #include <limits.h>
 
 namespace WTF {
 
+typedef HashMap<ThreadIdentifier, GThread*> ThreadMap;
+
 static Mutex* atomicallyInitializedStaticMutex;
 
 static Mutex& threadMapMutex()
 {
-    static Mutex mutex;
+    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
     return mutex;
 }
 
@@ -74,9 +77,9 @@ void unlockAtomicallyInitializedStaticMutex()
     atomicallyInitializedStaticMutex->unlock();
 }
 
-static HashMap<ThreadIdentifier, GThread*>& threadMap()
+static ThreadMap& threadMap()
 {
-    static HashMap<ThreadIdentifier, GThread*> map;
+    DEFINE_STATIC_LOCAL(ThreadMap, map, ());
     return map;
 }
 
@@ -84,7 +87,7 @@ static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
 {
     MutexLocker locker(threadMapMutex());
 
-    HashMap<ThreadIdentifier, GThread*>::iterator i = threadMap().begin();
+    ThreadMap::iterator i = threadMap().begin();
     for (; i != threadMap().end(); ++i) {
         if (i->second == thread)
             return i->first;
@@ -164,6 +167,11 @@ ThreadIdentifier currentThread()
     return establishIdentifierForThread(currentThread);
 }
 
+void yield()
+{
+    g_thread_yield();
+}
+
 Mutex::Mutex()
     : m_mutex(g_mutex_new())
 {
diff --git a/wtf/haiku/StringHaiku.cpp b/wtf/haiku/StringHaiku.cpp
new file mode 100644 (file)
index 0000000..fdf4e72
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
+ *
+ * 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 COMPUTER, 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 COMPUTER, 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.
+ */
+
+#include "config.h"
+#include "PlatformString.h"
+
+#include <String.h>
+#include <wtf/text/CString.h>
+
+namespace WTF {
+
+// String conversions
+String::String(const BString& string)
+{
+    if (string.Length())
+        m_impl = String::fromUTF8(string.String(), string.Length()).impl();
+    else
+        m_impl = StringImpl::empty();
+}
+
+String::operator BString() const
+{
+    BString string;
+    string.SetTo(utf8().data());
+
+    return string;
+}
+
+} // namespace WTF
index aabaafa19056d176befab19df275497666d710ce..d8b5a40e3d9f1ce16a12eeed769e62973b66f719 100644 (file)
@@ -59,16 +59,12 @@ static NSThread* mainThreadNSThread;
 
 void initializeMainThreadPlatform()
 {
-#if !defined(BUILDING_ON_TIGER)
     ASSERT(!staticMainThreadCaller);
     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
 
     mainThreadEstablishedAsPthreadMain = false;
     mainThreadPthread = pthread_self();
     mainThreadNSThread = [[NSThread currentThread] retain];
-#else
-    ASSERT_NOT_REACHED();
-#endif
 }
 
 void initializeMainThreadToProcessMainThreadPlatform()
@@ -117,12 +113,8 @@ void scheduleDispatchFunctionsOnMainThread()
         return;
     }
 
-#if !defined(BUILDING_ON_TIGER)
     ASSERT(mainThreadNSThread);
     [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
-#else
-    ASSERT_NOT_REACHED();
-#endif
 }
 
 bool isMainThread()
@@ -132,13 +124,8 @@ bool isMainThread()
         return pthread_main_np();
     }
 
-#if !defined(BUILDING_ON_TIGER)
     ASSERT(mainThreadPthread);
     return pthread_equal(pthread_self(), mainThreadPthread);
-#else
-    ASSERT_NOT_REACHED();
-    return false;
-#endif
 }
 
 // This function is the same as isMainThread() above except that it does not do
index b2c621ac3be48511a2b30a2e9d33da4ec2abdb29..16dd439e3bcf1b85a66bb1d509722545063668dc 100644 (file)
 
 #include "config.h"
 
+#include <wtf/StdLibExtras.h>
 #include <wtf/text/WTFString.h>
 
 #include <QString>
 
-namespace WebCore {
+namespace WTF {
 
 // String conversions
 String::String(const QString& qstr)
 {
     if (qstr.isNull())
         return;
-    m_impl = StringImpl::create(reinterpret_cast<const UChar*>(qstr.constData()), qstr.length());
+    m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(qstr.constData()), qstr.length());
 }
 
 String::String(const QStringRef& ref)
 {
     if (!ref.string())
         return;
-    m_impl = StringImpl::create(reinterpret_cast<const UChar*>(ref.unicode()), ref.length());
+    m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(ref.unicode()), ref.length());
 }
 
 String::operator QString() const
index 7f81646af55acdfcb6763d8b0364f769ee60f142..8041dea531a3a0995a551501948e75a27a2ee4be 100644 (file)
@@ -208,6 +208,11 @@ ThreadIdentifier currentThread()
     return establishIdentifierForThread(currentThread);
 }
 
+void yield()
+{
+    QThread::yieldCurrentThread();
+}
+
 Mutex::Mutex()
     : m_mutex(new QMutex())
 {
diff --git a/wtf/symbian/BlockAllocatorSymbian.cpp b/wtf/symbian/BlockAllocatorSymbian.cpp
deleted file mode 100644 (file)
index 6a28e9e..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
- *
- * 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. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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.
- */
-
-#include "config.h"
-
-#if OS(SYMBIAN)
-
-#include "BlockAllocatorSymbian.h"
-
-
-namespace WTF {
-
-/** Efficiently allocates blocks of size blockSize with blockSize alignment. 
- * Primarly designed for JSC Collector's needs. 
- * Not thread-safe.    
- */
-AlignedBlockAllocator::AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize )
-    : m_reservation(reservationSize), 
-      m_blockSize(blockSize)
-{
-
-     // Get system's page size value.
-     SYMBIAN_PAGESIZE(m_pageSize); 
-     
-     // We only accept multiples of system page size for both initial reservation and the alignment/block size
-     m_reservation = SYMBIAN_ROUNDUPTOMULTIPLE(m_reservation, m_pageSize);
-     __ASSERT_ALWAYS(SYMBIAN_ROUNDUPTOMULTIPLE(m_blockSize, m_pageSize), User::Panic(_L("AlignedBlockAllocator1"), KErrArgument));
-     
-     // Calculate max. bit flags we need to carve a reservationSize range into blockSize-sized blocks
-     m_map.numBits = m_reservation / m_blockSize;   
-     const TUint32 bitsPerWord = 8*sizeof(TUint32); 
-     const TUint32 numWords = (m_map.numBits + bitsPerWord -1) / bitsPerWord; 
-   
-     m_map.bits = new TUint32[numWords];
-     __ASSERT_ALWAYS(m_map.bits, User::Panic(_L("AlignedBlockAllocator2"), KErrNoMemory));
-     m_map.clearAll();
-     
-     // Open a Symbian RChunk, and reserve requested virtual address range   
-     // Any thread in this process can operate this rchunk due to EOwnerProcess access rights. 
-     TInt ret = m_chunk.CreateDisconnectedLocal(0 , 0, (TInt)m_reservation , EOwnerProcess);  
-     if (ret != KErrNone) 
-         User::Panic(_L("AlignedBlockAllocator3"), ret);
-       
-     // This is the offset to m_chunk.Base() required to make it m_blockSize-aligned
-     m_offset = SYMBIAN_ROUNDUPTOMULTIPLE(TUint32(m_chunk.Base()), m_blockSize) - TUint(m_chunk.Base()); 
-
-}
-
-void* AlignedBlockAllocator::alloc()
-{
-
-    TInt  freeRam = 0; 
-    void* address = 0;
-    
-    // Look up first free slot in bit map
-    const TInt freeIdx = m_map.findFree();
-        
-    // Pseudo OOM: We ate up the address space we reserved..
-    // ..even though the device may have free RAM left
-    if (freeIdx < 0)
-        return 0;
-        
-    TInt ret = m_chunk.Commit(m_offset + (m_blockSize * freeIdx), m_blockSize);
-    if (ret != KErrNone)  
-        return 0; // True OOM: Device didn't have physical RAM to spare
-        
-    // Updated bit to mark region as in use. 
-    m_map.set(freeIdx); 
-    
-    // Calculate address of committed region (block)
-    address = (void*)( (m_chunk.Base() + m_offset) + (TUint)(m_blockSize * freeIdx) );
-    
-    return address;
-}
-
-void AlignedBlockAllocator::free(void* block)
-{
-    // Calculate index of block to be freed
-    TInt idx = TUint(static_cast<TUint8*>(block) - m_chunk.Base() - m_offset) / m_blockSize;
-    
-    __ASSERT_DEBUG(idx >= 0 && idx < m_map.numBits, User::Panic(_L("AlignedBlockAllocator4"), KErrCorrupt)); // valid index check
-    __ASSERT_DEBUG(m_map.get(idx), User::Panic(_L("AlignedBlockAllocator5"), KErrCorrupt)); // in-use flag check    
-    
-    // Return committed region to system RAM pool (the physical RAM becomes usable by others)
-    TInt ret = m_chunk.Decommit(m_offset + m_blockSize * idx, m_blockSize);
-            
-    // mark this available again
-    m_map.clear(idx); 
-}
-
-void AlignedBlockAllocator::destroy() 
-{
-    // release everything!
-    m_chunk.Decommit(0, m_chunk.MaxSize());
-    m_map.clearAll();
-}
-
-AlignedBlockAllocator::~AlignedBlockAllocator()
-{
-    destroy();
-    m_chunk.Close();
-    delete [] m_map.bits;
-}
-
-} // end of namespace
-
-#endif // SYMBIAN
diff --git a/wtf/symbian/BlockAllocatorSymbian.h b/wtf/symbian/BlockAllocatorSymbian.h
deleted file mode 100644 (file)
index 21422f6..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
- *
- * 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. 
- * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission. 
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 BlockAllocatorSymbian_h
-#define BlockAllocatorSymbian_h
-
-#include <e32cmn.h>
-#include <e32std.h>
-#include <hal.h>
-
-
-#define SYMBIAN_PAGESIZE(x) (HAL::Get(HALData::EMemoryPageSize, x));
-#define SYMBIAN_FREERAM(x)  (HAL::Get(HALData::EMemoryRAMFree, x));
-#define SYMBIAN_ROUNDUPTOMULTIPLE(x, multipleof)    ( (x + multipleof - 1) & ~(multipleof - 1) )
-
-// Set sane defaults if -D<flagname=value> wasn't provided via compiler args
-#ifndef JSCCOLLECTOR_VIRTUALMEM_RESERVATION
-#if defined(__WINS__) 
-    // Emulator has limited virtual address space
-    #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (4*1024*1024)
-#else
-    // HW has plenty of virtual addresses
-    #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (128*1024*1024)
-#endif
-#endif
-
-namespace WTF {
-
-/** 
- *  Allocates contiguous region of size blockSize with blockSize-aligned address. 
- *  blockSize must be a multiple of system page size (typically 4K on Symbian/ARM)
- *
- *  @param reservationSize Virtual address range to be reserved upon creation of chunk (bytes).
- *  @param blockSize Size of a single allocation. Returned address will also be blockSize-aligned.
- */
-class AlignedBlockAllocator {
-    public:
-        AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize);
-        ~AlignedBlockAllocator();
-        void destroy();
-        void* alloc();
-        void free(void* data);
-    
-    private: 
-        RChunk   m_chunk; // Symbian chunk that lets us reserve/commit/decommit
-        TUint    m_offset; // offset of first committed region from base 
-        TInt     m_pageSize; // cached value of system page size, typically 4K on Symbian
-        TUint32  m_reservation;
-        TUint32  m_blockSize;  
-
-        // Tracks comitted/decommitted state of a blockSize region
-        struct {
-            
-            TUint32 *bits; // array of bit flags 
-            TUint32  numBits; // number of regions to keep track of
-            
-            bool get(TUint32 n) const
-            {
-                return !!(bits[n >> 5] & (1 << (n & 0x1F)));
-            }
-            
-            void set(TUint32 n)
-            {
-                bits[n >> 5] |= (1 << (n & 0x1F));
-            }
-            
-            void clear(TUint32 n)
-            {
-                bits[n >> 5] &= ~(1 << (n & 0x1F));
-            }
-            
-            void clearAll()
-            {
-               for (TUint32 i = 0; i < numBits; i++)
-                    clear(i);
-            }
-            
-            TInt findFree() const
-            {
-                for (TUint32 i = 0; i < numBits; i++) {
-                    if (!get(i)) 
-                        return i;
-                }
-                return -1;
-            }
-            
-        } m_map;  
-
-};
-}
-
-#endif // end of BlockAllocatorSymbian_h
-
-
index 946a6fb00e4516d37a110f29f051527f151ee766..06879770c0bcf0ed0b3b22fd1b4771dac84cf5b0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 
 #include "config.h"
 
-#include <libkern/OSAtomic.h>
-
 #include "AtomicString.h"
 
 #include "StringHash.h"
 #include <wtf/HashSet.h>
 #include <wtf/Threading.h>
 #include <wtf/WTFThreadData.h>
+#include <wtf/unicode/UTF8.h>
+
+#include <libkern/OSAtomic.h>
 
-namespace WebCore {
+namespace WTF {
+
+using namespace Unicode;
 
 COMPILE_ASSERT(sizeof(AtomicString) == sizeof(String), atomic_string_and_string_must_be_same_size);
 
@@ -87,10 +91,20 @@ static inline HashSet<StringImpl*>& stringTable()
     return table->table();
 }
 
+template<typename T, typename HashTranslator>
+static inline PassRefPtr<StringImpl> addToStringTable(const T& value)
+{
+    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<T, HashTranslator>(value);
+
+    // If the string is newly-translated, then we need to adopt it.
+    // The boolean in the pair tells us if that is so.
+    return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+}
+
 struct CStringTranslator {
     static unsigned hash(const char* c)
     {
-        return StringImpl::computeHash(c);
+        return StringHasher::computeHash(c);
     }
 
     static bool equal(StringImpl* r, const char* s)
@@ -102,12 +116,12 @@ struct CStringTranslator {
             if (d[i] != c)
                 return false;
         }
-        return s[length] == 0;
+        return !s[length];
     }
 
     static void translate(StringImpl*& location, const char* const& c, unsigned hash)
     {
-        location = StringImpl::create(c).releaseRef(); 
+        location = StringImpl::create(c).leakRef();
         location->setHash(hash);
         location->setIsAtomic(true);
     }
@@ -128,12 +142,10 @@ PassRefPtr<StringImpl> AtomicString::add(const char* c)
     if (!c)
         return 0;
     if (!*c)
-        return StringImpl::empty();    
+        return StringImpl::empty();
+
     AtomicStringTableLocker locker;
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c);
-    if (!addResult.second)
-        return *addResult.first;
-    return adoptRef(*addResult.first);
+    return addToStringTable<const char*, CStringTranslator>(c);
 }
 
 struct UCharBuffer {
@@ -148,7 +160,7 @@ static inline bool equal(StringImpl* string, const UChar* characters, unsigned l
 
     // FIXME: perhaps we should have a more abstract macro that indicates when
     // going 4 bytes at a time is unsafe
-#if CPU(ARM) || CPU(SH4)
+#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC)
     const UChar* stringCharacters = string->characters();
     for (unsigned i = 0; i != length; ++i) {
         if (*stringCharacters++ != *characters++)
@@ -174,20 +186,25 @@ static inline bool equal(StringImpl* string, const UChar* characters, unsigned l
 #endif
 }
 
+bool operator==(const AtomicString& string, const Vector<UChar>& vector)
+{
+    return string.impl() && equal(string.impl(), vector.data(), vector.size());
+}
+
 struct UCharBufferTranslator {
     static unsigned hash(const UCharBuffer& buf)
     {
-        return StringImpl::computeHash(buf.s, buf.length);
+        return StringHasher::computeHash(buf.s, buf.length);
     }
 
     static bool equal(StringImpl* const& str, const UCharBuffer& buf)
     {
-        return WebCore::equal(str, buf.s, buf.length);
+        return WTF::equal(str, buf.s, buf.length);
     }
 
     static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash)
     {
-        location = StringImpl::create(buf.s, buf.length).releaseRef(); 
+        location = StringImpl::create(buf.s, buf.length).leakRef();
         location->setHash(hash);
         location->setIsAtomic(true);
     }
@@ -202,18 +219,65 @@ struct HashAndCharacters {
 struct HashAndCharactersTranslator {
     static unsigned hash(const HashAndCharacters& buffer)
     {
-        ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length));
+        ASSERT(buffer.hash == StringHasher::computeHash(buffer.characters, buffer.length));
         return buffer.hash;
     }
 
     static bool equal(StringImpl* const& string, const HashAndCharacters& buffer)
     {
-        return WebCore::equal(string, buffer.characters, buffer.length);
+        return WTF::equal(string, buffer.characters, buffer.length);
     }
 
     static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash)
     {
-        location = StringImpl::create(buffer.characters, buffer.length).releaseRef();
+        location = StringImpl::create(buffer.characters, buffer.length).leakRef();
+        location->setHash(hash);
+        location->setIsAtomic(true);
+    }
+};
+
+struct HashAndUTF8Characters {
+    unsigned hash;
+    const char* characters;
+    unsigned length;
+    unsigned utf16Length;
+};
+
+struct HashAndUTF8CharactersTranslator {
+    static unsigned hash(const HashAndUTF8Characters& buffer)
+    {
+        return buffer.hash;
+    }
+
+    static bool equal(StringImpl* const& string, const HashAndUTF8Characters& buffer)
+    {
+        if (buffer.utf16Length != string->length())
+            return false;
+
+        const UChar* stringCharacters = string->characters();
+
+        // If buffer contains only ASCII characters UTF-8 and UTF16 length are the same.
+        if (buffer.utf16Length != buffer.length)
+            return equalUTF16WithUTF8(stringCharacters, stringCharacters + string->length(), buffer.characters, buffer.characters + buffer.length);
+
+        for (unsigned i = 0; i < buffer.length; ++i) {
+            ASSERT(isASCII(buffer.characters[i]));
+            if (stringCharacters[i] != buffer.characters[i])
+                return false;
+        }
+
+        return true;
+    }
+
+    static void translate(StringImpl*& location, const HashAndUTF8Characters& buffer, unsigned hash)
+    {
+        UChar* target;
+        location = StringImpl::createUninitialized(buffer.utf16Length, target).releaseRef();
+
+        const char* source = buffer.characters;
+        if (convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length) != conversionOK)
+            ASSERT_NOT_REACHED();
+
         location->setHash(hash);
         location->setIsAtomic(true);
     }
@@ -224,16 +288,12 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
     if (!s)
         return 0;
 
-    if (length == 0)
+    if (!length)
         return StringImpl::empty();
     
-    UCharBuffer buf = { s, length }; 
+    UCharBuffer buffer = { s, length };
     AtomicStringTableLocker locker;
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf);
-
-    // If the string is newly-translated, then we need to adopt it.
-    // The boolean in the pair tells us if that is so.
-    return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+    return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
 }
 
 PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsigned existingHash)
@@ -241,15 +301,12 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsign
     ASSERT(s);
     ASSERT(existingHash);
 
-    if (length == 0)
+    if (!length)
         return StringImpl::empty();
-    
-    HashAndCharacters buffer = { existingHash, s, length }; 
+
+    HashAndCharacters buffer = { existingHash, s, length };
     AtomicStringTableLocker locker;
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer);
-    if (!addResult.second)
-        return *addResult.first;
-    return adoptRef(*addResult.first);
+    return addToStringTable<HashAndCharacters, HashAndCharactersTranslator>(buffer);
 }
 
 PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
@@ -261,16 +318,12 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
     while (s[length] != UChar(0))
         length++;
 
-    if (length == 0)
+    if (!length)
         return StringImpl::empty();
 
-    UCharBuffer buf = {s, length}; 
+    UCharBuffer buffer = { s, length };
     AtomicStringTableLocker locker;
-    pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf);
-
-    // If the string is newly-translated, then we need to adopt it.
-    // The boolean in the pair tells us if that is so.
-    return addResult.second ? adoptRef(*addResult.first) : *addResult.first;
+    return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer);
 }
 
 PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
@@ -278,7 +331,7 @@ PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
     if (!r || r->isAtomic())
         return r;
 
-    if (r->length() == 0)
+    if (!r->length())
         return StringImpl::empty();
 
     AtomicStringTableLocker locker;
@@ -293,7 +346,7 @@ AtomicStringImpl* AtomicString::find(const UChar* s, unsigned length, unsigned e
     ASSERT(s);
     ASSERT(existingHash);
 
-    if (length == 0)
+    if (!length)
         return static_cast<AtomicStringImpl*>(StringImpl::empty());
 
     HashAndCharacters buffer = { existingHash, s, length }; 
@@ -309,15 +362,32 @@ void AtomicString::remove(StringImpl* r)
     AtomicStringTableLocker locker;
     stringTable().remove(r);
 }
-    
+
 AtomicString AtomicString::lower() const
 {
     // Note: This is a hot function in the Dromaeo benchmark.
     StringImpl* impl = this->impl();
+    if (UNLIKELY(!impl))
+        return *this;
     RefPtr<StringImpl> newImpl = impl->lower();
     if (LIKELY(newImpl == impl))
         return *this;
     return AtomicString(newImpl);
 }
 
+AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd)
+{
+    HashAndUTF8Characters buffer;
+    buffer.characters = charactersStart;
+    buffer.hash = calculateStringHashAndLengthFromUTF8(charactersStart, charactersEnd, buffer.length, buffer.utf16Length);
+
+    if (!buffer.hash)
+        return nullAtom;
+
+    AtomicString atomicString;
+    AtomicStringTableLocker locker;
+    atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(buffer);
+    return atomicString;
 }
+
+} // namespace WTF
index 5bb2cf9c9ae7ccb0c607e4064d47d699faa2b131..45d332f544f630e83f4e41fc9ecfcaf841a45b79 100644 (file)
@@ -32,9 +32,7 @@
 #define ATOMICSTRING_CONVERSION
 #endif
 
-// FIXME: This is a temporary layering violation while we move string code to WTF.
-// Landing the file moves in one patch, will follow on with patches to change the namespaces.
-namespace WebCore {
+namespace WTF {
 
 struct AtomicStringHash;
 
@@ -73,10 +71,10 @@ public:
     bool contains(const String& s, bool caseSensitive = true) const
         { return m_string.contains(s, caseSensitive); }
 
-    int find(UChar c, int start = 0) const { return m_string.find(c, start); }
-    int find(const char* s, int start = 0, bool caseSentitive = true) const
+    size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); }
+    size_t find(const char* s, size_t start = 0, bool caseSentitive = true) const
         { return m_string.find(s, start, caseSentitive); }
-    int find(const String& s, int start = 0, bool caseSentitive = true) const
+    size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const
         { return m_string.find(s, start, caseSentitive); }
     
     bool startsWith(const String& s, bool caseSensitive = true) const
@@ -97,7 +95,7 @@ public:
 
     static void remove(StringImpl*);
     
-#if PLATFORM(CF)
+#if USE(CF)
     AtomicString(CFStringRef s) :  m_string(add(String(s).impl())) { }
     CFStringRef createCFString() const { return m_string.createCFString(); }
 #endif    
@@ -110,6 +108,11 @@ public:
     operator QString() const { return m_string; }
 #endif
 
+    // AtomicString::fromUTF8 will return a null string if
+    // the input data contains invalid UTF-8 sequences.
+    static AtomicString fromUTF8(const char*, size_t);
+    static AtomicString fromUTF8(const char*);
+
 private:
     String m_string;
     
@@ -124,19 +127,24 @@ private:
         return addSlowCase(r);
     }
     static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
+    static AtomicString fromUTF8Internal(const char*, const char*);
 };
 
 inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); }
 bool operator==(const AtomicString& a, const char* b);
+bool operator==(const AtomicString& a, const Vector<UChar>& b);
 inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); }
 inline bool operator==(const char* a, const AtomicString& b) { return b == a; }
 inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); }
+inline bool operator==(const Vector<UChar>& a, const AtomicString& b) { return b == a; }
 
 inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); }
 inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); }
 inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); }
+inline bool operator!=(const AtomicString& a, const Vector<UChar>& b) { return !(a == b); }
 inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); }
 inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); }
+inline bool operator!=(const Vector<UChar>& a, const AtomicString& b) { return !(a == b); }
 
 inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
 inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); }
@@ -147,26 +155,51 @@ inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return e
 // Define external global variables for the commonly used atomic strings.
 // These are only usable from the main thread.
 #ifndef ATOMICSTRING_HIDE_GLOBALS
-    extern const JS_EXPORTDATA AtomicString nullAtom;
-    extern const JS_EXPORTDATA AtomicString emptyAtom;
-    extern const JS_EXPORTDATA AtomicString textAtom;
-    extern const JS_EXPORTDATA AtomicString commentAtom;
-    extern const JS_EXPORTDATA AtomicString starAtom;
-    extern const JS_EXPORTDATA AtomicString xmlAtom;
-    extern const JS_EXPORTDATA AtomicString xmlnsAtom;
+extern const JS_EXPORTDATA AtomicString nullAtom;
+extern const JS_EXPORTDATA AtomicString emptyAtom;
+extern const JS_EXPORTDATA AtomicString textAtom;
+extern const JS_EXPORTDATA AtomicString commentAtom;
+extern const JS_EXPORTDATA AtomicString starAtom;
+extern const JS_EXPORTDATA AtomicString xmlAtom;
+extern const JS_EXPORTDATA AtomicString xmlnsAtom;
+
+inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length)
+{
+    if (!characters)
+        return nullAtom;
+    if (!length)
+        return emptyAtom;
+    return fromUTF8Internal(characters, characters + length);
+}
+
+inline AtomicString AtomicString::fromUTF8(const char* characters)
+{
+    if (!characters)
+        return nullAtom;
+    if (!*characters)
+        return emptyAtom;
+    return fromUTF8Internal(characters, 0);
+}
 #endif
 
-} // namespace WebCore
-
-
-namespace WTF {
-
-    // AtomicStringHash is the default hash for AtomicString
-    template<typename T> struct DefaultHash;
-    template<> struct DefaultHash<WebCore::AtomicString> {
-        typedef WebCore::AtomicStringHash Hash;
-    };
+// AtomicStringHash is the default hash for AtomicString
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<AtomicString> {
+    typedef AtomicStringHash Hash;
+};
 
 } // namespace WTF
 
+#ifndef ATOMICSTRING_HIDE_GLOBALS
+using WTF::AtomicString;
+using WTF::nullAtom;
+using WTF::emptyAtom;
+using WTF::textAtom;
+using WTF::commentAtom;
+using WTF::starAtom;
+using WTF::xmlAtom;
+using WTF::xmlnsAtom;
+#endif
+
+#include "StringConcatenate.h"
 #endif // AtomicString_h
diff --git a/wtf/text/AtomicStringHash.h b/wtf/text/AtomicStringHash.h
new file mode 100644 (file)
index 0000000..f6e4ad1
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 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. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 AtomicStringHash_h
+#define AtomicStringHash_h
+
+#include <wtf/text/AtomicString.h>
+#include <wtf/HashTraits.h>
+
+namespace WTF {
+
+    struct AtomicStringHash {
+        static unsigned hash(const AtomicString& key)
+        {
+            return key.impl()->existingHash();
+        }
+
+        static bool equal(const AtomicString& a, const AtomicString& b)
+        {
+            return a == b;
+        }
+
+        static const bool safeToCompareToEmptyOrDeleted = false;
+    };
+
+    // AtomicStringHash is the default hash for AtomicString
+    template<> struct HashTraits<WTF::AtomicString> : GenericHashTraits<WTF::AtomicString> {
+        static const bool emptyValueIsZero = true;
+        static void constructDeletedValue(WTF::AtomicString& slot) { new (&slot) WTF::AtomicString(HashTableDeletedValue); }
+        static bool isDeletedValue(const WTF::AtomicString& slot) { return slot.isHashTableDeletedValue(); }
+    };
+
+}
+
+using WTF::AtomicStringHash;
+
+#endif
index 4b813f8cb46fa87d69ed9bb0d2248f6575707879..3f0c376064453ca91996c653a42ac96953f5ea43 100644 (file)
@@ -23,9 +23,7 @@
 
 #include "StringImpl.h"
 
-// FIXME: This is a temporary layering violation while we move string code to WTF.
-// Landing the file moves in one patch, will follow on with patches to change the namespaces.
-namespace WebCore {
+namespace WTF {
 
 class AtomicStringImpl : public StringImpl
 {
@@ -35,4 +33,6 @@ public:
 
 }
 
+using WTF::AtomicStringImpl;
+
 #endif
index 3ce3053eaed67c58f1c4a33d332e4d6c0ff62358..981d77a1db2e456faad927efe29a0641015fad37 100644 (file)
@@ -33,21 +33,27 @@ namespace WTF {
 
 CString::CString(const char* str)
 {
+    if (!str)
+        return;
+
     init(str, strlen(str));
 }
 
-CString::CString(const char* str, unsigned length)
+CString::CString(const char* str, size_t length)
 {
     init(str, length);
 }
 
-void CString::init(const char* str, unsigned length)
+void CString::init(const char* str, size_t length)
 {
     if (!str)
         return;
 
-    if (length >= numeric_limits<size_t>::max())
-        CRASH();
+    // We need to be sure we can add 1 to length without overflowing.
+    // Since the passed-in length is the length of an actual existing
+    // string, and we know the string doesn't occupy the entire address
+    // space, we can assert here and there's no need for a runtime check.
+    ASSERT(length < numeric_limits<size_t>::max());
 
     m_buffer = CStringBuffer::create(length + 1);
     memcpy(m_buffer->mutableData(), str, length); 
index d8250c5790c200d76dd523a8ece058c79f292900..343a7a52520741e2adcdbd810e3e9995a380d464 100644 (file)
@@ -40,8 +40,8 @@ public:
 private:
     friend class CString;
 
-    static PassRefPtr<CStringBuffer> create(unsigned length) { return adoptRef(new CStringBuffer(length)); }
-    CStringBuffer(unsigned length) : m_vector(length) { }
+    static PassRefPtr<CStringBuffer> create(size_t length) { return adoptRef(new CStringBuffer(length)); }
+    CStringBuffer(size_t length) : m_vector(length) { }
     char* mutableData() { return m_vector.data(); }
 
     Vector<char> m_vector;
@@ -53,7 +53,7 @@ class CString {
 public:
     CString() { }
     CString(const char*);
-    CString(const char*, unsigned length);
+    CString(const char*, size_t length);
     CString(CStringBuffer* buffer) : m_buffer(buffer) { }
     static CString newUninitialized(size_t length, char*& characterBuffer);
 
@@ -62,7 +62,7 @@ public:
         return m_buffer ? m_buffer->data() : 0;
     }
     char* mutableData();
-    unsigned length() const
+    size_t length() const
     {
         return m_buffer ? m_buffer->length() - 1 : 0;
     }
@@ -73,7 +73,7 @@ public:
 
 private:
     void copyBufferIfNeeded();
-    void init(const char*, unsigned length);
+    void init(const char*, size_t length);
     RefPtr<CStringBuffer> m_buffer;
 };
 
index cf732e31732d74de4eaae49b4d4269ba09677e06..e73d38e56d097c9edc036371d4d43ae283d5c3ee 100644 (file)
 #define StringBuffer_h
 
 #include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/unicode/Unicode.h>
 #include <limits>
 
-namespace WebCore {
+namespace WTF {
 
-class StringBuffer : public Noncopyable {
+class StringBuffer {
+    WTF_MAKE_NONCOPYABLE(StringBuffer);
 public:
     explicit StringBuffer(unsigned length)
         : m_length(length)
@@ -81,4 +81,6 @@ private:
 
 } // namespace WTF
 
+using WTF::StringBuffer;
+
 #endif // StringBuffer_h
diff --git a/wtf/text/StringBuilder.cpp b/wtf/text/StringBuilder.cpp
new file mode 100644 (file)
index 0000000..dfc9ff3
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2010 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. 
+ */
+
+#include "config.h"
+#include "StringBuilder.h"
+
+#include "WTFString.h"
+
+namespace WTF {
+
+void StringBuilder::reifyString()
+{
+    // Check if the string already exists.
+    if (!m_string.isNull()) {
+        ASSERT(m_string.length() == m_length);
+        return;
+    }
+
+    // Check for empty.
+    if (!m_length) {
+        m_string = StringImpl::empty();
+        return;
+    }
+
+    // Must be valid in the buffer, take a substring (unless string fills the buffer).
+    ASSERT(m_buffer && m_length <= m_buffer->length());
+    m_string = (m_length == m_buffer->length())
+        ? m_buffer.get()
+        : StringImpl::create(m_buffer, 0, m_length);
+}
+
+void StringBuilder::resize(unsigned newSize)
+{
+    // Check newSize < m_length, hence m_length > 0.
+    ASSERT(newSize <= m_length);
+    if (newSize == m_length)
+        return;
+    ASSERT(m_length);
+
+    // If there is a buffer, we only need to duplicate it if it has more than one ref.
+    if (m_buffer) {
+        if (!m_buffer->hasOneRef())
+            allocateBuffer(m_buffer->characters(), m_buffer->length());
+        m_length = newSize;
+        m_string = String();
+        return;
+    }
+
+    // Since m_length && !m_buffer, the string must be valid in m_string, and m_string.length() > 0.
+    ASSERT(!m_string.isEmpty());
+    ASSERT(m_length == m_string.length());
+    ASSERT(newSize < m_string.length());
+    m_length = newSize;
+    m_string = StringImpl::create(m_string.impl(), 0, newSize);
+}
+
+void StringBuilder::reserveCapacity(unsigned newCapacity)
+{
+    if (m_buffer) {
+        // If there is already a buffer, then grow if necessary.
+        if (newCapacity > m_buffer->length())
+            allocateBuffer(m_buffer->characters(), newCapacity);
+    } else {
+        // Grow the string, if necessary.
+        if (newCapacity > m_length)
+            allocateBuffer(m_string.characters(), newCapacity);
+    }
+}
+
+// Allocate a new buffer, copying in currentCharacters (these may come from either m_string
+// or m_buffer,  neither will be reassigned until the copy has completed).
+void StringBuilder::allocateBuffer(const UChar* currentCharacters, unsigned requiredLength)
+{
+    // Copy the existing data into a new buffer, set result to point to the end of the existing data.
+    RefPtr<StringImpl> buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters);
+    memcpy(m_bufferCharacters, currentCharacters, static_cast<size_t>(m_length) * sizeof(UChar)); // This can't overflow.
+
+    // Update the builder state.
+    m_buffer = buffer.release();
+    m_string = String();
+}
+
+// Make 'length' additional capacity be available in m_buffer, update m_string & m_length,
+// return a pointer to the newly allocated storage.
+UChar* StringBuilder::appendUninitialized(unsigned length)
+{
+    ASSERT(length);
+
+    // Calcuate the new size of the builder after appending.
+    unsigned requiredLength = length + m_length;
+    if (requiredLength < length)
+        CRASH();
+
+    if (m_buffer) {
+        // If the buffer is valid it must be at least as long as the current builder contents!
+        ASSERT(m_buffer->length() >= m_length);
+
+        // Check if the buffer already has sufficient capacity.
+        if (requiredLength <= m_buffer->length()) {
+            unsigned currentLength = m_length;
+            m_string = String();
+            m_length = requiredLength;
+            return m_bufferCharacters + currentLength;
+        }
+
+        // We need to realloc the buffer.
+        allocateBuffer(m_buffer->characters(), std::max(requiredLength, m_buffer->length() * 2));
+    } else {
+        ASSERT(m_string.length() == m_length);
+        allocateBuffer(m_string.characters(), std::max(requiredLength, requiredLength * 2));
+    }
+
+    UChar* result = m_bufferCharacters + m_length;
+    m_length = requiredLength;
+    return result;
+}
+
+void StringBuilder::append(const UChar* characters, unsigned length)
+{
+    if (!length)
+        return;
+    ASSERT(characters);
+
+    memcpy(appendUninitialized(length), characters, static_cast<size_t>(length) * 2);
+}
+
+void StringBuilder::append(const char* characters, unsigned length)
+{
+    if (!length)
+        return;
+    ASSERT(characters);
+
+    UChar* dest = appendUninitialized(length);
+    const char* end = characters + length;
+    while (characters < end)
+        *(dest++) = *(const unsigned char*)(characters++);
+}
+
+void StringBuilder::shrinkToFit()
+{
+    // If the buffer is at least 80% full, don't bother copying. Need to tune this heuristic!
+    if (m_buffer && m_buffer->length() > (m_length + (m_length >> 2))) {
+        UChar* result;
+        m_string = StringImpl::createUninitialized(m_length, result);
+        memcpy(result, m_buffer->characters(), static_cast<size_t>(m_length) * 2); // This can't overflow.
+        m_buffer = 0;
+    }
+}
+
+} // namespace WTF
diff --git a/wtf/text/StringBuilder.h b/wtf/text/StringBuilder.h
new file mode 100644 (file)
index 0000000..f10af64
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009, 2010 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 StringBuilder_h
+#define StringBuilder_h
+
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+class StringBuilder {
+public:
+    StringBuilder()
+        : m_length(0)
+    {
+    }
+
+    void append(const UChar*, unsigned);
+    void append(const char*, unsigned);
+
+    void append(const String& string)
+    {
+        // If we're appending to an empty string, and there is not buffer
+        // (in case reserveCapacity has been called) then just retain the
+        // string.
+        if (!m_length && !m_buffer) {
+            m_string = string;
+            m_length = string.length();
+            return;
+        }
+        append(string.characters(), string.length());
+    }
+
+    void append(const char* characters)
+    {
+        if (characters)
+            append(characters, strlen(characters));
+    }
+
+    void append(UChar c)
+    {
+        if (m_buffer && m_length < m_buffer->length() && m_string.isNull())
+            m_bufferCharacters[m_length++] = c;
+        else
+            append(&c, 1);
+    }
+
+    void append(char c)
+    {
+        if (m_buffer && m_length < m_buffer->length() && m_string.isNull())
+            m_bufferCharacters[m_length++] = (unsigned char)c;
+        else
+            append(&c, 1);
+    }
+
+    String toString()
+    {
+        if (m_string.isNull()) {
+            shrinkToFit();
+            reifyString();
+        }
+        return m_string;
+    }
+
+    String toStringPreserveCapacity()
+    {
+        if (m_string.isNull())
+            reifyString();
+        return m_string;
+    }
+
+    unsigned length() const
+    {
+        return m_length;
+    }
+
+    bool isEmpty() const { return !length(); }
+
+    void reserveCapacity(unsigned newCapacity);
+
+    void resize(unsigned newSize);
+
+    void shrinkToFit();
+
+    UChar operator[](unsigned i) const
+    {
+        ASSERT(i < m_length);
+        if (!m_string.isNull())
+            return m_string[i];
+        ASSERT(m_buffer);
+        return m_buffer->characters()[i];
+    }
+
+    void clear()
+    {
+        m_length = 0;
+        m_string = String();
+        m_buffer = 0;
+    }
+
+private:
+    void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength);
+    UChar* appendUninitialized(unsigned length);
+    void reifyString();
+
+    unsigned m_length;
+    String m_string;
+    RefPtr<StringImpl> m_buffer;
+    UChar* m_bufferCharacters;
+};
+
+} // namespace WTF
+
+using WTF::StringBuilder;
+
+#endif // StringBuilder_h
diff --git a/wtf/text/StringConcatenate.h b/wtf/text/StringConcatenate.h
new file mode 100644 (file)
index 0000000..e8c6331
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2010 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 StringConcatenate_h
+#define StringConcatenate_h
+
+#ifndef WTFString_h
+#include "AtomicString.h"
+#endif
+
+namespace WTF {
+
+template<typename StringType>
+class StringTypeAdapter {
+};
+
+template<>
+class StringTypeAdapter<char> {
+public:
+    StringTypeAdapter<char>(char buffer)
+        : m_buffer(buffer)
+    {
+    }
+
+    unsigned length() { return 1; }
+    void writeTo(UChar* destination) { *destination = m_buffer; }
+
+private:
+    unsigned char m_buffer;
+};
+
+template<>
+class StringTypeAdapter<UChar> {
+public:
+    StringTypeAdapter<UChar>(UChar buffer)
+        : m_buffer(buffer)
+    {
+    }
+
+    unsigned length() { return 1; }
+    void writeTo(UChar* destination) { *destination = m_buffer; }
+
+private:
+    UChar m_buffer;
+};
+
+template<>
+class StringTypeAdapter<char*> {
+public:
+    StringTypeAdapter<char*>(char* buffer)
+        : m_buffer(buffer)
+        , m_length(strlen(buffer))
+    {
+    }
+
+    unsigned length() { return m_length; }
+
+    void writeTo(UChar* destination)
+    {
+        for (unsigned i = 0; i < m_length; ++i) {
+            unsigned char c = m_buffer[i];
+            destination[i] = c;
+        }
+    }
+
+private:
+    const char* m_buffer;
+    unsigned m_length;
+};
+
+template<>
+class StringTypeAdapter<const UChar*> {
+public:
+    StringTypeAdapter<const UChar*>(const UChar* buffer)
+        : m_buffer(buffer)
+    {
+        size_t len = 0;
+        while (m_buffer[len] != UChar(0))
+            len++;
+
+        if (len > std::numeric_limits<unsigned>::max())
+            CRASH();
+
+        m_length = len;
+    }
+
+    unsigned length() { return m_length; }
+
+    void writeTo(UChar* destination)
+    {
+        memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(UChar));
+    }
+
+private:
+    const UChar* m_buffer;
+    unsigned m_length;
+};
+
+template<>
+class StringTypeAdapter<const char*> {
+public:
+    StringTypeAdapter<const char*>(const char* buffer)
+        : m_buffer(buffer)
+        , m_length(strlen(buffer))
+    {
+    }
+
+    unsigned length() { return m_length; }
+
+    void writeTo(UChar* destination)
+    {
+        for (unsigned i = 0; i < m_length; ++i) {
+            unsigned char c = m_buffer[i];
+            destination[i] = c;
+        }
+    }
+
+private:
+    const char* m_buffer;
+    unsigned m_length;
+};
+
+template<>
+class StringTypeAdapter<Vector<char> > {
+public:
+    StringTypeAdapter<Vector<char> >(const Vector<char>& buffer)
+        : m_buffer(buffer)
+    {
+    }
+
+    size_t length() { return m_buffer.size(); }
+
+    void writeTo(UChar* destination)
+    {
+        for (size_t i = 0; i < m_buffer.size(); ++i) {
+            unsigned char c = m_buffer[i];
+            destination[i] = c;
+        }
+    }
+
+private:
+    const Vector<char>& m_buffer;
+};
+
+template<>
+class StringTypeAdapter<String> {
+public:
+    StringTypeAdapter<String>(const String& string)
+        : m_buffer(string)
+    {
+    }
+
+    unsigned length() { return m_buffer.length(); }
+
+    void writeTo(UChar* destination)
+    {
+        const UChar* data = m_buffer.characters();
+        unsigned length = m_buffer.length();
+        for (unsigned i = 0; i < length; ++i)
+            destination[i] = data[i];
+    }
+
+private:
+    const String& m_buffer;
+};
+
+template<>
+class StringTypeAdapter<AtomicString> {
+public:
+    StringTypeAdapter<AtomicString>(const AtomicString& string)
+        : m_adapter(string.string())
+    {
+    }
+
+    unsigned length() { return m_adapter.length(); }
+    void writeTo(UChar* destination) { m_adapter.writeTo(destination); }
+
+private:
+    StringTypeAdapter<String> m_adapter;
+};
+
+inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow)
+{
+    unsigned oldTotal = total;
+    total = oldTotal + addend;
+    if (total < oldTotal)
+        overflow = true;
+}
+
+template<typename StringType1, typename StringType2>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+
+    UChar* buffer = 0;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+    StringTypeAdapter<StringType4> adapter4(string4);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    sumWithOverflow(length, adapter4.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+    result += adapter3.length();
+    adapter4.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+    StringTypeAdapter<StringType4> adapter4(string4);
+    StringTypeAdapter<StringType5> adapter5(string5);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    sumWithOverflow(length, adapter4.length(), overflow);
+    sumWithOverflow(length, adapter5.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+    result += adapter3.length();
+    adapter4.writeTo(result);
+    result += adapter4.length();
+    adapter5.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+    StringTypeAdapter<StringType4> adapter4(string4);
+    StringTypeAdapter<StringType5> adapter5(string5);
+    StringTypeAdapter<StringType6> adapter6(string6);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    sumWithOverflow(length, adapter4.length(), overflow);
+    sumWithOverflow(length, adapter5.length(), overflow);
+    sumWithOverflow(length, adapter6.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+    result += adapter3.length();
+    adapter4.writeTo(result);
+    result += adapter4.length();
+    adapter5.writeTo(result);
+    result += adapter5.length();
+    adapter6.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+    StringTypeAdapter<StringType4> adapter4(string4);
+    StringTypeAdapter<StringType5> adapter5(string5);
+    StringTypeAdapter<StringType6> adapter6(string6);
+    StringTypeAdapter<StringType7> adapter7(string7);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    sumWithOverflow(length, adapter4.length(), overflow);
+    sumWithOverflow(length, adapter5.length(), overflow);
+    sumWithOverflow(length, adapter6.length(), overflow);
+    sumWithOverflow(length, adapter7.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+    result += adapter3.length();
+    adapter4.writeTo(result);
+    result += adapter4.length();
+    adapter5.writeTo(result);
+    result += adapter5.length();
+    adapter6.writeTo(result);
+    result += adapter6.length();
+    adapter7.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+    StringTypeAdapter<StringType4> adapter4(string4);
+    StringTypeAdapter<StringType5> adapter5(string5);
+    StringTypeAdapter<StringType6> adapter6(string6);
+    StringTypeAdapter<StringType7> adapter7(string7);
+    StringTypeAdapter<StringType8> adapter8(string8);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    sumWithOverflow(length, adapter4.length(), overflow);
+    sumWithOverflow(length, adapter5.length(), overflow);
+    sumWithOverflow(length, adapter6.length(), overflow);
+    sumWithOverflow(length, adapter7.length(), overflow);
+    sumWithOverflow(length, adapter8.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+    result += adapter3.length();
+    adapter4.writeTo(result);
+    result += adapter4.length();
+    adapter5.writeTo(result);
+    result += adapter5.length();
+    adapter6.writeTo(result);
+    result += adapter6.length();
+    adapter7.writeTo(result);
+    result += adapter7.length();
+    adapter8.writeTo(result);
+
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
+PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
+{
+    StringTypeAdapter<StringType1> adapter1(string1);
+    StringTypeAdapter<StringType2> adapter2(string2);
+    StringTypeAdapter<StringType3> adapter3(string3);
+    StringTypeAdapter<StringType4> adapter4(string4);
+    StringTypeAdapter<StringType5> adapter5(string5);
+    StringTypeAdapter<StringType6> adapter6(string6);
+    StringTypeAdapter<StringType7> adapter7(string7);
+    StringTypeAdapter<StringType8> adapter8(string8);
+    StringTypeAdapter<StringType9> adapter9(string9);
+
+    UChar* buffer;
+    bool overflow = false;
+    unsigned length = adapter1.length();
+    sumWithOverflow(length, adapter2.length(), overflow);
+    sumWithOverflow(length, adapter3.length(), overflow);
+    sumWithOverflow(length, adapter4.length(), overflow);
+    sumWithOverflow(length, adapter5.length(), overflow);
+    sumWithOverflow(length, adapter6.length(), overflow);
+    sumWithOverflow(length, adapter7.length(), overflow);
+    sumWithOverflow(length, adapter8.length(), overflow);
+    sumWithOverflow(length, adapter9.length(), overflow);
+    if (overflow)
+        return 0;
+    RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer);
+    if (!resultImpl)
+        return 0;
+
+    UChar* result = buffer;
+    adapter1.writeTo(result);
+    result += adapter1.length();
+    adapter2.writeTo(result);
+    result += adapter2.length();
+    adapter3.writeTo(result);
+    result += adapter3.length();
+    adapter4.writeTo(result);
+    result += adapter4.length();
+    adapter5.writeTo(result);
+    result += adapter5.length();
+    adapter6.writeTo(result);
+    result += adapter6.length();
+    adapter7.writeTo(result);
+    result += adapter7.length();
+    adapter8.writeTo(result);
+    result += adapter8.length();
+    adapter9.writeTo(result);
+
+    return resultImpl.release();
+}
+
+
+// Convenience only.
+template<typename StringType1>
+String makeString(StringType1 string1)
+{
+    return String(string1);
+}
+
+template<typename StringType1, typename StringType2>
+String makeString(StringType1 string1, StringType2 string2)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9>
+String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9)
+{
+    RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9);
+    if (!resultImpl)
+        CRASH();
+    return resultImpl.release();
+}
+
+} // namespace WTF
+
+using WTF::makeString;
+
+#include "StringOperators.h"
+#endif
index b82000443333817487fb8f56d9796a48750f3702..c47c1d874009230f97d5a982e3816ad380b3f0ee 100644 (file)
 
 #include "AtomicString.h"
 #include "WTFString.h"
+#include <wtf/Forward.h>
 #include <wtf/HashTraits.h>
-#include <wtf/StringHashFunctions.h>
+#include <wtf/StringHasher.h>
 #include <wtf/unicode/Unicode.h>
 
-// FIXME: This is a temporary layering violation while we move string code to WTF.
-// Landing the file moves in one patch, will follow on with patches to change the namespaces.
-namespace WebCore {
+namespace WTF {
 
     // The hash() functions on StringHash and CaseFoldingHash do not support
     // null strings. get(), contains(), and add() on HashMap<String,..., StringHash>
@@ -56,7 +55,7 @@ namespace WebCore {
 
             // FIXME: perhaps we should have a more abstract macro that indicates when
             // going 4 bytes at a time is unsafe
-#if CPU(ARM) || CPU(SH4)
+#if CPU(ARM) || CPU(SH4) || CPU(MIPS)
             const UChar* aChars = a->characters();
             const UChar* bChars = b->characters();
             for (unsigned i = 0; i != aLength; ++i) {
@@ -98,99 +97,26 @@ namespace WebCore {
 
     class CaseFoldingHash {
     public:
-        // Paul Hsieh's SuperFastHash
-        // http://www.azillionmonkeys.com/qed/hash.html
+        template<typename T> static inline UChar foldCase(T ch)
+        {
+            return WTF::Unicode::foldCase(ch);
+        }
+
         static unsigned hash(const UChar* data, unsigned length)
         {
-            unsigned l = length;
-            const UChar* s = data;
-            uint32_t hash = WTF::stringHashingStartValue;
-            uint32_t tmp;
-            
-            int rem = l & 1;
-            l >>= 1;
-            
-            // Main loop.
-            for (; l > 0; l--) {
-                hash += WTF::Unicode::foldCase(s[0]);
-                tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash;
-                hash = (hash << 16) ^ tmp;
-                s += 2;
-                hash += hash >> 11;
-            }
-            
-            // Handle end case.
-            if (rem) {
-                hash += WTF::Unicode::foldCase(s[0]);
-                hash ^= hash << 11;
-                hash += hash >> 17;
-            }
-            
-            // Force "avalanching" of final 127 bits.
-            hash ^= hash << 3;
-            hash += hash >> 5;
-            hash ^= hash << 2;
-            hash += hash >> 15;
-            hash ^= hash << 10;
-            
-            // This avoids ever returning a hash code of 0, since that is used to
-            // signal "hash not computed yet", using a value that is likely to be
-            // effectively the same as 0 when the low bits are masked.
-            hash |= !hash << 31;
-            
-            return hash;
+            return StringHasher::computeHash<UChar, foldCase<UChar> >(data, length);
         }
 
         static unsigned hash(StringImpl* str)
         {
             return hash(str->characters(), str->length());
         }
-        
-        static unsigned hash(const char* str, unsigned length)
-        {
-            // This hash is designed to work on 16-bit chunks at a time. But since the normal case
-            // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they
-            // were 16-bit chunks, which will give matching results.
 
-            unsigned l = length;
-            const char* s = str;
-            uint32_t hash = WTF::stringHashingStartValue;
-            uint32_t tmp;
-            
-            int rem = l & 1;
-            l >>= 1;
-            
-            // Main loop
-            for (; l > 0; l--) {
-                hash += WTF::Unicode::foldCase(s[0]);
-                tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash;
-                hash = (hash << 16) ^ tmp;
-                s += 2;
-                hash += hash >> 11;
-            }
-            
-            // Handle end case
-            if (rem) {
-                hash += WTF::Unicode::foldCase(s[0]);
-                hash ^= hash << 11;
-                hash += hash >> 17;
-            }
-            
-            // Force "avalanching" of final 127 bits
-            hash ^= hash << 3;
-            hash += hash >> 5;
-            hash ^= hash << 2;
-            hash += hash >> 15;
-            hash ^= hash << 10;
-            
-            // this avoids ever returning a hash code of 0, since that is used to
-            // signal "hash not computed yet", using a value that is likely to be
-            // effectively the same as 0 when the low bits are masked
-            hash |= !hash << 31;
-            
-            return hash;
+        static unsigned hash(const char* data, unsigned length)
+        {
+            return StringHasher::computeHash<char, foldCase<char> >(data, length);
         }
-        
+
         static bool equal(const StringImpl* a, const StringImpl* b)
         {
             if (a == b)
@@ -253,16 +179,12 @@ namespace WebCore {
         }
     };
 
-}
-
-namespace WTF {
-
-    template<> struct HashTraits<WebCore::String> : GenericHashTraits<WebCore::String> {
-        static const bool emptyValueIsZero = true;
-        static void constructDeletedValue(WebCore::String& slot) { new (&slot) WebCore::String(HashTableDeletedValue); }
-        static bool isDeletedValue(const WebCore::String& slot) { return slot.isHashTableDeletedValue(); }
-    };
+    template<> struct HashTraits<String> : SimpleClassHashTraits<String> { };
 
 }
 
+using WTF::StringHash;
+using WTF::CaseFoldingHash;
+using WTF::AlreadyHashed;
+
 #endif
index 9d5333f98ca03a2ea1e6c27cd6c3ffebad282286..ec0c094636bdfdf0cda93fc92f6535e42b745276 100644 (file)
 #include <wtf/StdLibExtras.h>
 #include <wtf/WTFThreadData.h>
 
-using namespace WTF;
-using namespace Unicode;
 using namespace std;
 
-namespace WebCore {
+namespace WTF {
+
+using namespace Unicode;
 
 static const unsigned minLengthToShare = 20;
 
+COMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*), StringImpl_should_stay_small);
+
 StringImpl::~StringImpl()
 {
     ASSERT(!isStatic());
@@ -46,8 +48,10 @@ StringImpl::~StringImpl()
     if (isAtomic())
         AtomicString::remove(this);
 #if USE(JSC)
-    if (isIdentifier())
-        wtfThreadData().currentIdentifierTable()->remove(this);
+    if (isIdentifier()) {
+        if (!wtfThreadData().currentIdentifierTable()->remove(this))
+            CRASH();
+    }
 #endif
 
     BufferOwnership ownership = bufferOwnership();
@@ -143,7 +147,7 @@ SharedUChar* StringImpl::sharedBuffer()
         return m_substringBuffer->sharedBuffer();
     if (ownership == BufferOwned) {
         ASSERT(!m_sharedBuffer);
-        m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).releaseRef();
+        m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).leakRef();
         m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
     }
 
@@ -266,16 +270,17 @@ PassRefPtr<StringImpl> StringImpl::upper()
     return newImpl.release();
 }
 
-PassRefPtr<StringImpl> StringImpl::secure(UChar character, bool hideLastCharacter)
+PassRefPtr<StringImpl> StringImpl::secure(UChar character, LastCharacterBehavior behavior)
 {
+    if (!m_length)
+        return this;
+
     UChar* data;
     RefPtr<StringImpl> newImpl = createUninitialized(m_length, data);
-    if (m_length) {
-        const unsigned lastCharacterIndex = m_length - 1;
-        for (unsigned i = 0; i < lastCharacterIndex; ++i)
-            data[i] = character;
-        data[lastCharacterIndex] = hideLastCharacter ? character : m_data[lastCharacterIndex];
-    }
+    unsigned lastCharacterIndex = m_length - 1;
+    for (unsigned i = 0; i < lastCharacterIndex; ++i)
+        data[i] = character;
+    data[lastCharacterIndex] = (behavior == ObscureLastCharacter) ? character : m_data[lastCharacterIndex];
     return newImpl.release();
 }
 
@@ -453,14 +458,14 @@ intptr_t StringImpl::toIntPtr(bool* ok)
     return charactersToIntPtr(m_data, m_length, ok);
 }
 
-double StringImpl::toDouble(bool* ok)
+double StringImpl::toDouble(bool* ok, bool* didReadNumber)
 {
-    return charactersToDouble(m_data, m_length, ok);
+    return charactersToDouble(m_data, m_length, ok, didReadNumber);
 }
 
-float StringImpl::toFloat(bool* ok)
+float StringImpl::toFloat(bool* ok, bool* didReadNumber)
 {
-    return charactersToFloat(m_data, m_length, ok);
+    return charactersToFloat(m_data, m_length, ok, didReadNumber);
 }
 
 static bool equal(const UChar* a, const char* b, int length)
@@ -490,178 +495,279 @@ static inline bool equalIgnoringCase(const UChar* a, const UChar* b, int length)
     return umemcasecmp(a, b, length) == 0;
 }
 
-int StringImpl::find(const char* chs, int index, bool caseSensitive)
+int codePointCompare(const StringImpl* s1, const StringImpl* s2)
 {
-    if (!chs || index < 0)
-        return -1;
+    const unsigned l1 = s1 ? s1->length() : 0;
+    const unsigned l2 = s2 ? s2->length() : 0;
+    const unsigned lmin = l1 < l2 ? l1 : l2;
+    const UChar* c1 = s1 ? s1->characters() : 0;
+    const UChar* c2 = s2 ? s2->characters() : 0;
+    unsigned pos = 0;
+    while (pos < lmin && *c1 == *c2) {
+        c1++;
+        c2++;
+        pos++;
+    }
+
+    if (pos < lmin)
+        return (c1[0] > c2[0]) ? 1 : -1;
+
+    if (l1 == l2)
+        return 0;
 
-    size_t matchStringLength = strlen(chs);
-    if (matchStringLength > static_cast<unsigned>(numeric_limits<int>::max()))
+    return (l1 > l2) ? 1 : -1;
+}
+
+size_t StringImpl::find(UChar c, unsigned start)
+{
+    return WTF::find(m_data, m_length, c, start);
+}
+
+size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start)
+{
+    return WTF::find(m_data, m_length, matchFunction, start);
+}
+
+size_t StringImpl::find(const char* matchString, unsigned index)
+{
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    size_t matchStringLength = strlen(matchString);
+    if (matchStringLength > numeric_limits<unsigned>::max())
         CRASH();
-    int chsLength = matchStringLength;
-    int n = m_length - index;
-    if (n < 0)
-        return -1;
-    n -= chsLength - 1;
-    if (n <= 0)
-        return -1;
-
-    const char* chsPlusOne = chs + 1;
-    int chsLengthMinusOne = chsLength - 1;
-    
-    const UChar* ptr = m_data + index - 1;
-    if (caseSensitive) {
-        UChar c = *chs;
-        do {
-            if (*++ptr == c && equal(ptr + 1, chsPlusOne, chsLengthMinusOne))
-                return m_length - chsLength - n + 1;
-        } while (--n);
-    } else {
-        UChar lc = Unicode::foldCase(*chs);
-        do {
-            if (Unicode::foldCase(*++ptr) == lc && equalIgnoringCase(ptr + 1, chsPlusOne, chsLengthMinusOne))
-                return m_length - chsLength - n + 1;
-        } while (--n);
-    }
-
-    return -1;
-}
-
-int StringImpl::find(UChar c, int start)
-{
-    return WebCore::find(m_data, m_length, c, start);
-}
-
-int StringImpl::find(CharacterMatchFunctionPtr matchFunction, int start)
-{
-    return WebCore::find(m_data, m_length, matchFunction, start);
-}
-
-int StringImpl::find(StringImpl* str, int index, bool caseSensitive)
-{
-    /*
-      We use a simple trick for efficiency's sake. Instead of
-      comparing strings, we compare the sum of str with that of
-      a part of this string. Only if that matches, we call memcmp
-      or ucstrnicmp.
-    */
-    ASSERT(str);
-    if (index < 0)
-        index += m_length;
-    int lstr = str->m_length;
-    int lthis = m_length - index;
-    if ((unsigned)lthis > m_length)
-        return -1;
-    int delta = lthis - lstr;
-    if (delta < 0)
-        return -1;
-
-    const UChar* uthis = m_data + index;
-    const UChar* ustr = str->m_data;
-    unsigned hthis = 0;
-    unsigned hstr = 0;
-    if (caseSensitive) {
-        for (int i = 0; i < lstr; i++) {
-            hthis += uthis[i];
-            hstr += ustr[i];
-        }
-        int i = 0;
-        while (1) {
-            if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0)
-                return index + i;
-            if (i == delta)
-                return -1;
-            hthis += uthis[i + lstr];
-            hthis -= uthis[i];
-            i++;
-        }
-    } else {
-        for (int i = 0; i < lstr; i++ ) {
-            hthis += toASCIILower(uthis[i]);
-            hstr += toASCIILower(ustr[i]);
-        }
-        int i = 0;
-        while (1) {
-            if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr))
-                return index + i;
-            if (i == delta)
-                return -1;
-            hthis += toASCIILower(uthis[i + lstr]);
-            hthis -= toASCIILower(uthis[i]);
-            i++;
-        }
+    unsigned matchLength = matchStringLength;
+    if (!matchLength)
+        return min(index, length());
+
+    // Optimization 1: fast case for strings of length 1.
+    if (matchLength == 1)
+        return WTF::find(characters(), length(), *(const unsigned char*)matchString, index);
+
+    // Check index & matchLength are in range.
+    if (index > length())
+        return notFound;
+    unsigned searchLength = length() - index;
+    if (matchLength > searchLength)
+        return notFound;
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = searchLength - matchLength;
+
+    const UChar* searchCharacters = characters() + index;
+    const unsigned char* matchCharacters = (const unsigned char*)matchString;
+
+    // Optimization 2: keep a running hash of the strings,
+    // only call memcmp if the hashes match.
+    unsigned searchHash = 0;
+    unsigned matchHash = 0;
+    for (unsigned i = 0; i < matchLength; ++i) {
+        searchHash += searchCharacters[i];
+        matchHash += matchCharacters[i];
+    }
+
+    unsigned i = 0;
+    // keep looping until we match
+    while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) {
+        if (i == delta)
+            return notFound;
+        searchHash += searchCharacters[i + matchLength];
+        searchHash -= searchCharacters[i];
+        ++i;
     }
+    return index + i;
 }
 
-int StringImpl::reverseFind(UChar c, int index)
+size_t StringImpl::findIgnoringCase(const char* matchString, unsigned index)
 {
-    return WebCore::reverseFind(m_data, m_length, c, index);
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    size_t matchStringLength = strlen(matchString);
+    if (matchStringLength > numeric_limits<unsigned>::max())
+        CRASH();
+    unsigned matchLength = matchStringLength;
+    if (!matchLength)
+        return min(index, length());
+
+    // Check index & matchLength are in range.
+    if (index > length())
+        return notFound;
+    unsigned searchLength = length() - index;
+    if (matchLength > searchLength)
+        return notFound;
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = searchLength - matchLength;
+
+    const UChar* searchCharacters = characters() + index;
+
+    unsigned i = 0;
+    // keep looping until we match
+    while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) {
+        if (i == delta)
+            return notFound;
+        ++i;
+    }
+    return index + i;
 }
 
-int StringImpl::reverseFind(StringImpl* str, int index, bool caseSensitive)
+size_t StringImpl::find(StringImpl* matchString, unsigned index)
 {
-    /*
-     See StringImpl::find() for explanations.
-     */
-    ASSERT(str);
-    int lthis = m_length;
-    if (index < 0)
-        index += lthis;
-    
-    int lstr = str->m_length;
-    int delta = lthis - lstr;
-    if ( index < 0 || index > lthis || delta < 0 )
-        return -1;
-    if ( index > delta )
-        index = delta;
-    
-    const UChar *uthis = m_data;
-    const UChar *ustr = str->m_data;
-    unsigned hthis = 0;
-    unsigned hstr = 0;
-    int i;
-    if (caseSensitive) {
-        for ( i = 0; i < lstr; i++ ) {
-            hthis += uthis[index + i];
-            hstr += ustr[i];
-        }
-        i = index;
-        while (1) {
-            if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0)
-                return i;
-            if (i == 0)
-                return -1;
-            i--;
-            hthis -= uthis[i + lstr];
-            hthis += uthis[i];
-        }
-    } else {
-        for (i = 0; i < lstr; i++) {
-            hthis += toASCIILower(uthis[index + i]);
-            hstr += toASCIILower(ustr[i]);
-        }
-        i = index;
-        while (1) {
-            if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr) )
-                return i;
-            if (i == 0)
-                return -1;
-            i--;
-            hthis -= toASCIILower(uthis[i + lstr]);
-            hthis += toASCIILower(uthis[i]);
-        }
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    unsigned matchLength = matchString->length();
+    if (!matchLength)
+        return min(index, length());
+
+    // Optimization 1: fast case for strings of length 1.
+    if (matchLength == 1)
+        return WTF::find(characters(), length(), matchString->characters()[0], index);
+
+    // Check index & matchLength are in range.
+    if (index > length())
+        return notFound;
+    unsigned searchLength = length() - index;
+    if (matchLength > searchLength)
+        return notFound;
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = searchLength - matchLength;
+
+    const UChar* searchCharacters = characters() + index;
+    const UChar* matchCharacters = matchString->characters();
+
+    // Optimization 2: keep a running hash of the strings,
+    // only call memcmp if the hashes match.
+    unsigned searchHash = 0;
+    unsigned matchHash = 0;
+    for (unsigned i = 0; i < matchLength; ++i) {
+        searchHash += searchCharacters[i];
+        matchHash += matchCharacters[i];
+    }
+
+    unsigned i = 0;
+    // keep looping until we match
+    while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(UChar))) {
+        if (i == delta)
+            return notFound;
+        searchHash += searchCharacters[i + matchLength];
+        searchHash -= searchCharacters[i];
+        ++i;
+    }
+    return index + i;
+}
+
+size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index)
+{
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    unsigned matchLength = matchString->length();
+    if (!matchLength)
+        return min(index, length());
+
+    // Check index & matchLength are in range.
+    if (index > length())
+        return notFound;
+    unsigned searchLength = length() - index;
+    if (matchLength > searchLength)
+        return notFound;
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = searchLength - matchLength;
+
+    const UChar* searchCharacters = characters() + index;
+    const UChar* matchCharacters = matchString->characters();
+
+    unsigned i = 0;
+    // keep looping until we match
+    while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength)) {
+        if (i == delta)
+            return notFound;
+        ++i;
+    }
+    return index + i;
+}
+
+size_t StringImpl::reverseFind(UChar c, unsigned index)
+{
+    return WTF::reverseFind(m_data, m_length, c, index);
+}
+
+size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index)
+{
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    unsigned matchLength = matchString->length();
+    if (!matchLength)
+        return min(index, length());
+
+    // Optimization 1: fast case for strings of length 1.
+    if (matchLength == 1)
+        return WTF::reverseFind(characters(), length(), matchString->characters()[0], index);
+
+    // Check index & matchLength are in range.
+    if (matchLength > length())
+        return notFound;
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = min(index, length() - matchLength);
+
+    const UChar *searchCharacters = characters();
+    const UChar *matchCharacters = matchString->characters();
+
+    // Optimization 2: keep a running hash of the strings,
+    // only call memcmp if the hashes match.
+    unsigned searchHash = 0;
+    unsigned matchHash = 0;
+    for (unsigned i = 0; i < matchLength; ++i) {
+        searchHash += searchCharacters[delta + i];
+        matchHash += matchCharacters[i];
+    }
+
+    // keep looping until we match
+    while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(UChar))) {
+        if (!delta)
+            return notFound;
+        delta--;
+        searchHash -= searchCharacters[delta + matchLength];
+        searchHash += searchCharacters[delta];
     }
+    return delta;
+}
+
+size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index)
+{
+    // Check for null or empty string to match against
+    if (!matchString)
+        return notFound;
+    unsigned matchLength = matchString->length();
+    if (!matchLength)
+        return min(index, length());
+
+    // Check index & matchLength are in range.
+    if (matchLength > length())
+        return notFound;
+    // delta is the number of additional times to test; delta == 0 means test only once.
+    unsigned delta = min(index, length() - matchLength);
     
-    // Should never get here.
-    return -1;
+    const UChar *searchCharacters = characters();
+    const UChar *matchCharacters = matchString->characters();
+
+    // keep looping until we match
+    while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) {
+        if (!delta)
+            return notFound;
+        delta--;
+    }
+    return delta;
 }
 
-bool StringImpl::endsWith(StringImpl* m_data, bool caseSensitive)
+bool StringImpl::endsWith(StringImpl* matchString, bool caseSensitive)
 {
-    ASSERT(m_data);
-    int start = m_length - m_data->m_length;
-    if (start >= 0)
-        return (find(m_data, start, caseSensitive) == start);
+    ASSERT(matchString);
+    if (m_length >= matchString->m_length) {
+        unsigned start = m_length - matchString->m_length;
+        return (caseSensitive ? find(matchString, start) : findIgnoringCase(matchString, start)) == start;
+    }
     return false;
 }
 
@@ -715,12 +821,12 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
     if (!replacement)
         return this;
         
-    int repStrLength = replacement->length();
-    int srcSegmentStart = 0;
+    unsigned repStrLength = replacement->length();
+    size_t srcSegmentStart = 0;
     unsigned matchCount = 0;
     
     // Count the matches
-    while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) {
+    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
         ++matchCount;
         ++srcSegmentStart;
     }
@@ -743,12 +849,12 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
 
     // Construct the new data
-    int srcSegmentEnd;
-    int srcSegmentLength;
+    size_t srcSegmentEnd;
+    unsigned srcSegmentLength;
     srcSegmentStart = 0;
-    int dstOffset = 0;
+    unsigned dstOffset = 0;
     
-    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) {
+    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
         srcSegmentLength = srcSegmentEnd - srcSegmentStart;
         memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
         dstOffset += srcSegmentLength;
@@ -760,7 +866,7 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
     srcSegmentLength = m_length - srcSegmentStart;
     memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
 
-    ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length()));
+    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
 
     return newImpl.release();
 }
@@ -770,16 +876,16 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl
     if (!pattern || !replacement)
         return this;
 
-    int patternLength = pattern->length();
+    unsigned patternLength = pattern->length();
     if (!patternLength)
         return this;
         
-    int repStrLength = replacement->length();
-    int srcSegmentStart = 0;
+    unsigned repStrLength = replacement->length();
+    size_t srcSegmentStart = 0;
     unsigned matchCount = 0;
     
     // Count the matches
-    while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) {
+    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
         ++matchCount;
         srcSegmentStart += patternLength;
     }
@@ -801,12 +907,12 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl
     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
     
     // Construct the new data
-    int srcSegmentEnd;
-    int srcSegmentLength;
+    size_t srcSegmentEnd;
+    unsigned srcSegmentLength;
     srcSegmentStart = 0;
-    int dstOffset = 0;
+    unsigned dstOffset = 0;
     
-    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) {
+    while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) {
         srcSegmentLength = srcSegmentEnd - srcSegmentStart;
         memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
         dstOffset += srcSegmentLength;
@@ -818,7 +924,7 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl
     srcSegmentLength = m_length - srcSegmentStart;
     memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar));
 
-    ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length()));
+    ASSERT(dstOffset + srcSegmentLength == newImpl->length());
 
     return newImpl.release();
 }
@@ -899,29 +1005,23 @@ bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
     return false;
 }
 
-Vector<char> StringImpl::ascii()
-{
-    Vector<char> buffer(m_length + 1);
-    for (unsigned i = 0; i != m_length; ++i) {
-        UChar c = m_data[i];
-        if ((c >= 0x20 && c < 0x7F) || c == 0x00)
-            buffer[i] = static_cast<char>(c);
-        else
-            buffer[i] = '?';
-    }
-    buffer[m_length] = '\0';
-    return buffer;
-}
-
-WTF::Unicode::Direction StringImpl::defaultWritingDirection()
+WTF::Unicode::Direction StringImpl::defaultWritingDirection(bool* hasStrongDirectionality)
 {
     for (unsigned i = 0; i < m_length; ++i) {
         WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]);
-        if (charDirection == WTF::Unicode::LeftToRight)
+        if (charDirection == WTF::Unicode::LeftToRight) {
+            if (hasStrongDirectionality)
+                *hasStrongDirectionality = true;
             return WTF::Unicode::LeftToRight;
-        if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic)
+        }
+        if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) {
+            if (hasStrongDirectionality)
+                *hasStrongDirectionality = true;
             return WTF::Unicode::RightToLeft;
+        }
     }
+    if (hasStrongDirectionality)
+        *hasStrongDirectionality = false;
     return WTF::Unicode::LeftToRight;
 }
 
@@ -996,4 +1096,4 @@ PassRefPtr<StringImpl> StringImpl::crossThreadString()
     return threadsafeCopy();
 }
 
-} // namespace WebCore
+} // namespace WTF
index 4354cabaf2ba3736a188e2110fa7ce74e6ff69ae..239ab491e3e03b9927c332ab8f7c85f6deeed553 100644 (file)
 #include <limits.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/CrossThreadRefCounted.h>
+#include <wtf/Forward.h>
 #include <wtf/OwnFastMallocPtr.h>
 #include <wtf/StdLibExtras.h>
-#include <wtf/StringHashFunctions.h>
+#include <wtf/StringHasher.h>
 #include <wtf/Vector.h>
 #include <wtf/text/StringImplBase.h>
 #include <wtf/unicode/Unicode.h>
 
-#if PLATFORM(CF)
+#if USE(CF)
 typedef const struct __CFString * CFStringRef;
 #endif
 
@@ -44,21 +45,15 @@ typedef const struct __CFString * CFStringRef;
 // FIXME: This is a temporary layering violation while we move string code to WTF.
 // Landing the file moves in one patch, will follow on with patches to change the namespaces.
 namespace JSC {
-
 struct IdentifierCStringTranslator;
 struct IdentifierUCharBufferTranslator;
-
 }
 
-// FIXME: This is a temporary layering violation while we move string code to WTF.
-// Landing the file moves in one patch, will follow on with patches to change the namespaces.
-namespace WebCore {
-
-class StringBuffer;
+namespace WTF {
 
 struct CStringTranslator;
 struct HashAndCharactersTranslator;
-struct StringHash;
+struct HashAndUTF8CharactersTranslator;
 struct UCharBufferTranslator;
 
 enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
@@ -70,9 +65,10 @@ typedef bool (*CharacterMatchFunctionPtr)(UChar);
 class StringImpl : public StringImplBase {
     friend struct JSC::IdentifierCStringTranslator;
     friend struct JSC::IdentifierUCharBufferTranslator;
-    friend struct CStringTranslator;
-    friend struct HashAndCharactersTranslator;
-    friend struct UCharBufferTranslator;
+    friend struct WTF::CStringTranslator;
+    friend struct WTF::HashAndCharactersTranslator;
+    friend struct WTF::HashAndUTF8CharactersTranslator;
+    friend struct WTF::UCharBufferTranslator;
     friend class AtomicStringImpl;
 private:
     // Used to construct static strings, which have an special refCount that can never hit zero.
@@ -116,7 +112,7 @@ private:
     StringImpl(const UChar* characters, unsigned length, PassRefPtr<StringImpl> base)
         : StringImplBase(length, BufferSubstring)
         , m_data(characters)
-        , m_substringBuffer(base.releaseRef())
+        , m_substringBuffer(base.leakRef())
         , m_hash(0)
     {
         ASSERT(m_data);
@@ -128,7 +124,7 @@ private:
     StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer)
         : StringImplBase(length, BufferShared)
         , m_data(characters)
-        , m_sharedBuffer(sharedBuffer.releaseRef())
+        , m_sharedBuffer(sharedBuffer.leakRef())
         , m_hash(0)
     {
         ASSERT(m_data);
@@ -140,7 +136,7 @@ private:
     {
         ASSERT(!isStatic());
         ASSERT(!m_hash);
-        ASSERT(hash == computeHash(m_data, m_length));
+        ASSERT(hash == StringHasher::computeHash(m_data, m_length));
         m_hash = hash;
     }
 
@@ -151,7 +147,7 @@ public:
     static PassRefPtr<StringImpl> create(const char*, unsigned length);
     static PassRefPtr<StringImpl> create(const char*);
     static PassRefPtr<StringImpl> create(const UChar*, unsigned length, PassRefPtr<SharedUChar> sharedBuffer);
-    static PassRefPtr<StringImpl> create(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
+    static ALWAYS_INLINE PassRefPtr<StringImpl> create(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length)
     {
         ASSERT(rep);
         ASSERT(length <= rep->length());
@@ -164,7 +160,7 @@ public:
     }
 
     static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
-    static PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
+    static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, UChar*& output)
     {
         if (!length) {
             output = 0;
@@ -239,11 +235,8 @@ public:
             m_refCountAndFlags &= ~s_refCountFlagIsAtomic;
     }
 
-    unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; }
+    unsigned hash() const { if (!m_hash) m_hash = StringHasher::computeHash(m_data, m_length); return m_hash; }
     unsigned existingHash() const { ASSERT(m_hash); return m_hash; }
-    static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); }
-    static unsigned computeHash(const char* data, unsigned length) { return WTF::stringHash(data, length); }
-    static unsigned computeHash(const char* data) { return WTF::stringHash(data); }
 
     ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; }
     ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; }
@@ -285,12 +278,15 @@ public:
     uint64_t toUInt64(bool* ok = 0); // ignores trailing garbage
     intptr_t toIntPtr(bool* ok = 0); // ignores trailing garbage
 
-    double toDouble(bool* ok = 0);
-    float toFloat(bool* ok = 0);
+    double toDouble(bool* ok = 0, bool* didReadNumber = 0);
+    float toFloat(bool* ok = 0, bool* didReadNumber = 0);
 
     PassRefPtr<StringImpl> lower();
     PassRefPtr<StringImpl> upper();
-    PassRefPtr<StringImpl> secure(UChar, bool hideLastCharacter = true);
+
+    enum LastCharacterBehavior { ObscureLastCharacter, DisplayLastCharacter };
+
+    PassRefPtr<StringImpl> secure(UChar, LastCharacterBehavior = ObscureLastCharacter);
     PassRefPtr<StringImpl> foldCase();
 
     PassRefPtr<StringImpl> stripWhiteSpace();
@@ -298,15 +294,18 @@ public:
 
     PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr);
 
-    int find(const char*, int index = 0, bool caseSensitive = true);
-    int find(UChar, int index = 0);
-    int find(CharacterMatchFunctionPtr, int index = 0);
-    int find(StringImpl*, int index, bool caseSensitive = true);
+    size_t find(UChar, unsigned index = 0);
+    size_t find(CharacterMatchFunctionPtr, unsigned index = 0);
+    size_t find(const char*, unsigned index = 0);
+    size_t find(StringImpl*, unsigned index = 0);
+    size_t findIgnoringCase(const char*, unsigned index = 0);
+    size_t findIgnoringCase(StringImpl*, unsigned index = 0);
 
-    int reverseFind(UChar, int index);
-    int reverseFind(StringImpl*, int index, bool caseSensitive = true);
-    
-    bool startsWith(StringImpl* str, bool caseSensitive = true) { return reverseFind(str, 0, caseSensitive) == 0; }
+    size_t reverseFind(UChar, unsigned index = UINT_MAX);
+    size_t reverseFind(StringImpl*, unsigned index = UINT_MAX);
+    size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX);
+
+    bool startsWith(StringImpl* str, bool caseSensitive = true) { return (caseSensitive ? reverseFind(str, 0) : reverseFindIgnoringCase(str, 0)) == 0; }
     bool endsWith(StringImpl*, bool caseSensitive = true);
 
     PassRefPtr<StringImpl> replace(UChar, UChar);
@@ -314,12 +313,11 @@ public:
     PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*);
     PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*);
 
-    Vector<char> ascii();
     int wordCount(int maxWordsToCount = INT_MAX);
 
-    WTF::Unicode::Direction defaultWritingDirection();
+    WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0);
 
-#if PLATFORM(CF)
+#if USE(CF)
     CFStringRef createCFString();
 #endif
 #ifdef __OBJC__
@@ -355,6 +353,18 @@ inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) {
 
 bool equalIgnoringNullity(StringImpl*, StringImpl*);
 
+template<size_t inlineCapacity>
+bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, StringImpl* b)
+{
+    if (!b)
+        return !a.size();
+    if (a.size() != b->length())
+        return false;
+    return !memcmp(a.data(), b->characters(), b->length());
+}
+
+int codePointCompare(const StringImpl*, const StringImpl*);
+
 static inline bool isSpaceOrNewline(UChar c)
 {
     // Use isASCIISpace() for basic Latin-1.
@@ -385,21 +395,23 @@ inline PassRefPtr<StringImpl> StringImpl::createStrippingNullCharacters(const UC
     return StringImpl::createStrippingNullCharactersSlowCase(characters, length);
 }
 
-}
-
-using WebCore::equal;
-
-namespace WTF {
+struct StringHash;
 
-    // WebCore::StringHash is the default hash for StringImpl* and RefPtr<StringImpl>
-    template<typename T> struct DefaultHash;
-    template<> struct DefaultHash<WebCore::StringImpl*> {
-        typedef WebCore::StringHash Hash;
-    };
-    template<> struct DefaultHash<RefPtr<WebCore::StringImpl> > {
-        typedef WebCore::StringHash Hash;
-    };
+// StringHash is the default hash for StringImpl* and RefPtr<StringImpl>
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<StringImpl*> {
+    typedef StringHash Hash;
+};
+template<> struct DefaultHash<RefPtr<StringImpl> > {
+    typedef StringHash Hash;
+};
 
 }
 
+using WTF::StringImpl;
+using WTF::equal;
+using WTF::TextCaseSensitivity;
+using WTF::TextCaseSensitive;
+using WTF::TextCaseInsensitive;
+
 #endif
index 65676725eb583158a7569d0d1a0bb685b83bd019..26bc1d90ce524e5233f3e47c0e86ccccb1cfbb91 100644 (file)
 #ifndef StringImplBase_h
 #define StringImplBase_h
 
-#include <wtf/Noncopyable.h>
 #include <wtf/unicode/Unicode.h>
 
 namespace WTF {
 
-class StringImplBase : public Noncopyable {
+class StringImplBase {
+    WTF_MAKE_NONCOPYABLE(StringImplBase); WTF_MAKE_FAST_ALLOCATED;
 public:
     bool isStringImpl() { return (m_refCountAndFlags & s_refCountInvalidForStringImpl) != s_refCountInvalidForStringImpl; }
     unsigned length() const { return m_length; }
@@ -45,9 +45,6 @@ protected:
         BufferShared,
     };
 
-    using Noncopyable::operator new;
-    void* operator new(size_t, void* inPlace) { ASSERT(inPlace); return inPlace; }
-
     // For SmallStringStorage, which allocates an array and uses an in-place new.
     StringImplBase() { }
 
diff --git a/wtf/text/StringOperators.h b/wtf/text/StringOperators.h
new file mode 100644 (file)
index 0000000..e8c2181
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef StringOperators_h
+#define StringOperators_h
+
+namespace WTF {
+
+template<typename StringType1, typename StringType2>
+class StringAppend {
+public:
+    StringAppend(StringType1 string1, StringType2 string2)
+        : m_string1(string1)
+        , m_string2(string2)
+    {
+    }
+
+    operator String() const
+    {
+        RefPtr<StringImpl> resultImpl = tryMakeString(m_string1, m_string2);
+        if (!resultImpl)
+            CRASH();
+        return resultImpl.release();
+    }
+
+    operator AtomicString() const
+    {
+        return operator String();
+    }
+
+    void writeTo(UChar* destination)
+    {
+        StringTypeAdapter<StringType1> adapter1(m_string1);
+        StringTypeAdapter<StringType2> adapter2(m_string2);
+        adapter1.writeTo(destination);
+        adapter2.writeTo(destination + adapter1.length());
+    }
+
+    unsigned length()
+    {
+        StringTypeAdapter<StringType1> adapter1(m_string1);
+        StringTypeAdapter<StringType2> adapter2(m_string2);
+        return adapter1.length() + adapter2.length();
+    }    
+
+private:
+    StringType1 m_string1;
+    StringType2 m_string2;
+};
+
+template<typename StringType1, typename StringType2>
+class StringTypeAdapter<StringAppend<StringType1, StringType2> > {
+public:
+    StringTypeAdapter<StringAppend<StringType1, StringType2> >(StringAppend<StringType1, StringType2>& buffer)
+        : m_buffer(buffer)
+    {
+    }
+
+    unsigned length() { return m_buffer.length(); }
+    void writeTo(UChar* destination) { m_buffer.writeTo(destination); }
+
+private:
+    StringAppend<StringType1, StringType2>& m_buffer;
+};
+
+inline StringAppend<const char*, String> operator+(const char* string1, const String& string2)
+{
+    return StringAppend<const char*, String>(string1, string2);
+}
+
+inline StringAppend<const char*, AtomicString> operator+(const char* string1, const AtomicString& string2)
+{
+    return StringAppend<const char*, AtomicString>(string1, string2);
+}
+
+template<typename T>
+StringAppend<String, T> operator+(const String& string1, T string2)
+{
+    return StringAppend<String, T>(string1, string2);
+}
+
+template<typename U, typename V, typename W>
+StringAppend<U, StringAppend<V, W> > operator+(U string1, const StringAppend<V, W>& string2)
+{
+    return StringAppend<U, StringAppend<V, W> >(string1, string2);
+}
+
+} // namespace WTF
+
+#endif // StringOperators_h
index 5ee261354e45d6407a470ce29fa4fbf93f3673e6..1881464598f49a3ce6532875c81a8b55dfcc4dcd 100644 (file)
 #endif
 
 #include "AtomicString.h"
+#include "DynamicAnnotations.h"
 #include "StaticConstructors.h"
 #include "StringImpl.h"
 
-namespace WebCore {
+namespace WTF {
 
 StringImpl* StringImpl::empty()
 {
@@ -46,6 +47,7 @@ StringImpl* StringImpl::empty()
     // PCRE goes away.
     static UChar emptyUCharData = 0;
     DEFINE_STATIC_LOCAL(StringImpl, emptyString, (&emptyUCharData, 0, ConstructStaticString));
+    WTF_ANNOTATE_BENIGN_RACE(&emptyString, "Benign race on StringImpl::emptyString reference counter");
     return &emptyString;
 }
 
diff --git a/wtf/text/TextPosition.h b/wtf/text/TextPosition.h
new file mode 100644 (file)
index 0000000..bb3ffa4
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2010, Google 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. AND ITS CONTRIBUTORS ``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 ITS 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 TextPosition_h
+#define TextPosition_h
+
+#include <wtf/Assertions.h>
+
+namespace WTF {
+
+/*
+ * Text Position
+ *
+ * TextPosition structure specifies coordinates within an text resource. It is used mostly
+ * for saving script source position.
+ *
+ * Later TextPosition0 and TextPosition1 and both number types can be merged together quite easily.
+ *
+ * 0-based and 1-based
+ *
+ * Line and column numbers could be interpreted as zero-based or 1-based. Since
+ * both practices coexist in WebKit source base, 'int' type should be replaced with
+ * a dedicated wrapper types, so that compiler helped us with this ambiguity.
+ *
+ * Here we introduce 2 types of numbers: ZeroBasedNumber and OneBasedNumber and
+ * 2 corresponding types of TextPosition structure. While only one type ought to be enough,
+ * this is done to keep transition to the new types as transparent as possible:
+ * e.g. in areas where 0-based integers are used, TextPosition0 should be introduced. This
+ * way all changes will remain trackable.
+ *
+ * Later both number types can be merged in one type quite easily.
+ *
+ * For type safety and for the future type merge it is important that all operations in API
+ * that accept or return integer have a name explicitly defining base of integer. For this reason
+ * int-receiving constructors are hidden from API.
+ */
+
+template<typename NUMBER>
+class TextPosition {
+public:
+    TextPosition(NUMBER line, NUMBER column)
+        : m_line(line)
+        , m_column(column)
+    {
+    }
+    TextPosition() {}
+
+    bool operator==(const TextPosition& other) { return m_line == other.m_line && m_column == other.m_column; }
+    bool operator!=(const TextPosition& other) { return !((*this) == other); }
+
+    // A 'minimum' value of position, used as a default value.
+    static TextPosition<NUMBER> minimumPosition() { return TextPosition<NUMBER>(NUMBER::base(), NUMBER::base()); }
+
+    // A value with line value less than a minimum; used as an impossible position.
+    static TextPosition<NUMBER> belowRangePosition() { return TextPosition<NUMBER>(NUMBER::belowBase(), NUMBER::belowBase()); }
+
+    NUMBER m_line;
+    NUMBER m_column;
+};
+
+class OneBasedNumber;
+
+// An int wrapper that always reminds you that the number should be 0-based
+class ZeroBasedNumber {
+public:
+    static ZeroBasedNumber fromZeroBasedInt(int zeroBasedInt) { return ZeroBasedNumber(zeroBasedInt); }
+
+    ZeroBasedNumber() {}
+
+    int zeroBasedInt() const { return m_value; }
+    int convertAsOneBasedInt() const { return m_value + 1; }
+    OneBasedNumber convertToOneBased() const;
+
+    bool operator==(ZeroBasedNumber other) { return m_value == other.m_value; }
+    bool operator!=(ZeroBasedNumber other) { return !((*this) == other); }
+
+    static ZeroBasedNumber base() { return 0; }
+    static ZeroBasedNumber belowBase() { return -1; }
+
+private:
+    ZeroBasedNumber(int value) : m_value(value) {}
+    int m_value;
+};
+
+// An int wrapper that always reminds you that the number should be 1-based
+class OneBasedNumber {
+public:
+    static OneBasedNumber fromOneBasedInt(int oneBasedInt) { return OneBasedNumber(oneBasedInt); }
+    OneBasedNumber() {}
+
+    int oneBasedInt() const { return m_value; }
+    int convertAsZeroBasedInt() const { return m_value - 1; }
+    ZeroBasedNumber convertToZeroBased() const { return ZeroBasedNumber::fromZeroBasedInt(m_value - 1); }
+
+    bool operator==(OneBasedNumber other) { return m_value == other.m_value; }
+    bool operator!=(OneBasedNumber other) { return !((*this) == other); }
+
+    static OneBasedNumber base() { return 1; }
+    static OneBasedNumber belowBase() { return 0; }
+
+private:
+    OneBasedNumber(int value) : m_value(value) {}
+    int m_value;
+};
+
+typedef TextPosition<ZeroBasedNumber> TextPosition0;
+typedef TextPosition<OneBasedNumber> TextPosition1;
+
+inline TextPosition0 toZeroBasedTextPosition(const TextPosition1& position)
+{
+    return TextPosition0(position.m_line.convertToZeroBased(), position.m_column.convertToZeroBased());
+}
+
+inline TextPosition1 toOneBasedTextPosition(const TextPosition0& position)
+{
+    return TextPosition1(position.m_line.convertToOneBased(), position.m_column.convertToOneBased());
+}
+
+inline OneBasedNumber ZeroBasedNumber::convertToOneBased() const
+{
+    return OneBasedNumber::fromOneBasedInt(m_value + 1);
+}
+
+}
+
+using WTF::TextPosition0;
+using WTF::TextPosition1;
+
+#endif // TextPosition_h
index e73bac22c693bc0384ab70865e4c0648820f480a..3ab4ff501b88105a7277d905e9a251ebb113081a 100644 (file)
 #include <wtf/unicode/UTF8.h>
 #include <wtf/unicode/Unicode.h>
 
-using namespace WTF;
-using namespace WTF::Unicode;
 using namespace std;
 
-namespace WebCore {
+namespace WTF {
 
+using namespace Unicode;
+using namespace std;
+
+// Construct a string with UTF-16 data.
+String::String(const UChar* characters, unsigned length)
+    : m_impl(characters ? StringImpl::create(characters, length) : 0)
+{
+}
+
+// Construct a string with UTF-16 data, from a null-terminated source.
 String::String(const UChar* str)
 {
     if (!str)
@@ -52,6 +60,18 @@ String::String(const UChar* str)
     m_impl = StringImpl::create(str, len);
 }
 
+// Construct a string with latin1 data.
+String::String(const char* characters, unsigned length)
+    : m_impl(characters ? StringImpl::create(characters, length) : 0)
+{
+}
+
+// Construct a string with latin1 data, from a null-terminated source.
+String::String(const char* characters)
+    : m_impl(characters ? StringImpl::create(characters) : 0)
+{
+}
+
 void String::append(const String& str)
 {
     if (str.isEmpty())
@@ -111,25 +131,9 @@ void String::append(UChar c)
         m_impl = StringImpl::create(&c, 1);
 }
 
-String operator+(const String& a, const String& b)
+int codePointCompare(const String& a, const String& b)
 {
-    if (a.isEmpty())
-        return b;
-    if (b.isEmpty())
-        return a;
-    String c = a;
-    c += b;
-    return c;
-}
-
-String operator+(const String& s, const char* cs)
-{
-    return s + String(cs);
-}
-
-String operator+(const char* cs, const String& s)
-{
-    return String(cs) + s;
+    return codePointCompare(a.impl(), b.impl());
 }
 
 void String::insert(const String& str, unsigned pos)
@@ -229,6 +233,19 @@ String String::substring(unsigned pos, unsigned len) const
     return m_impl->substring(pos, len);
 }
 
+String String::substringSharingImpl(unsigned offset, unsigned length) const
+{
+    // FIXME: We used to check against a limit of Heap::minExtraCost / sizeof(UChar).
+
+    unsigned stringLength = this->length();
+    offset = min(offset, stringLength);
+    length = min(length, stringLength - offset);
+
+    if (!offset && length == stringLength)
+        return *this;
+    return String(StringImpl::create(m_impl, offset, length));
+}
+
 String String::lower() const
 {
     if (!m_impl)
@@ -306,7 +323,8 @@ String String::format(const char *format, ...)
 
     va_end(args);
 
-    return buffer;
+    QByteArray ba = buffer.toUtf8();
+    return StringImpl::create(ba.constData(), ba.length());
 
 #elif OS(WINCE)
     va_list args;
@@ -522,24 +540,28 @@ intptr_t String::toIntPtr(bool* ok) const
     return m_impl->toIntPtr(ok);
 }
 
-double String::toDouble(bool* ok) const
+double String::toDouble(bool* ok, bool* didReadNumber) const
 {
     if (!m_impl) {
         if (ok)
             *ok = false;
+        if (didReadNumber)
+            *didReadNumber = false;
         return 0.0;
     }
-    return m_impl->toDouble(ok);
+    return m_impl->toDouble(ok, didReadNumber);
 }
 
-float String::toFloat(bool* ok) const
+float String::toFloat(bool* ok, bool* didReadNumber) const
 {
     if (!m_impl) {
         if (ok)
             *ok = false;
+        if (didReadNumber)
+            *didReadNumber = false;
         return 0.0f;
     }
-    return m_impl->toFloat(ok);
+    return m_impl->toFloat(ok, didReadNumber);
 }
 
 String String::threadsafeCopy() const
@@ -560,54 +582,59 @@ void String::split(const String& separator, bool allowEmptyEntries, Vector<Strin
 {
     result.clear();
 
-    int startPos = 0;
-    int endPos;
-    while ((endPos = find(separator, startPos)) != -1) {
+    unsigned startPos = 0;
+    size_t endPos;
+    while ((endPos = find(separator, startPos)) != notFound) {
         if (allowEmptyEntries || startPos != endPos)
             result.append(substring(startPos, endPos - startPos));
         startPos = endPos + separator.length();
     }
-    if (allowEmptyEntries || startPos != static_cast<int>(length()))
+    if (allowEmptyEntries || startPos != length())
         result.append(substring(startPos));
 }
 
 void String::split(const String& separator, Vector<String>& result) const
 {
-    return split(separator, false, result);
+    split(separator, false, result);
 }
 
 void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const
 {
     result.clear();
 
-    int startPos = 0;
-    int endPos;
-    while ((endPos = find(separator, startPos)) != -1) {
+    unsigned startPos = 0;
+    size_t endPos;
+    while ((endPos = find(separator, startPos)) != notFound) {
         if (allowEmptyEntries || startPos != endPos)
             result.append(substring(startPos, endPos - startPos));
         startPos = endPos + 1;
     }
-    if (allowEmptyEntries || startPos != static_cast<int>(length()))
+    if (allowEmptyEntries || startPos != length())
         result.append(substring(startPos));
 }
 
 void String::split(UChar separator, Vector<String>& result) const
 {
-    return split(String(&separator, 1), false, result);
+    split(String(&separator, 1), false, result);
 }
 
-Vector<char> String::ascii() const
+CString String::ascii() const
 {
-    if (m_impl) 
-        return m_impl->ascii();
-    
-    const char* nullMsg = "(null impl)";
-    Vector<char, 2048> buffer;
-    for (int i = 0; nullMsg[i]; ++i)
-        buffer.append(nullMsg[i]);
-    
-    buffer.append('\0');
-    return buffer;
+    // Printable ASCII characters 32..127 and the null character are
+    // preserved, characters outside of this range are converted to '?'.
+
+    unsigned length = this->length();
+    const UChar* characters = this->characters();
+
+    char* characterBuffer;
+    CString result = CString::newUninitialized(length, characterBuffer);
+
+    for (unsigned i = 0; i < length; ++i) {
+        UChar ch = characters[i];
+        characterBuffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch;
+    }
+
+    return result;
 }
 
 CString String::latin1() const
@@ -623,7 +650,7 @@ CString String::latin1() const
 
     for (unsigned i = 0; i < length; ++i) {
         UChar ch = characters[i];
-        characterBuffer[i] = ch > 255 ? '?' : ch;
+        characterBuffer[i] = ch > 0xff ? '?' : ch;
     }
 
     return result;
@@ -638,7 +665,7 @@ static inline void putUTF8Triple(char*& buffer, UChar ch)
     *buffer++ = static_cast<char>((ch & 0x3F) | 0x80);
 }
 
-CString String::utf8() const
+CString String::utf8(bool strict) const
 {
     unsigned length = this->length();
     const UChar* characters = this->characters();
@@ -658,16 +685,22 @@ CString String::utf8() const
     Vector<char, 1024> bufferVector(length * 3);
 
     char* buffer = bufferVector.data();
-    ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), false);
-    ASSERT(result != sourceIllegal); // Only produced from strict conversion.
+    ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict);
     ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion
 
-    // If a high surrogate is left unconverted, treat it the same was as an unpaired high surrogate
-    // would have been handled in the middle of a string with non-strict conversion - which is to say,
-    // simply encode it to UTF-8.
+    // Only produced from strict conversion.
+    if (result == sourceIllegal)
+        return CString();
+
+    // Check for an unconverted high surrogate.
     if (result == sourceExhausted) {
-        // This should be one unpaired high surrogate.
-        ASSERT((characters + 1) == (characters + length));
+        if (strict)
+            return CString();
+        // This should be one unpaired high surrogate. Treat it the same
+        // was as an unpaired high surrogate would have been handled in
+        // the middle of a string with non-strict conversion - which is
+        // to say, simply encode it to UTF-8.
+        ASSERT((characters + 1) == (this->characters() + length));
         ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF));
         // There should be room left, since one UChar hasn't been converted.
         ASSERT((buffer + 3) <= (buffer + bufferVector.size()));
@@ -887,11 +920,13 @@ intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok)
     return toIntegralType<intptr_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10);
 }
 
-double charactersToDouble(const UChar* data, size_t length, bool* ok)
+double charactersToDouble(const UChar* data, size_t length, bool* ok, bool* didReadNumber)
 {
     if (!length) {
         if (ok)
             *ok = false;
+        if (didReadNumber)
+            *didReadNumber = false;
         return 0.0;
     }
 
@@ -899,27 +934,64 @@ double charactersToDouble(const UChar* data, size_t length, bool* ok)
     for (unsigned i = 0; i < length; ++i)
         bytes[i] = data[i] < 0x7F ? data[i] : '?';
     bytes[length] = '\0';
+    char* start = bytes.data();
     char* end;
-    double val = WTF::strtod(bytes.data(), &end);
+    double val = WTF::strtod(start, &end);
     if (ok)
         *ok = (end == 0 || *end == '\0');
+    if (didReadNumber)
+        *didReadNumber = end - start;
     return val;
 }
 
-float charactersToFloat(const UChar* data, size_t length, bool* ok)
+float charactersToFloat(const UChar* data, size_t length, bool* ok, bool* didReadNumber)
 {
     // FIXME: This will return ok even when the string fits into a double but not a float.
-    return static_cast<float>(charactersToDouble(data, length, ok));
+    return static_cast<float>(charactersToDouble(data, length, ok, didReadNumber));
+}
+
+const String& emptyString()
+{
+    DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty()));
+    return emptyString;
 }
 
-} // namespace WebCore
+} // namespace WTF
 
 #ifndef NDEBUG
-// For use in the debugger - leaks memory
-WebCore::String* string(const char*);
+// For use in the debugger
+String* string(const char*);
+Vector<char> asciiDebug(StringImpl* impl);
+Vector<char> asciiDebug(String& string);
 
-WebCore::String* string(const char* s)
+String* string(const char* s)
 {
-    return new WebCore::String(s);
+    // leaks memory!
+    return new String(s);
 }
+
+Vector<char> asciiDebug(StringImpl* impl)
+{
+    if (!impl)
+        return asciiDebug(String("[null]").impl());
+
+    Vector<char> buffer;
+    unsigned length = impl->length();
+    const UChar* characters = impl->characters();
+
+    buffer.resize(length + 1);
+    for (unsigned i = 0; i < length; ++i) {
+        UChar ch = characters[i];
+        buffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch;
+    }
+    buffer[length] = '\0';
+
+    return buffer;
+}
+
+Vector<char> asciiDebug(String& string)
+{
+    return asciiDebug(string.impl());
+}
+
 #endif
index 493e793d3b1eb7c26548b7e81d08175f1e548a0d..71176b2b54b1e00ad3dddb4d95780bbb968faac5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * (C) 1999 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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
@@ -31,7 +31,7 @@
 #include <objc/objc.h>
 #endif
 
-#if PLATFORM(CF)
+#if USE(CF)
 typedef const struct __CFString * CFStringRef;
 #endif
 
@@ -50,21 +50,23 @@ class wxString;
 class BString;
 #endif
 
-namespace WTF {
-class CString;
-}
-using WTF::CString;
+#if PLATFORM(BREWMP)
+// AECHAR is defined in AEEStdDef.h, but don't include it here to avoid conflicts.
+#ifndef _AECHAR_DEFINED
+typedef uint16             AECHAR;
+#define _AECHAR_DEFINED
+#endif
+#endif
 
-// FIXME: This is a temporary layering violation while we move string code to WTF.
-// Landing the file moves in one patch, will follow on with patches to change the namespaces.
-namespace WebCore {
+namespace WTF {
 
-class SharedBuffer;
+class CString;
 struct StringHash;
 
 // Declarations of string operations
 
 bool charactersAreAllASCII(const UChar*, size_t);
+bool charactersAreAllLatin1(const UChar*, size_t);
 int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
 unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10);
 int64_t charactersToInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10);
@@ -77,48 +79,53 @@ int64_t charactersToInt64(const UChar*, size_t, bool* ok = 0); // ignores traili
 uint64_t charactersToUInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
 intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage
 
-double charactersToDouble(const UChar*, size_t, bool* ok = 0);
-float charactersToFloat(const UChar*, size_t, bool* ok = 0);
+double charactersToDouble(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
+float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0);
 
-int find(const UChar*, size_t, UChar, int startPosition = 0);
-int reverseFind(const UChar*, size_t, UChar, int startPosition = -1);
+template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters(const UChar*, size_t);
 
 class String {
 public:
-    String() { } // gives null string, distinguishable from an empty string
-    String(const UChar* str, unsigned len)
-    {
-        if (!str)
-            return;
-        m_impl = StringImpl::create(str, len);
-    }
-    String(const char* str)
-    {
-        if (!str)
-            return;
-        m_impl = StringImpl::create(str);
-    }
-    String(const char* str, unsigned length)
-    {
-        if (!str)
-            return;
-        m_impl = StringImpl::create(str, length);
-    }
-    String(const UChar*); // Specifically for null terminated UTF-16
-    String(StringImpl* i) : m_impl(i) { }
-    String(PassRefPtr<StringImpl> i) : m_impl(i) { }
-    String(RefPtr<StringImpl> i) : m_impl(i) { }
+    // Construct a null string, distinguishable from an empty string.
+    String() { }
 
-    void swap(String& o) { m_impl.swap(o.m_impl); }
+    // Construct a string with UTF-16 data.
+    String(const UChar* characters, unsigned length);
 
-    // Hash table deleted values, which are only constructed and never copied or destroyed.
-    String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
-    bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
+    // Construct a string by copying the contents of a vector.  To avoid
+    // copying, consider using String::adopt instead.
+    template<size_t inlineCapacity>
+    explicit String(const Vector<UChar, inlineCapacity>&);
+
+    // Construct a string with UTF-16 data, from a null-terminated source.
+    String(const UChar*);
+
+    // Construct a string with latin1 data.
+    String(const char* characters, unsigned length);
+
+    // Construct a string with latin1 data, from a null-terminated source.
+    String(const char* characters);
+
+    // Construct a string referencing an existing StringImpl.
+    String(StringImpl* impl) : m_impl(impl) { }
+    String(PassRefPtr<StringImpl> impl) : m_impl(impl) { }
+    String(RefPtr<StringImpl> impl) : m_impl(impl) { }
+
+    // Inline the destructor.
+    ALWAYS_INLINE ~String() { }
+
+    void swap(String& o) { m_impl.swap(o.m_impl); }
 
     static String adopt(StringBuffer& buffer) { return StringImpl::adopt(buffer); }
-    static String adopt(Vector<UChar>& vector) { return StringImpl::adopt(vector); }
+    template<size_t inlineCapacity>
+    static String adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); }
+
+    bool isNull() const { return !m_impl; }
+    bool isEmpty() const { return !m_impl || !m_impl->length(); }
 
-    ALWAYS_INLINE unsigned length() const
+    StringImpl* impl() const { return m_impl.get(); }
+
+    unsigned length() const
     {
         if (!m_impl)
             return 0;
@@ -132,34 +139,67 @@ public:
         return m_impl->characters();
     }
 
-    const UChar* charactersWithNullTermination();
-    
-    UChar operator[](unsigned i) const // if i >= length(), returns 0
+    CString ascii() const;
+    CString latin1() const;
+    CString utf8(bool strict = false) const;
+
+    UChar operator[](unsigned index) const
     {
-        if (!m_impl || i >= m_impl->length())
+        if (!m_impl || index >= m_impl->length())
             return 0;
-        return m_impl->characters()[i];
+        return m_impl->characters()[index];
     }
-    UChar32 characterStartingAt(unsigned) const; // Ditto.
+
+    static String number(short);
+    static String number(unsigned short);
+    static String number(int);
+    static String number(unsigned);
+    static String number(long);
+    static String number(unsigned long);
+    static String number(long long);
+    static String number(unsigned long long);
+    static String number(double);
+
+    // Find a single character or string, also with match function & latin1 forms.
+    size_t find(UChar c, unsigned start = 0) const
+        { return m_impl ? m_impl->find(c, start) : notFound; }
+    size_t find(const String& str, unsigned start = 0) const
+        { return m_impl ? m_impl->find(str.impl(), start) : notFound; }
+    size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const
+        { return m_impl ? m_impl->find(matchFunction, start) : notFound; }
+    size_t find(const char* str, unsigned start = 0) const
+        { return m_impl ? m_impl->find(str, start) : notFound; }
+
+    // Find the last instance of a single character or string.
+    size_t reverseFind(UChar c, unsigned start = UINT_MAX) const
+        { return m_impl ? m_impl->reverseFind(c, start) : notFound; }
+    size_t reverseFind(const String& str, unsigned start = UINT_MAX) const
+        { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; }
+
+    // Case insensitive string matching.
+    size_t findIgnoringCase(const char* str, unsigned start = 0) const
+        { return m_impl ? m_impl->findIgnoringCase(str, start) : notFound; }
+    size_t findIgnoringCase(const String& str, unsigned start = 0) const
+        { return m_impl ? m_impl->findIgnoringCase(str.impl(), start) : notFound; }
+    size_t reverseFindIgnoringCase(const String& str, unsigned start = UINT_MAX) const
+        { return m_impl ? m_impl->reverseFindIgnoringCase(str.impl(), start) : notFound; }
+
+    // Wrappers for find & reverseFind adding dynamic sensitivity check.
+    size_t find(const char* str, unsigned start, bool caseSensitive) const
+        { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); }
+    size_t find(const String& str, unsigned start, bool caseSensitive) const
+        { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); }
+    size_t reverseFind(const String& str, unsigned start, bool caseSensitive) const
+        { return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); }
+
+    const UChar* charactersWithNullTermination();
     
-    bool contains(UChar c) const { return find(c) != -1; }
-    bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; }
-    bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; }
-
-    int find(UChar c, int start = 0) const
-        { return m_impl ? m_impl->find(c, start) : -1; }
-    int find(CharacterMatchFunctionPtr matchFunction, int start = 0) const
-        { return m_impl ? m_impl->find(matchFunction, start) : -1; }
-    int find(const char* str, int start = 0, bool caseSensitive = true) const
-        { return m_impl ? m_impl->find(str, start, caseSensitive) : -1; }
-    int find(const String& str, int start = 0, bool caseSensitive = true) const
-        { return m_impl ? m_impl->find(str.impl(), start, caseSensitive) : -1; }
-
-    int reverseFind(UChar c, int start = -1) const
-        { return m_impl ? m_impl->reverseFind(c, start) : -1; }
-    int reverseFind(const String& str, int start = -1, bool caseSensitive = true) const
-        { return m_impl ? m_impl->reverseFind(str.impl(), start, caseSensitive) : -1; }
+    UChar32 characterStartingAt(unsigned) const; // Ditto.
     
+    bool contains(UChar c) const { return find(c) != notFound; }
+    bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
+    bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
+
     bool startsWith(const String& s, bool caseSensitive = true) const
         { return m_impl ? m_impl->startsWith(s.impl(), caseSensitive) : s.isEmpty(); }
     bool endsWith(const String& s, bool caseSensitive = true) const
@@ -179,12 +219,17 @@ public:
 
     void makeLower() { if (m_impl) m_impl = m_impl->lower(); }
     void makeUpper() { if (m_impl) m_impl = m_impl->upper(); }
-    void makeSecure(UChar aChar, bool last = true) { if (m_impl) m_impl = m_impl->secure(aChar, last); }
+    void makeSecure(UChar aChar, StringImpl::LastCharacterBehavior behavior = StringImpl::ObscureLastCharacter)
+    {
+        if (m_impl)
+            m_impl = m_impl->secure(aChar, behavior);
+    }
 
     void truncate(unsigned len);
     void remove(unsigned pos, int len = 1);
 
     String substring(unsigned pos, unsigned len = UINT_MAX) const;
+    String substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const;
     String left(unsigned len) const { return substring(0, len); }
     String right(unsigned len) const { return substring(length() - len, len); }
 
@@ -196,21 +241,16 @@ public:
     String simplifyWhiteSpace() const;
 
     String removeCharacters(CharacterMatchFunctionPtr) const;
+    template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters() const;
 
     // Return the string with case folded for case insensitive comparison.
     String foldCase() const;
 
-    static String number(short);
-    static String number(unsigned short);
-    static String number(int);
-    static String number(unsigned);
-    static String number(long);
-    static String number(unsigned long);
-    static String number(long long);
-    static String number(unsigned long long);
-    static String number(double);
-    
+#if !PLATFORM(QT)
     static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
+#else
+    static String format(const char *, ...);
+#endif
 
     // Returns an uninitialized string. The characters needs to be written
     // into the buffer returned in data before the returned string is used.
@@ -233,8 +273,8 @@ public:
     int64_t toInt64(bool* ok = 0) const;
     uint64_t toUInt64(bool* ok = 0) const;
     intptr_t toIntPtr(bool* ok = 0) const;
-    double toDouble(bool* ok = 0) const;
-    float toFloat(bool* ok = 0) const;
+    double toDouble(bool* ok = 0, bool* didReadNumber = 0) const;
+    float toFloat(bool* ok = 0, bool* didReadNumber = 0) const;
 
     bool percentage(int& percentage) const;
 
@@ -246,12 +286,14 @@ public:
     // to ever prefer copy() over plain old assignment.
     String threadsafeCopy() const;
 
-    bool isNull() const { return !m_impl; }
-    ALWAYS_INLINE bool isEmpty() const { return !m_impl || !m_impl->length(); }
-
-    StringImpl* impl() const { return m_impl.get(); }
+    // Prevent Strings from being implicitly convertable to bool as it will be ambiguous on any platform that
+    // allows implicit conversion to another pointer type (e.g., Mac allows implicit conversion to NSString*).
+    typedef struct ImplicitConversionFromWTFStringToBoolDisallowedA* (String::*UnspecifiedBoolTypeA);
+    typedef struct ImplicitConversionFromWTFStringToBoolDisallowedB* (String::*UnspecifiedBoolTypeB);
+    operator UnspecifiedBoolTypeA() const;
+    operator UnspecifiedBoolTypeB() const;
 
-#if PLATFORM(CF)
+#if USE(CF)
     String(CFStringRef);
     CFStringRef createCFString() const;
 #endif
@@ -280,11 +322,12 @@ public:
     operator BString() const;
 #endif
 
-    Vector<char> ascii() const;
-
-    CString latin1() const;
-    CString utf8() const;
+#if PLATFORM(BREWMP)
+    String(const AECHAR*);
+#endif
 
+    // String::fromUTF8 will return a null string if
+    // the input data contains invalid UTF-8 sequences.
     static String fromUTF8(const char*, size_t);
     static String fromUTF8(const char*);
 
@@ -292,9 +335,21 @@ public:
     static String fromUTF8WithLatin1Fallback(const char*, size_t);
     
     // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3.
-    WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; }
+    WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0) const
+    {
+        if (m_impl)
+            return m_impl->defaultWritingDirection(hasStrongDirectionality);
+        if (hasStrongDirectionality)
+            *hasStrongDirectionality = false;
+        return WTF::Unicode::LeftToRight;
+    }
 
     bool containsOnlyASCII() const { return charactersAreAllASCII(characters(), length()); }
+    bool containsOnlyLatin1() const { return charactersAreAllLatin1(characters(), length()); }
+
+    // Hash table deleted values, which are only constructed and never copied or destroyed.
+    String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { }
+    bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); }
 
 private:
     RefPtr<StringImpl> m_impl;
@@ -305,10 +360,6 @@ QDataStream& operator<<(QDataStream& stream, const String& str);
 QDataStream& operator>>(QDataStream& stream, String& str);
 #endif
 
-String operator+(const String&, const String&);
-String operator+(const String&, const char*);
-String operator+(const char*, const String&);
-
 inline String& operator+=(String& a, const String& b) { a.append(b); return a; }
 
 inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); }
@@ -330,12 +381,21 @@ inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ign
 
 inline bool equalIgnoringNullity(const String& a, const String& b) { return equalIgnoringNullity(a.impl(), b.impl()); }
 
+template<size_t inlineCapacity>
+inline bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, const String& b) { return equalIgnoringNullity(a, b.impl()); }
+
 inline bool operator!(const String& str) { return str.isNull(); }
 
 inline void swap(String& a, String& b) { a.swap(b); }
 
 // Definitions of string operations
 
+template<size_t inlineCapacity>
+String::String(const Vector<UChar, inlineCapacity>& vector)
+    : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : 0)
+{
+}
+
 #ifdef __OBJC__
 // This is for situations in WebKit where the long standing behavior has been
 // "nil if empty", so we try to maintain longstanding behavior for the sake of
@@ -351,43 +411,47 @@ inline bool charactersAreAllASCII(const UChar* characters, size_t length)
     return !(ored & 0xFF80);
 }
 
-inline int find(const UChar* characters, size_t length, UChar character, int startPosition)
+inline bool charactersAreAllLatin1(const UChar* characters, size_t length)
+{
+    UChar ored = 0;
+    for (size_t i = 0; i < length; ++i)
+        ored |= characters[i];
+    return !(ored & 0xFF00);
+}
+
+int codePointCompare(const String&, const String&);
+
+inline size_t find(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = 0)
 {
-    if (startPosition >= static_cast<int>(length))
-        return -1;
-    for (size_t i = startPosition; i < length; ++i) {
-        if (characters[i] == character)
-            return static_cast<int>(i);
+    while (index < length) {
+        if (characters[index] == matchCharacter)
+            return index;
+        ++index;
     }
-    return -1;
+    return notFound;
 }
 
-inline int find(const UChar* characters, size_t length, CharacterMatchFunctionPtr matchFunction, int startPosition)
+inline size_t find(const UChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0)
 {
-    if (startPosition >= static_cast<int>(length))
-        return -1;
-    for (size_t i = startPosition; i < length; ++i) {
-        if (matchFunction(characters[i]))
-            return static_cast<int>(i);
+    while (index < length) {
+        if (matchFunction(characters[index]))
+            return index;
+        ++index;
     }
-    return -1;
+    return notFound;
 }
 
-inline int reverseFind(const UChar* characters, size_t length, UChar character, int startPosition)
+inline size_t reverseFind(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = UINT_MAX)
 {
-    if (startPosition >= static_cast<int>(length) || !length)
-        return -1;
-    if (startPosition < 0)
-        startPosition += static_cast<int>(length);
-    while (true) {
-        if (characters[startPosition] == character)
-            return startPosition;
-        if (!startPosition)
-            return -1;
-        startPosition--;
+    if (!length)
+        return notFound;
+    if (index >= length)
+        index = length - 1;
+    while (characters[index] != matchCharacter) {
+        if (!index--)
+            return notFound;
     }
-    ASSERT_NOT_REACHED();
-    return -1;
+    return index;
 }
 
 inline void append(Vector<UChar>& vector, const String& string)
@@ -415,16 +479,58 @@ inline void appendNumber(Vector<UChar>& vector, unsigned char number)
     }
 }
 
-} // namespace WebCore
+template<bool isSpecialCharacter(UChar)> inline bool isAllSpecialCharacters(const UChar* characters, size_t length)
+{
+    for (size_t i = 0; i < length; ++i) {
+        if (!isSpecialCharacter(characters[i]))
+            return false;
+    }
+    return true;
+}
 
-namespace WTF {
+template<bool isSpecialCharacter(UChar)> inline bool String::isAllSpecialCharacters() const
+{
+    return WTF::isAllSpecialCharacters<isSpecialCharacter>(characters(), length());
+}
+
+// StringHash is the default hash for String
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<String> {
+    typedef StringHash Hash;
+};
+
+template <> struct VectorTraits<String> : SimpleClassVectorTraits { };
 
-    // StringHash is the default hash for String
-    template<typename T> struct DefaultHash;
-    template<> struct DefaultHash<WebCore::String> {
-        typedef WebCore::StringHash Hash;
-    };
+// Shared global empty string.
+const String& emptyString();
 
 }
 
+using WTF::CString;
+using WTF::String;
+using WTF::emptyString;
+using WTF::append;
+using WTF::appendNumber;
+using WTF::charactersAreAllASCII;
+using WTF::charactersAreAllLatin1;
+using WTF::charactersToIntStrict;
+using WTF::charactersToUIntStrict;
+using WTF::charactersToInt64Strict;
+using WTF::charactersToUInt64Strict;
+using WTF::charactersToIntPtrStrict;
+using WTF::charactersToInt;
+using WTF::charactersToUInt;
+using WTF::charactersToInt64;
+using WTF::charactersToUInt64;
+using WTF::charactersToIntPtr;
+using WTF::charactersToDouble;
+using WTF::charactersToFloat;
+using WTF::equal;
+using WTF::equalIgnoringCase;
+using WTF::find;
+using WTF::isAllSpecialCharacters;
+using WTF::isSpaceOrNewline;
+using WTF::reverseFind;
+
+#include "AtomicString.h"
 #endif
diff --git a/wtf/unicode/CharacterNames.h b/wtf/unicode/CharacterNames.h
new file mode 100644 (file)
index 0000000..c0c5818
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2007, 2009, 2010 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 COMPUTER, 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 COMPUTER, 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 CharacterNames_h
+#define CharacterNames_h
+
+#include "Unicode.h"
+
+namespace WTF {
+namespace Unicode {
+
+// Names here are taken from the Unicode standard.
+
+// Most of these are UChar constants, not UChar32, which makes them
+// more convenient for WebCore code that mostly uses UTF-16.
+
+const UChar32 aegeanWordSeparatorLine = 0x10100;
+const UChar32 aegeanWordSeparatorDot = 0x10101;
+const UChar blackCircle = 0x25CF;
+const UChar blackSquare = 0x25A0;
+const UChar blackUpPointingTriangle = 0x25B2;
+const UChar bullet = 0x2022;
+const UChar bullseye = 0x25CE;
+const UChar carriageReturn = 0x000D;
+const UChar combiningEnclosingKeycap = 0x20E3;
+const UChar ethiopicPrefaceColon = 0x1366;
+const UChar ethiopicWordspace = 0x1361;
+const UChar fisheye = 0x25C9;
+const UChar hebrewPunctuationGeresh = 0x05F3;
+const UChar hebrewPunctuationGershayim = 0x05F4;
+const UChar horizontalEllipsis = 0x2026;
+const UChar hyphen = 0x2010;
+const UChar hyphenMinus = 0x002D;
+const UChar ideographicComma = 0x3001;
+const UChar ideographicFullStop = 0x3002;
+const UChar ideographicSpace = 0x3000;
+const UChar leftDoubleQuotationMark = 0x201C;
+const UChar leftSingleQuotationMark = 0x2018;
+const UChar leftToRightEmbed = 0x202A;
+const UChar leftToRightMark = 0x200E;
+const UChar leftToRightOverride = 0x202D;
+const UChar minusSign = 0x2212;
+const UChar newlineCharacter = 0x000A;
+const UChar noBreakSpace = 0x00A0;
+const UChar objectReplacementCharacter = 0xFFFC;
+const UChar popDirectionalFormatting = 0x202C;
+const UChar replacementCharacter = 0xFFFD;
+const UChar rightDoubleQuotationMark = 0x201D;
+const UChar rightSingleQuotationMark = 0x2019;
+const UChar rightToLeftEmbed = 0x202B;
+const UChar rightToLeftMark = 0x200F;
+const UChar rightToLeftOverride = 0x202E;
+const UChar sesameDot = 0xFE45;
+const UChar softHyphen = 0x00AD;
+const UChar space = 0x0020;
+const UChar tibetanMarkIntersyllabicTsheg = 0x0F0B;
+const UChar tibetanMarkDelimiterTshegBstar = 0x0F0C;
+const UChar32 ugariticWordDivider = 0x1039F;
+const UChar whiteBullet = 0x25E6;
+const UChar whiteCircle = 0x25CB;
+const UChar whiteSesameDot = 0xFE46;
+const UChar whiteUpPointingTriangle = 0x25B3;
+const UChar yenSign = 0x00A5;
+const UChar zeroWidthJoiner = 0x200D;
+const UChar zeroWidthNonJoiner = 0x200C;
+const UChar zeroWidthSpace = 0x200B;
+const UChar zeroWidthNoBreakSpace = 0xFEFF;
+
+const UChar AppleLogo = 0xF8FF;
+const UChar BigDot = 0x25CF;
+
+} // namespace Unicode
+} // namespace WTF
+
+using WTF::Unicode::aegeanWordSeparatorLine;
+using WTF::Unicode::aegeanWordSeparatorDot;
+using WTF::Unicode::blackCircle;
+using WTF::Unicode::blackSquare;
+using WTF::Unicode::blackUpPointingTriangle;
+using WTF::Unicode::bullet;
+using WTF::Unicode::bullseye;
+using WTF::Unicode::carriageReturn;
+using WTF::Unicode::combiningEnclosingKeycap;
+using WTF::Unicode::ethiopicPrefaceColon;
+using WTF::Unicode::ethiopicWordspace;
+using WTF::Unicode::fisheye;
+using WTF::Unicode::hebrewPunctuationGeresh;
+using WTF::Unicode::hebrewPunctuationGershayim;
+using WTF::Unicode::horizontalEllipsis;
+using WTF::Unicode::hyphen;
+using WTF::Unicode::hyphenMinus;
+using WTF::Unicode::ideographicComma;
+using WTF::Unicode::ideographicFullStop;
+using WTF::Unicode::ideographicSpace;
+using WTF::Unicode::leftDoubleQuotationMark;
+using WTF::Unicode::leftSingleQuotationMark;
+using WTF::Unicode::leftToRightEmbed;
+using WTF::Unicode::leftToRightMark;
+using WTF::Unicode::leftToRightOverride;
+using WTF::Unicode::minusSign;
+using WTF::Unicode::newlineCharacter;
+using WTF::Unicode::noBreakSpace;
+using WTF::Unicode::objectReplacementCharacter;
+using WTF::Unicode::popDirectionalFormatting;
+using WTF::Unicode::replacementCharacter;
+using WTF::Unicode::rightDoubleQuotationMark;
+using WTF::Unicode::rightSingleQuotationMark;
+using WTF::Unicode::rightToLeftEmbed;
+using WTF::Unicode::rightToLeftMark;
+using WTF::Unicode::rightToLeftOverride;
+using WTF::Unicode::sesameDot;
+using WTF::Unicode::softHyphen;
+using WTF::Unicode::space;
+using WTF::Unicode::tibetanMarkIntersyllabicTsheg;
+using WTF::Unicode::tibetanMarkDelimiterTshegBstar;
+using WTF::Unicode::ugariticWordDivider;
+using WTF::Unicode::whiteBullet;
+using WTF::Unicode::whiteCircle;
+using WTF::Unicode::whiteSesameDot;
+using WTF::Unicode::whiteUpPointingTriangle;
+using WTF::Unicode::yenSign;
+using WTF::Unicode::zeroWidthJoiner;
+using WTF::Unicode::zeroWidthNonJoiner;
+using WTF::Unicode::zeroWidthSpace;
+using WTF::Unicode::zeroWidthNoBreakSpace;
+
+using WTF::Unicode::AppleLogo;
+using WTF::Unicode::BigDot;
+
+#endif // CharacterNames_h
index fe6a8096ce6adff570a1f54c6bc3096141f85b3c..00ab16e6a5bdba6ff14b5b371f1c914c1880382f 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef WTF_Collator_h
 #define WTF_Collator_h
 
+#include <wtf/FastAllocBase.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/unicode/Unicode.h>
@@ -39,7 +40,8 @@ struct UCollator;
 
 namespace WTF {
 
-    class Collator : public Noncopyable {
+    class Collator {
+        WTF_MAKE_NONCOPYABLE(Collator); WTF_MAKE_FAST_ALLOCATED;
     public:
         enum Result { Equal = 0, Greater = 1, Less = -1 };
 
index 4e05432243671f34bb00ffd0c81b3d65cd6f939e..7bde114a48bea1ab290992df116141d6ae34437e 100644 (file)
@@ -47,7 +47,7 @@ void Collator::setOrderLowerFirst(bool)
 
 PassOwnPtr<Collator> Collator::userDefault()
 {
-    return new Collator(0);
+    return adoptPtr(new Collator(0));
 }
 
 // A default implementation for platforms that lack Unicode-aware collation.
index 21d58563cc005ae61ac74f03966b57eec55d1027..3a88906567d0a33270983e2bcb64a59d9943b189 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include "config.h"
 #include "UTF8.h"
 
+#include "ASCIICType.h"
+#include <wtf/StringHasher.h>
+#include <wtf/unicode/CharacterNames.h>
+
 namespace WTF {
 namespace Unicode {
 
@@ -44,12 +49,12 @@ inline int inlineUTF8SequenceLengthNonASCII(char b0)
 
 inline int inlineUTF8SequenceLength(char b0)
 {
-    return (b0 & 0x80) == 0 ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
+    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
 }
 
 int UTF8SequenceLength(char b0)
 {
-    return (b0 & 0x80) == 0 ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
+    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
 }
 
 int decodeUTF8Sequence(const char* sequence)
@@ -172,7 +177,7 @@ ConversionResult convertUTF16ToUTF8(
             bytesToWrite = 4;
         } else {
             bytesToWrite = 3;
-            ch = 0xFFFD;
+            ch = replacementCharacter;
         }
 
         target += bytesToWrite;
@@ -231,6 +236,23 @@ static bool isLegalUTF8(const unsigned char* source, int length)
 static const UChar32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, 
             0x03C82080UL, 0xFA082080UL, 0x82082080UL };
 
+static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length)
+{
+    UChar32 character = 0;
+
+    // The cases all fall through.
+    switch (length) {
+        case 6: character += static_cast<unsigned char>(*sequence++); character <<= 6;
+        case 5: character += static_cast<unsigned char>(*sequence++); character <<= 6;
+        case 4: character += static_cast<unsigned char>(*sequence++); character <<= 6;
+        case 3: character += static_cast<unsigned char>(*sequence++); character <<= 6;
+        case 2: character += static_cast<unsigned char>(*sequence++); character <<= 6;
+        case 1: character += static_cast<unsigned char>(*sequence++);
+    }
+
+    return character - offsetsFromUTF8[length - 1];
+}
+
 ConversionResult convertUTF8ToUTF16(
     const char** sourceStart, const char* sourceEnd, 
     UChar** targetStart, UChar* targetEnd, bool strict)
@@ -239,60 +261,52 @@ ConversionResult convertUTF8ToUTF16(
     const char* source = *sourceStart;
     UChar* target = *targetStart;
     while (source < sourceEnd) {
-        UChar32 ch = 0;
-        int extraBytesToRead = UTF8SequenceLength(*source) - 1;
-        if (source + extraBytesToRead >= sourceEnd) {
+        int utf8SequenceLength = inlineUTF8SequenceLength(*source);
+        if (sourceEnd - source < utf8SequenceLength)  {
             result = sourceExhausted;
             break;
         }
         // Do this check whether lenient or strict
-        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), extraBytesToRead + 1)) {
+        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), utf8SequenceLength)) {
             result = sourceIllegal;
             break;
         }
-        // The cases all fall through.
-        switch (extraBytesToRead) {
-            case 5: ch += static_cast<unsigned char>(*source++); ch <<= 6; // remember, illegal UTF-8
-            case 4: ch += static_cast<unsigned char>(*source++); ch <<= 6; // remember, illegal UTF-8
-            case 3: ch += static_cast<unsigned char>(*source++); ch <<= 6;
-            case 2: ch += static_cast<unsigned char>(*source++); ch <<= 6;
-            case 1: ch += static_cast<unsigned char>(*source++); ch <<= 6;
-            case 0: ch += static_cast<unsigned char>(*source++);
-        }
-        ch -= offsetsFromUTF8[extraBytesToRead];
+
+        UChar32 character = readUTF8Sequence(source, utf8SequenceLength);
 
         if (target >= targetEnd) {
-            source -= (extraBytesToRead + 1); // Back up source pointer!
-            result = targetExhausted; break;
+            source -= utf8SequenceLength; // Back up source pointer!
+            result = targetExhausted;
+            break;
         }
-        if (ch <= 0xFFFF) {
+
+        if (U_IS_BMP(character)) {
             // UTF-16 surrogate values are illegal in UTF-32
-            if (ch >= 0xD800 && ch <= 0xDFFF) {
+            if (U_IS_SURROGATE(character)) {
                 if (strict) {
-                    source -= (extraBytesToRead + 1); // return to the illegal value itself
+                    source -= utf8SequenceLength; // return to the illegal value itself
                     result = sourceIllegal;
                     break;
                 } else
-                    *target++ = 0xFFFD;
+                    *target++ = replacementCharacter;
             } else
-                *target++ = (UChar)ch; // normal case
-        } else if (ch > 0x10FFFF) {
-            if (strict) {
-                result = sourceIllegal;
-                source -= (extraBytesToRead + 1); // return to the start
-                break; // Bail out; shouldn't continue
-            } else
-                *target++ = 0xFFFD;
-        } else {
+                *target++ = character; // normal case
+        } else if (U_IS_SUPPLEMENTARY(character)) {
             // target is a character in range 0xFFFF - 0x10FFFF
             if (target + 1 >= targetEnd) {
-                source -= (extraBytesToRead + 1); // Back up source pointer!
+                source -= utf8SequenceLength; // Back up source pointer!
                 result = targetExhausted;
                 break;
             }
-            ch -= 0x0010000UL;
-            *target++ = (UChar)((ch >> 10) + 0xD800);
-            *target++ = (UChar)((ch & 0x03FF) + 0xDC00);
+            *target++ = U16_LEAD(character);
+            *target++ = U16_TRAIL(character);
+        } else {
+            if (strict) {
+                source -= utf8SequenceLength; // return to the start
+                result = sourceIllegal;
+                break; // Bail out; shouldn't continue
+            } else
+                *target++ = replacementCharacter;
         }
     }
     *sourceStart = source;
@@ -300,5 +314,94 @@ ConversionResult convertUTF8ToUTF16(
     return result;
 }
 
+unsigned calculateStringHashAndLengthFromUTF8(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length)
+{
+    if (!data)
+        return 0;
+
+    StringHasher stringHasher;
+    dataLength = 0;
+    utf16Length = 0;
+
+    while (data < dataEnd || (!dataEnd && *data)) {
+        if (isASCII(*data)) {
+            stringHasher.addCharacter(*data++);
+            dataLength++;
+            utf16Length++;
+            continue;
+        }
+
+        int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*data);
+        dataLength += utf8SequenceLength;
+
+        if (!dataEnd) {
+            for (int i = 1; i < utf8SequenceLength; ++i) {
+                if (!data[i])
+                    return 0;
+            }
+        } else if (dataEnd - data < utf8SequenceLength)
+            return 0;
+
+        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(data), utf8SequenceLength))
+            return 0;
+
+        UChar32 character = readUTF8Sequence(data, utf8SequenceLength);
+        ASSERT(!isASCII(character));
+
+        if (U_IS_BMP(character)) {
+            // UTF-16 surrogate values are illegal in UTF-32
+            if (U_IS_SURROGATE(character))
+                return 0;
+            stringHasher.addCharacter(static_cast<UChar>(character)); // normal case
+            utf16Length++;
+        } else if (U_IS_SUPPLEMENTARY(character)) {
+            stringHasher.addCharacters(static_cast<UChar>(U16_LEAD(character)),
+                                       static_cast<UChar>(U16_TRAIL(character)));
+            utf16Length += 2;
+        } else
+            return 0;
+    }
+
+    return stringHasher.hash();
 }
+
+bool equalUTF16WithUTF8(const UChar* a, const UChar* aEnd, const char* b, const char* bEnd)
+{
+    while (b < bEnd) {
+        if (isASCII(*b)) {
+            if (*a++ != *b++)
+                return false;
+            continue;
+        }
+
+        int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*b);
+
+        if (bEnd - b < utf8SequenceLength)
+            return false;
+
+        if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(b), utf8SequenceLength))
+            return 0;
+
+        UChar32 character = readUTF8Sequence(b, utf8SequenceLength);
+        ASSERT(!isASCII(character));
+
+        if (U_IS_BMP(character)) {
+            // UTF-16 surrogate values are illegal in UTF-32
+            if (U_IS_SURROGATE(character))
+                return false;
+            if (*a++ != character)
+                return false;
+        } else if (U_IS_SUPPLEMENTARY(character)) {
+            if (*a++ != U16_LEAD(character))
+                return false;
+            if (*a++ != U16_TRAIL(character))
+                return false;
+        } else
+            return false;
+    }
+
+    return a == aEnd;
 }
+
+} // namespace Unicode
+} // namespace WTF
index a5ed93e94ddb871ad2ad419e7237619c3fd9624e..7b7b75d37cc3fc3781662d7fdd57594adf7130cf 100644 (file)
@@ -29,7 +29,7 @@
 #include "Unicode.h"
 
 namespace WTF {
-  namespace Unicode {
+namespace Unicode {
 
     // Given a first byte, gives the length of the UTF-8 sequence it begins.
     // Returns 0 for bytes that are not legal starts of UTF-8 sequences.
@@ -69,7 +69,12 @@ namespace WTF {
     ConversionResult convertUTF16ToUTF8(
                     const UChar** sourceStart, const UChar* sourceEnd, 
                     char** targetStart, char* targetEnd, bool strict = true);
-  }
-}
+
+    unsigned calculateStringHashAndLengthFromUTF8(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length);
+
+    bool equalUTF16WithUTF8(const UChar* a, const UChar* aEnd, const char* b, const char* bEnd);
+
+} // namespace Unicode
+} // namespace WTF
 
 #endif // WTF_UTF8_h
index d59439dc83634184801acd26f8f54584b03024a9..50524b12650ce2ba70af94fbd86c95ff91d16934 100644 (file)
@@ -32,7 +32,9 @@
 #elif USE(GLIB_UNICODE)
 #include <wtf/unicode/glib/UnicodeGLib.h>
 #elif USE(WINCE_UNICODE)
-#include <wtf/unicode/wince/UnicodeWince.h>
+#include <wtf/unicode/wince/UnicodeWinCE.h>
+#elif USE(BREWMP_UNICODE)
+#include <wtf/unicode/brew/UnicodeBrew.h>
 #else
 #error "Unknown Unicode implementation"
 #endif
diff --git a/wtf/unicode/UnicodeMacrosFromICU.h b/wtf/unicode/UnicodeMacrosFromICU.h
new file mode 100644 (file)
index 0000000..09a7036
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (C) 1999-2004, International Business Machines Corporation and others.  All Rights Reserved.
+ *
+ */
+
+#ifndef UnicodeMacrosFromICU_h
+#define UnicodeMacrosFromICU_h
+
+// some defines from ICU
+
+#define U_IS_BMP(c) ((UChar32)(c)<=0xffff)
+#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
+#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
+#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
+#define U16_GET_SUPPLEMENTARY(lead, trail) \
+    (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET)
+
+#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
+#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
+#define U16_LENGTH(c) ((uint32_t)(c) <= 0xffff ? 1 : 2)
+
+#define U_IS_SUPPLEMENTARY(c) ((UChar32)((c)-0x10000)<=0xfffff)
+#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
+#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c)
+#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
+#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
+
+#define U16_GET(s, start, i, length, c) { \
+    (c)=(s)[i]; \
+    if(U16_IS_SURROGATE(c)) { \
+        uint16_t __c2; \
+        if(U16_IS_SURROGATE_LEAD(c)) { \
+            if((i)+1<(length) && U16_IS_TRAIL(__c2=(s)[(i)+1])) { \
+                (c)=U16_GET_SUPPLEMENTARY((c), __c2); \
+            } \
+        } else { \
+            if((i)-1>=(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \
+                (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
+            } \
+        } \
+    } \
+}
+
+#define U16_PREV(s, start, i, c) { \
+    (c)=(s)[--(i)]; \
+    if(U16_IS_TRAIL(c)) { \
+        uint16_t __c2; \
+        if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \
+            --(i); \
+            (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
+        } \
+    } \
+}
+
+#define U16_BACK_1(s, start, i) { \
+    if(U16_IS_TRAIL((s)[--(i)]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \
+        --(i); \
+    } \
+}
+
+#define U16_NEXT(s, i, length, c) { \
+    (c)=(s)[(i)++]; \
+    if(U16_IS_LEAD(c)) { \
+        uint16_t __c2; \
+        if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
+            ++(i); \
+            (c)=U16_GET_SUPPLEMENTARY((c), __c2); \
+        } \
+    } \
+}
+
+#define U16_FWD_1(s, i, length) { \
+    if(U16_IS_LEAD((s)[(i)++]) && (i)<(length) && U16_IS_TRAIL((s)[i])) { \
+        ++(i); \
+    } \
+}
+
+#define U_MASK(x) ((uint32_t)1<<(x))
+
+#define U8_MAX_LENGTH 4
+
+#define U8_APPEND_UNSAFE(s, i, c) { \
+    if((uint32_t)(c)<=0x7f) { \
+        (s)[(i)++]=(uint8_t)(c); \
+    } else { \
+        if((uint32_t)(c)<=0x7ff) { \
+            (s)[(i)++]=(uint8_t)(((c)>>6)|0xc0); \
+        } else { \
+            if((uint32_t)(c)<=0xffff) { \
+                (s)[(i)++]=(uint8_t)(((c)>>12)|0xe0); \
+            } else { \
+                (s)[(i)++]=(uint8_t)(((c)>>18)|0xf0); \
+                (s)[(i)++]=(uint8_t)((((c)>>12)&0x3f)|0x80); \
+            } \
+            (s)[(i)++]=(uint8_t)((((c)>>6)&0x3f)|0x80); \
+        } \
+        (s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \
+    } \
+}
+#endif
diff --git a/wtf/unicode/brew/UnicodeBrew.cpp b/wtf/unicode/brew/UnicodeBrew.cpp
new file mode 100644 (file)
index 0000000..8367f17
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (C) 2006 George Staikos <staikos@kde.org>
+ *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *  Copyright (C) 2010 Company 100, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "UnicodeBrew.h"
+
+#include <wchar.h>
+#include <wctype.h>
+
+namespace WTF {
+namespace Unicode {
+
+UChar toLower(UChar c)
+{
+    return towlower(c);
+}
+
+UChar toUpper(UChar c)
+{
+    return towupper(c);
+}
+
+UChar foldCase(UChar c)
+{
+    return towlower(c);
+}
+
+bool isPrintableChar(UChar c)
+{
+    return !!iswprint(c);
+}
+
+bool isUpper(UChar c)
+{
+    return !!iswupper(c);
+}
+
+bool isLower(UChar c)
+{
+    return !!iswlower(c);
+}
+
+bool isDigit(UChar c)
+{
+    return !!iswdigit(c);
+}
+
+bool isPunct(UChar c)
+{
+    return !!iswpunct(c);
+}
+
+bool isAlphanumeric(UChar c)
+{
+    return !!iswalnum(c);
+}
+
+int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError)
+{
+    const UChar* sourceIterator = source;
+    const UChar* sourceEnd = source + sourceLength;
+    UChar* resultIterator = result;
+    UChar* resultEnd = result + resultLength;
+
+    if (sourceLength <= resultLength) {
+        while (sourceIterator < sourceEnd)
+            *resultIterator++ = towlower(*sourceIterator++);
+    } else {
+        while (resultIterator < resultEnd)
+            *resultIterator++ = towlower(*sourceIterator++);
+    }
+
+    int remainingCharacters = sourceIterator < sourceEnd ? sourceEnd - sourceIterator : 0;
+    *isError = !!remainingCharacters;
+    if (resultIterator < resultEnd)
+        *resultIterator = 0;
+
+    return (resultIterator - result) + remainingCharacters;
+}
+
+int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError)
+{
+    const UChar* sourceIterator = source;
+    const UChar* sourceEnd = source + sourceLength;
+    UChar* resultIterator = result;
+    UChar* resultEnd = result + resultLength;
+
+    if (sourceLength <= resultLength) {
+        while (sourceIterator < sourceEnd)
+            *resultIterator++ = towupper(*sourceIterator++);
+    } else {
+        while (resultIterator < resultEnd)
+            *resultIterator++ = towupper(*sourceIterator++);
+    }
+
+    int remainingCharacters = sourceIterator < sourceEnd ? sourceEnd - sourceIterator : 0;
+    *isError = !!remainingCharacters;
+    if (resultIterator < resultEnd)
+        *resultIterator = 0;
+
+    return (resultIterator - result) + remainingCharacters;
+}
+
+int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError)
+{
+    *isError = false;
+    if (resultLength < sourceLength) {
+        *isError = true;
+        return sourceLength;
+    }
+    for (int i = 0; i < sourceLength; ++i)
+        result[i] = foldCase(source[i]);
+    return sourceLength;
+}
+
+UChar toTitleCase(UChar c)
+{
+    return towupper(c);
+}
+
+Direction direction(UChar32 c)
+{
+    return static_cast<Direction>(ICU::direction(c));
+}
+
+CharCategory category(unsigned int c)
+{
+    return static_cast<CharCategory>(TO_MASK((int8_t) ICU::category(c)));
+}
+
+DecompositionType decompositionType(UChar32 c)
+{
+    return static_cast<DecompositionType>(ICU::decompositionType(c));
+}
+
+unsigned char combiningClass(UChar32 c)
+{
+    return ICU::combiningClass(c);
+}
+
+UChar mirroredChar(UChar32 c)
+{
+    return ICU::mirroredChar(c);
+}
+
+int digitValue(UChar c)
+{
+    return ICU::digitValue(c);
+}
+
+bool isSpace(UChar c)
+{
+    return !!iswspace(c);
+}
+
+bool isLetter(UChar c)
+{
+    return !!iswalpha(c);
+}
+
+} // namespace Unicode
+} // namespace WTF
diff --git a/wtf/unicode/brew/UnicodeBrew.h b/wtf/unicode/brew/UnicodeBrew.h
new file mode 100644 (file)
index 0000000..1d7576f
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ *  Copyright (C) 2006 George Staikos <staikos@kde.org>
+ *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ *  Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *  Copyright (C) 2010 Company 100, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef UnicodeBrew_h
+#define UnicodeBrew_h
+
+#include "UnicodeFromICU.h"
+#include "UnicodeMacrosFromICU.h"
+
+namespace WTF {
+namespace Unicode {
+
+enum Direction {
+    LeftToRight = ICU::U_LEFT_TO_RIGHT,
+    RightToLeft = ICU::U_RIGHT_TO_LEFT,
+    EuropeanNumber = ICU::U_EUROPEAN_NUMBER,
+    EuropeanNumberSeparator = ICU::U_EUROPEAN_NUMBER_SEPARATOR,
+    EuropeanNumberTerminator = ICU::U_EUROPEAN_NUMBER_TERMINATOR,
+    ArabicNumber = ICU::U_ARABIC_NUMBER,
+    CommonNumberSeparator = ICU::U_COMMON_NUMBER_SEPARATOR,
+    BlockSeparator = ICU::U_BLOCK_SEPARATOR,
+    SegmentSeparator = ICU::U_SEGMENT_SEPARATOR,
+    WhiteSpaceNeutral = ICU::U_WHITE_SPACE_NEUTRAL,
+    OtherNeutral = ICU::U_OTHER_NEUTRAL,
+    LeftToRightEmbedding = ICU::U_LEFT_TO_RIGHT_EMBEDDING,
+    LeftToRightOverride = ICU::U_LEFT_TO_RIGHT_OVERRIDE,
+    RightToLeftArabic = ICU::U_RIGHT_TO_LEFT_ARABIC,
+    RightToLeftEmbedding = ICU::U_RIGHT_TO_LEFT_EMBEDDING,
+    RightToLeftOverride = ICU::U_RIGHT_TO_LEFT_OVERRIDE,
+    PopDirectionalFormat = ICU::U_POP_DIRECTIONAL_FORMAT,
+    NonSpacingMark = ICU::U_DIR_NON_SPACING_MARK,
+    BoundaryNeutral = ICU::U_BOUNDARY_NEUTRAL
+};
+
+enum DecompositionType {
+    DecompositionNone = ICU::U_DT_NONE,
+    DecompositionCanonical = ICU::U_DT_CANONICAL,
+    DecompositionCompat = ICU::U_DT_COMPAT,
+    DecompositionCircle = ICU::U_DT_CIRCLE,
+    DecompositionFinal = ICU::U_DT_FINAL,
+    DecompositionFont = ICU::U_DT_FONT,
+    DecompositionFraction = ICU::U_DT_FRACTION,
+    DecompositionInitial = ICU::U_DT_INITIAL,
+    DecompositionIsolated = ICU::U_DT_ISOLATED,
+    DecompositionMedial = ICU::U_DT_MEDIAL,
+    DecompositionNarrow = ICU::U_DT_NARROW,
+    DecompositionNoBreak = ICU::U_DT_NOBREAK,
+    DecompositionSmall = ICU::U_DT_SMALL,
+    DecompositionSquare = ICU::U_DT_SQUARE,
+    DecompositionSub = ICU::U_DT_SUB,
+    DecompositionSuper = ICU::U_DT_SUPER,
+    DecompositionVertical = ICU::U_DT_VERTICAL,
+    DecompositionWide = ICU::U_DT_WIDE,
+};
+
+enum CharCategory {
+    NoCategory =  0,
+    Other_NotAssigned = TO_MASK(ICU::U_GENERAL_OTHER_TYPES),
+    Letter_Uppercase = TO_MASK(ICU::U_UPPERCASE_LETTER),
+    Letter_Lowercase = TO_MASK(ICU::U_LOWERCASE_LETTER),
+    Letter_Titlecase = TO_MASK(ICU::U_TITLECASE_LETTER),
+    Letter_Modifier = TO_MASK(ICU::U_MODIFIER_LETTER),
+    Letter_Other = TO_MASK(ICU::U_OTHER_LETTER),
+
+    Mark_NonSpacing = TO_MASK(ICU::U_NON_SPACING_MARK),
+    Mark_Enclosing = TO_MASK(ICU::U_ENCLOSING_MARK),
+    Mark_SpacingCombining = TO_MASK(ICU::U_COMBINING_SPACING_MARK),
+
+    Number_DecimalDigit = TO_MASK(ICU::U_DECIMAL_DIGIT_NUMBER),
+    Number_Letter = TO_MASK(ICU::U_LETTER_NUMBER),
+    Number_Other = TO_MASK(ICU::U_OTHER_NUMBER),
+
+    Separator_Space = TO_MASK(ICU::U_SPACE_SEPARATOR),
+    Separator_Line = TO_MASK(ICU::U_LINE_SEPARATOR),
+    Separator_Paragraph = TO_MASK(ICU::U_PARAGRAPH_SEPARATOR),
+
+    Other_Control = TO_MASK(ICU::U_CONTROL_CHAR),
+    Other_Format = TO_MASK(ICU::U_FORMAT_CHAR),
+    Other_PrivateUse = TO_MASK(ICU::U_PRIVATE_USE_CHAR),
+    Other_Surrogate = TO_MASK(ICU::U_SURROGATE),
+
+    Punctuation_Dash = TO_MASK(ICU::U_DASH_PUNCTUATION),
+    Punctuation_Open = TO_MASK(ICU::U_START_PUNCTUATION),
+    Punctuation_Close = TO_MASK(ICU::U_END_PUNCTUATION),
+    Punctuation_Connector = TO_MASK(ICU::U_CONNECTOR_PUNCTUATION),
+    Punctuation_Other = TO_MASK(ICU::U_OTHER_PUNCTUATION),
+
+    Symbol_Math = TO_MASK(ICU::U_MATH_SYMBOL),
+    Symbol_Currency = TO_MASK(ICU::U_CURRENCY_SYMBOL),
+    Symbol_Modifier = TO_MASK(ICU::U_MODIFIER_SYMBOL),
+    Symbol_Other = TO_MASK(ICU::U_OTHER_SYMBOL),
+
+    Punctuation_InitialQuote = TO_MASK(ICU::U_INITIAL_PUNCTUATION),
+    Punctuation_FinalQuote = TO_MASK(ICU::U_FINAL_PUNCTUATION)
+};
+
+UChar foldCase(UChar);
+
+int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError);
+
+int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError);
+
+UChar toUpper(UChar);
+UChar toLower(UChar);
+
+bool isUpper(UChar);
+
+int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError);
+
+UChar toTitleCase(UChar);
+
+inline bool isArabicChar(UChar32 c)
+{
+    return c >= 0x0600 && c <= 0x06FF;
+}
+
+bool isAlphanumeric(UChar);
+
+CharCategory category(unsigned int);
+
+inline bool isSeparatorSpace(UChar c)
+{
+    return category(c) == Separator_Space;
+}
+
+bool isPrintableChar(UChar);
+
+bool isDigit(UChar);
+
+bool isPunct(UChar);
+
+inline bool hasLineBreakingPropertyComplexContext(UChar32)
+{
+    // FIXME: implement!
+    return false;
+}
+
+inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c)
+{
+    // FIXME
+    return false;
+}
+
+UChar mirroredChar(UChar32);
+
+Direction direction(UChar32);
+
+bool isLower(UChar);
+
+int digitValue(UChar);
+
+unsigned char combiningClass(UChar32);
+
+DecompositionType decompositionType(UChar32);
+
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+    for (int i = 0; i < len; ++i) {
+        UChar c1 = foldCase(a[i]);
+        UChar c2 = foldCase(b[i]);
+        if (c1 != c2)
+            return c1 - c2;
+    }
+    return 0;
+}
+
+bool isSpace(UChar);
+bool isLetter(UChar);
+
+} // namespace Unicode
+} // namespace WTF
+
+#endif
index e20c376e4404fcd29d31d95da22a6f257b17f25c..a01c3ee9db57cb43b890a2e663a376eb54061088 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2008 Jürg Billeter <j@bitron.ch>
  *  Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com>
+ *  Copyright (C) 2010 Igalia S.L.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
 #include "config.h"
 #include "UnicodeGLib.h"
 
+#include <wtf/Vector.h>
+#include <wtf/unicode/UTF8.h>
+
+#define UTF8_IS_SURROGATE(character) (character >= 0x10000 && character <= 0x10FFFF)
+
 namespace WTF {
 namespace Unicode {
 
@@ -43,100 +49,71 @@ UChar32 foldCase(UChar32 ch)
     return *ucs4Result;
 }
 
-int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+static int getUTF16LengthFromUTF8(const gchar* utf8String, int length)
 {
-    *error = false;
-    GOwnPtr<GError> gerror;
+    int utf16Length = 0;
+    const gchar* inputString = utf8String;
 
-    GOwnPtr<char> utf8src;
-    utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
-    }
-
-    GOwnPtr<char> utf8result;
-    utf8result.set(g_utf8_casefold(utf8src.get(), -1));
+    while ((utf8String + length - inputString > 0) && *inputString) {
+        gunichar character = g_utf8_get_char(inputString);
 
-    long utf16resultLength = -1;
-    GOwnPtr<UChar> utf16result;
-    utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
+        utf16Length += UTF8_IS_SURROGATE(character) ? 2 : 1;
+        inputString = g_utf8_next_char(inputString);
     }
 
-    if (utf16resultLength > resultLength) {
-        *error = true;
-        return utf16resultLength;
-    }
-    memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
-
-    return utf16resultLength;
+    return utf16Length;
 }
 
-int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+typedef gchar* (*UTF8CaseFunction)(const gchar*, gssize length);
+
+static int convertCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error, UTF8CaseFunction caseFunction)
 {
     *error = false;
-    GOwnPtr<GError> gerror;
 
-    GOwnPtr<char> utf8src;
-    utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
-    if (gerror) {
+    // Allocate a buffer big enough to hold all the characters.
+    Vector<char> buffer(srcLength * 3);
+    char* utf8Target = buffer.data();
+    const UChar* utf16Source = src;
+    ConversionResult conversionResult = convertUTF16ToUTF8(&utf16Source, utf16Source + srcLength, &utf8Target, utf8Target + buffer.size(), true);
+    if (conversionResult != conversionOK) {
         *error = true;
         return -1;
     }
+    buffer.shrink(utf8Target - buffer.data());
 
-    GOwnPtr<char> utf8result;
-    utf8result.set(g_utf8_strdown(utf8src.get(), -1));
+    GOwnPtr<char> utf8Result(caseFunction(buffer.data(), buffer.size()));
+    long utf8ResultLength = strlen(utf8Result.get());
 
-    long utf16resultLength = -1;
-    GOwnPtr<UChar> utf16result;
-    utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
-    if (gerror) {
+    // Calculate the destination buffer size.
+    int realLength = getUTF16LengthFromUTF8(utf8Result.get(), utf8ResultLength);
+    if (realLength > resultLength) {
         *error = true;
-        return -1;
+        return realLength;
     }
 
-    if (utf16resultLength > resultLength) {
+    // Convert the result to UTF-16.
+    UChar* utf16Target = result;
+    const char* utf8Source = utf8Result.get();
+    conversionResult = convertUTF8ToUTF16(&utf8Source, utf8Source + utf8ResultLength, &utf16Target, utf16Target + resultLength, true);
+    long utf16ResultLength = utf16Target - result;
+    if (conversionResult != conversionOK)
         *error = true;
-        return utf16resultLength;
-    }
-    memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
 
-    return utf16resultLength;
+    return utf16ResultLength <= 0 ? -1 : utf16ResultLength;
 }
-
-int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
 {
-    *error = false;
-    GOwnPtr<GError> gerror;
-
-    GOwnPtr<char> utf8src;
-    utf8src.set(g_utf16_to_utf8(src, srcLength, 0, 0, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
-    }
-
-    GOwnPtr<char> utf8result;
-    utf8result.set(g_utf8_strup(utf8src.get(), -1));
-
-    long utf16resultLength = -1;
-    GOwnPtr<UChar> utf16result;
-    utf16result.set(g_utf8_to_utf16(utf8result.get(), -1, 0, &utf16resultLength, &gerror.outPtr()));
-    if (gerror) {
-        *error = true;
-        return -1;
-    }
+    return convertCase(result, resultLength, src, srcLength, error, g_utf8_casefold);
+}
 
-    if (utf16resultLength > resultLength) {
-        *error = true;
-        return utf16resultLength;
-    }
-    memcpy(result, utf16result.get(), utf16resultLength * sizeof(UChar));
+int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+    return convertCase(result, resultLength, src, srcLength, error, g_utf8_strdown);
+}
 
-    return utf16resultLength;
+int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error)
+{
+    return convertCase(result, resultLength, src, srcLength, error, g_utf8_strup);
 }
 
 Direction direction(UChar32 c)
diff --git a/wtf/unicode/glib/UnicodeMacrosFromICU.h b/wtf/unicode/glib/UnicodeMacrosFromICU.h
deleted file mode 100644 (file)
index 5d3eca6..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  Copyright (C) 2006 George Staikos <staikos@kde.org>
- *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- *  Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
- *  Copyright (C) 2008 Jürg Billeter <j@bitron.ch>
- *  Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com>
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef UnicodeMacrosFromICU_h
-#define UnicodeMacrosFromICU_h
-
-// some defines from ICU
-
-#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
-#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
-#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
-#define U16_GET_SUPPLEMENTARY(lead, trail) \
-    (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET)
-
-#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
-#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
-
-#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
-#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c)
-#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
-#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
-
-#define U16_PREV(s, start, i, c) { \
-    (c)=(s)[--(i)]; \
-    if(U16_IS_TRAIL(c)) { \
-        uint16_t __c2; \
-        if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \
-            --(i); \
-            (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
-        } \
-    } \
-}
-
-#define U16_NEXT(s, i, length, c) { \
-    (c)=(s)[(i)++]; \
-    if(U16_IS_LEAD(c)) { \
-        uint16_t __c2; \
-        if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
-            ++(i); \
-            (c)=U16_GET_SUPPLEMENTARY((c), __c2); \
-        } \
-    } \
-}
-
-#define U_MASK(x) ((uint32_t)1<<(x))
-
-#endif
-
index ecab5bdc37642fbf89b8a65643f15f9b0f351be7..348693f4d940fabf6595e14a58dcd993d4f7bca7 100644 (file)
@@ -59,9 +59,9 @@ Collator::Collator(const char* locale)
 
 PassOwnPtr<Collator> Collator::userDefault()
 {
-#if OS(DARWIN) && PLATFORM(CF)
+#if OS(DARWIN) && USE(CF)
     // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work.
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !OS(IPHONE_OS)
+#if !defined(BUILDING_ON_LEOPARD) && !OS(IOS)
     RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent());
     CFStringRef collationOrder = (CFStringRef)CFLocaleGetValue(currentLocale.get(), kCFLocaleCollatorIdentifier);
 #else
@@ -69,13 +69,12 @@ PassOwnPtr<Collator> Collator::userDefault()
     CFStringRef collationOrder = collationOrderRetainer.get();
 #endif
     char buf[256];
-    if (collationOrder) {
-        CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
-        return new Collator(buf);
-    } else
-        return new Collator("");
+    if (!collationOrder)
+        return adoptPtr(new Collator(""));
+    CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII);
+    return adoptPtr(new Collator(buf));
 #else
-    return new Collator(0);
+    return adoptPtr(new Collator(0));
 #endif
 }
 
index 97c42b7bb810b9146a32963a2f4211d271cc0112..eaa7a0783d81e4c9bee83d5ce3302dc10d12d805 100644 (file)
 #ifndef WTF_UNICODE_QT4_H
 #define WTF_UNICODE_QT4_H
 
+#include "UnicodeMacrosFromICU.h"
+
 #include <QChar>
 #include <QString>
 
 #include <config.h>
 
 #include <stdint.h>
+#if USE(QT_ICU_TEXT_BREAKING)
+#include <unicode/ubrk.h>
+#endif
 
 QT_BEGIN_NAMESPACE
 namespace QUnicodeTables {
@@ -56,52 +61,15 @@ namespace QUnicodeTables {
 QT_END_NAMESPACE
 
 // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h
-#if defined(Q_OS_WIN) || COMPILER(WINSCW) || (COMPILER(RVCT) && OS(SYMBIAN))
+#if defined(Q_OS_WIN) || COMPILER(WINSCW) || (COMPILER(RVCT) && !OS(LINUX))
 typedef wchar_t UChar;
 #else
 typedef uint16_t UChar;
 #endif
-typedef uint32_t UChar32;
-
-// some defines from ICU
-
-#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
-#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
-#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
-#define U16_GET_SUPPLEMENTARY(lead, trail) \
-    (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET)
-
-#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
-#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
-
-#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
-#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c)
-#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
-#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0)
-
-#define U16_NEXT(s, i, length, c) { \
-    (c)=(s)[(i)++]; \
-    if(U16_IS_LEAD(c)) { \
-        uint16_t __c2; \
-        if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \
-            ++(i); \
-            (c)=U16_GET_SUPPLEMENTARY((c), __c2); \
-        } \
-    } \
-}
 
-#define U16_PREV(s, start, i, c) { \
-    (c)=(s)[--(i)]; \
-    if(U16_IS_TRAIL(c)) { \
-        uint16_t __c2; \
-        if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \
-            --(i); \
-            (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
-        } \
-    } \
-}
-
-#define U_MASK(x) ((uint32_t)1<<(x))
+#if !USE(QT_ICU_TEXT_BREAKING)
+typedef uint32_t UChar32;
+#endif
 
 namespace WTF {
 namespace Unicode {
@@ -188,7 +156,7 @@ enum CharCategory {
 
 inline UChar32 toLower(UChar32 ch)
 {
-    return QChar::toLower(ch);
+    return QChar::toLower(uint32_t(ch));
 }
 
 inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
@@ -244,9 +212,9 @@ inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLen
     return rindex + needed;
 }
 
-inline UChar32 toUpper(UChar32 ch)
+inline UChar32 toUpper(UChar32 c)
 {
-    return QChar::toUpper(ch);
+    return QChar::toUpper(uint32_t(c));
 }
 
 inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
@@ -304,12 +272,12 @@ inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLen
 
 inline int toTitleCase(UChar32 c)
 {
-    return QChar::toTitleCase(c);
+    return QChar::toTitleCase(uint32_t(c));
 }
 
 inline UChar32 foldCase(UChar32 c)
 {
-    return QChar::toCaseFolded(c);
+    return QChar::toCaseFolded(uint32_t(c));
 }
 
 inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength,  bool* error)
@@ -334,12 +302,12 @@ inline bool isPrintableChar(UChar32 c)
 {
     const uint test = U_MASK(QChar::Other_Control) |
                       U_MASK(QChar::Other_NotAssigned);
-    return !(U_MASK(QChar::category(c)) & test);
+    return !(U_MASK(QChar::category(uint32_t(c))) & test);
 }
 
 inline bool isSeparatorSpace(UChar32 c)
 {
-    return QChar::category(c) == QChar::Separator_Space;
+    return QChar::category(uint32_t(c)) == QChar::Separator_Space;
 }
 
 inline bool isPunct(UChar32 c)
@@ -351,12 +319,12 @@ inline bool isPunct(UChar32 c)
                       U_MASK(QChar::Punctuation_InitialQuote) |
                       U_MASK(QChar::Punctuation_FinalQuote) |
                       U_MASK(QChar::Punctuation_Other);
-    return U_MASK(QChar::category(c)) & test;
+    return U_MASK(QChar::category(uint32_t(c))) & test;
 }
 
 inline bool isLower(UChar32 c)
 {
-    return QChar::category(c) == QChar::Letter_Lowercase;
+    return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase;
 }
 
 inline bool hasLineBreakingPropertyComplexContext(UChar32)
@@ -367,12 +335,12 @@ inline bool hasLineBreakingPropertyComplexContext(UChar32)
 
 inline UChar32 mirroredChar(UChar32 c)
 {
-    return QChar::mirroredChar(c);
+    return QChar::mirroredChar(uint32_t(c));
 }
 
 inline uint8_t combiningClass(UChar32 c)
 {
-    return QChar::combiningClass(c);
+    return QChar::combiningClass(uint32_t(c));
 }
 
 inline DecompositionType decompositionType(UChar32 c)
@@ -394,12 +362,12 @@ inline int umemcasecmp(const UChar* a, const UChar* b, int len)
 
 inline Direction direction(UChar32 c)
 {
-    return (Direction)QChar::direction(c);
+    return (Direction)QChar::direction(uint32_t(c));
 }
 
 inline CharCategory category(UChar32 c)
 {
-    return (CharCategory) U_MASK(QChar::category(c));
+    return (CharCategory) U_MASK(QChar::category(uint32_t(c)));
 }
 
 } }
diff --git a/wtf/unicode/wince/UnicodeWinCE.cpp b/wtf/unicode/wince/UnicodeWinCE.cpp
new file mode 100644 (file)
index 0000000..96dac7d
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (C) 2006 George Staikos <staikos@kde.org>
+ *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "UnicodeWinCE.h"
+
+#include <wchar.h>
+
+namespace WTF {
+namespace Unicode {
+
+UChar toLower(UChar c)
+{
+    return towlower(c);
+}
+
+UChar toUpper(UChar c)
+{
+    return towupper(c);
+}
+
+UChar foldCase(UChar c)
+{
+    return towlower(c);
+}
+
+bool isPrintableChar(UChar c)
+{
+    return !!iswprint(c);
+}
+
+bool isSpace(UChar c)
+{
+    return !!iswspace(c);
+}
+
+bool isLetter(UChar c)
+{
+    return !!iswalpha(c);
+}
+
+bool isUpper(UChar c)
+{
+    return !!iswupper(c);
+}
+
+bool isLower(UChar c)
+{
+    return !!iswlower(c);
+}
+
+bool isDigit(UChar c)
+{
+    return !!iswdigit(c);
+}
+
+bool isPunct(UChar c)
+{
+    return !!iswpunct(c);
+}
+
+bool isAlphanumeric(UChar c)
+{
+    return !!iswalnum(c);
+}
+
+int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError)
+{
+    const UChar* sourceIterator = source;
+    const UChar* sourceEnd = source + sourceLength;
+    UChar* resultIterator = result;
+    UChar* resultEnd = result + resultLength;
+
+    int remainingCharacters = 0;
+    if (sourceLength <= resultLength)
+        while (sourceIterator < sourceEnd)
+            *resultIterator++ = towlower(*sourceIterator++);
+    else
+        while (resultIterator < resultEnd)
+            *resultIterator++ = towlower(*sourceIterator++);
+
+    if (sourceIterator < sourceEnd)
+        remainingCharacters += sourceEnd - sourceIterator;
+    *isError = !!remainingCharacters;
+    if (resultIterator < resultEnd)
+        *resultIterator = 0;
+
+    return (resultIterator - result) + remainingCharacters;
+}
+
+int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError)
+{
+    const UChar* sourceIterator = source;
+    const UChar* sourceEnd = source + sourceLength;
+    UChar* resultIterator = result;
+    UChar* resultEnd = result + resultLength;
+
+    int remainingCharacters = 0;
+    if (sourceLength <= resultLength)
+        while (sourceIterator < sourceEnd)
+            *resultIterator++ = towupper(*sourceIterator++);
+    else
+        while (resultIterator < resultEnd)
+            *resultIterator++ = towupper(*sourceIterator++);
+
+    if (sourceIterator < sourceEnd)
+        remainingCharacters += sourceEnd - sourceIterator;
+    *isError = !!remainingCharacters;
+    if (resultIterator < resultEnd)
+        *resultIterator = 0;
+
+    return (resultIterator - result) + remainingCharacters;
+}
+
+int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError)
+{
+    *isError = false;
+    if (resultLength < sourceLength) {
+        *isError = true;
+        return sourceLength;
+    }
+    for (int i = 0; i < sourceLength; ++i)
+        result[i] = foldCase(source[i]);
+    return sourceLength;
+}
+
+UChar toTitleCase(UChar c)
+{
+    return towupper(c);
+}
+
+Direction direction(UChar32 c)
+{
+    return static_cast<Direction>(UnicodeCE::direction(c));
+}
+
+CharCategory category(unsigned int c)
+{
+    return static_cast<CharCategory>(TO_MASK((__int8) UnicodeCE::category(c)));
+}
+
+DecompositionType decompositionType(UChar32 c)
+{
+    return static_cast<DecompositionType>(UnicodeCE::decompositionType(c));
+}
+
+unsigned char combiningClass(UChar32 c)
+{
+    return UnicodeCE::combiningClass(c);
+}
+
+UChar mirroredChar(UChar32 c)
+{
+    return UnicodeCE::mirroredChar(c);
+}
+
+int digitValue(UChar c)
+{
+    return UnicodeCE::digitValue(c);
+}
+
+} // namespace Unicode
+} // namespace WTF
diff --git a/wtf/unicode/wince/UnicodeWinCE.h b/wtf/unicode/wince/UnicodeWinCE.h
new file mode 100644 (file)
index 0000000..2688aa9
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (C) 2006 George Staikos <staikos@kde.org>
+ *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
+ *  Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
+ *  Copyright (C) 2007-2009 Torch Mobile, Inc.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_UnicodeWinCE_h
+#define WTF_UnicodeWinCE_h
+
+#include "UnicodeMacrosFromICU.h"
+
+#include "ce_unicode.h"
+
+#define TO_MASK(x) (1 << (x))
+
+namespace WTF {
+namespace Unicode {
+
+enum Direction {
+    LeftToRight = UnicodeCE::U_LEFT_TO_RIGHT,
+    RightToLeft = UnicodeCE::U_RIGHT_TO_LEFT,
+    EuropeanNumber = UnicodeCE::U_EUROPEAN_NUMBER,
+    EuropeanNumberSeparator = UnicodeCE::U_EUROPEAN_NUMBER_SEPARATOR,
+    EuropeanNumberTerminator = UnicodeCE::U_EUROPEAN_NUMBER_TERMINATOR,
+    ArabicNumber = UnicodeCE::U_ARABIC_NUMBER,
+    CommonNumberSeparator = UnicodeCE::U_COMMON_NUMBER_SEPARATOR,
+    BlockSeparator = UnicodeCE::U_BLOCK_SEPARATOR,
+    SegmentSeparator = UnicodeCE::U_SEGMENT_SEPARATOR,
+    WhiteSpaceNeutral = UnicodeCE::U_WHITE_SPACE_NEUTRAL,
+    OtherNeutral = UnicodeCE::U_OTHER_NEUTRAL,
+    LeftToRightEmbedding = UnicodeCE::U_LEFT_TO_RIGHT_EMBEDDING,
+    LeftToRightOverride = UnicodeCE::U_LEFT_TO_RIGHT_OVERRIDE,
+    RightToLeftArabic = UnicodeCE::U_RIGHT_TO_LEFT_ARABIC,
+    RightToLeftEmbedding = UnicodeCE::U_RIGHT_TO_LEFT_EMBEDDING,
+    RightToLeftOverride = UnicodeCE::U_RIGHT_TO_LEFT_OVERRIDE,
+    PopDirectionalFormat = UnicodeCE::U_POP_DIRECTIONAL_FORMAT,
+    NonSpacingMark = UnicodeCE::U_DIR_NON_SPACING_MARK,
+    BoundaryNeutral = UnicodeCE::U_BOUNDARY_NEUTRAL
+};
+
+enum DecompositionType {
+    DecompositionNone = UnicodeCE::U_DT_NONE,
+    DecompositionCanonical = UnicodeCE::U_DT_CANONICAL,
+    DecompositionCompat = UnicodeCE::U_DT_COMPAT,
+    DecompositionCircle = UnicodeCE::U_DT_CIRCLE,
+    DecompositionFinal = UnicodeCE::U_DT_FINAL,
+    DecompositionFont = UnicodeCE::U_DT_FONT,
+    DecompositionFraction = UnicodeCE::U_DT_FRACTION,
+    DecompositionInitial = UnicodeCE::U_DT_INITIAL,
+    DecompositionIsolated = UnicodeCE::U_DT_ISOLATED,
+    DecompositionMedial = UnicodeCE::U_DT_MEDIAL,
+    DecompositionNarrow = UnicodeCE::U_DT_NARROW,
+    DecompositionNoBreak = UnicodeCE::U_DT_NOBREAK,
+    DecompositionSmall = UnicodeCE::U_DT_SMALL,
+    DecompositionSquare = UnicodeCE::U_DT_SQUARE,
+    DecompositionSub = UnicodeCE::U_DT_SUB,
+    DecompositionSuper = UnicodeCE::U_DT_SUPER,
+    DecompositionVertical = UnicodeCE::U_DT_VERTICAL,
+    DecompositionWide = UnicodeCE::U_DT_WIDE
+};
+
+enum CharCategory {
+    NoCategory =  0,
+    Other_NotAssigned = TO_MASK(UnicodeCE::U_GENERAL_OTHER_TYPES),
+    Letter_Uppercase = TO_MASK(UnicodeCE::U_UPPERCASE_LETTER),
+    Letter_Lowercase = TO_MASK(UnicodeCE::U_LOWERCASE_LETTER),
+    Letter_Titlecase = TO_MASK(UnicodeCE::U_TITLECASE_LETTER),
+    Letter_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_LETTER),
+    Letter_Other = TO_MASK(UnicodeCE::U_OTHER_LETTER),
+
+    Mark_NonSpacing = TO_MASK(UnicodeCE::U_NON_SPACING_MARK),
+    Mark_Enclosing = TO_MASK(UnicodeCE::U_ENCLOSING_MARK),
+    Mark_SpacingCombining = TO_MASK(UnicodeCE::U_COMBINING_SPACING_MARK),
+
+    Number_DecimalDigit = TO_MASK(UnicodeCE::U_DECIMAL_DIGIT_NUMBER),
+    Number_Letter = TO_MASK(UnicodeCE::U_LETTER_NUMBER),
+    Number_Other = TO_MASK(UnicodeCE::U_OTHER_NUMBER),
+
+    Separator_Space = TO_MASK(UnicodeCE::U_SPACE_SEPARATOR),
+    Separator_Line = TO_MASK(UnicodeCE::U_LINE_SEPARATOR),
+    Separator_Paragraph = TO_MASK(UnicodeCE::U_PARAGRAPH_SEPARATOR),
+
+    Other_Control = TO_MASK(UnicodeCE::U_CONTROL_CHAR),
+    Other_Format = TO_MASK(UnicodeCE::U_FORMAT_CHAR),
+    Other_PrivateUse = TO_MASK(UnicodeCE::U_PRIVATE_USE_CHAR),
+    Other_Surrogate = TO_MASK(UnicodeCE::U_SURROGATE),
+
+    Punctuation_Dash = TO_MASK(UnicodeCE::U_DASH_PUNCTUATION),
+    Punctuation_Open = TO_MASK(UnicodeCE::U_START_PUNCTUATION),
+    Punctuation_Close = TO_MASK(UnicodeCE::U_END_PUNCTUATION),
+    Punctuation_Connector = TO_MASK(UnicodeCE::U_CONNECTOR_PUNCTUATION),
+    Punctuation_Other = TO_MASK(UnicodeCE::U_OTHER_PUNCTUATION),
+
+    Symbol_Math = TO_MASK(UnicodeCE::U_MATH_SYMBOL),
+    Symbol_Currency = TO_MASK(UnicodeCE::U_CURRENCY_SYMBOL),
+    Symbol_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_SYMBOL),
+    Symbol_Other = TO_MASK(UnicodeCE::U_OTHER_SYMBOL),
+
+    Punctuation_InitialQuote = TO_MASK(UnicodeCE::U_INITIAL_PUNCTUATION),
+    Punctuation_FinalQuote = TO_MASK(UnicodeCE::U_FINAL_PUNCTUATION)
+};
+
+CharCategory category(unsigned int);
+
+bool isSpace(UChar);
+bool isLetter(UChar);
+bool isPrintableChar(UChar);
+bool isUpper(UChar);
+bool isLower(UChar);
+bool isPunct(UChar);
+bool isDigit(UChar);
+bool isAlphanumeric(UChar);
+inline bool isSeparatorSpace(UChar c) { return category(c) == Separator_Space; }
+inline bool isHighSurrogate(UChar c) { return (c & 0xfc00) == 0xd800; }
+inline bool isLowSurrogate(UChar c) { return (c & 0xfc00) == 0xdc00; }
+
+UChar toLower(UChar);
+UChar toUpper(UChar);
+UChar foldCase(UChar);
+UChar toTitleCase(UChar);
+int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError);
+int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError);
+int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError);
+
+int digitValue(UChar);
+
+UChar mirroredChar(UChar32);
+unsigned char combiningClass(UChar32);
+DecompositionType decompositionType(UChar32);
+Direction direction(UChar32);
+inline bool isArabicChar(UChar32 c)
+{
+    return c >= 0x0600 && c <= 0x06FF;
+}
+
+inline bool hasLineBreakingPropertyComplexContext(UChar32)
+{
+    return false; // FIXME: implement!
+}
+
+inline int umemcasecmp(const UChar* a, const UChar* b, int len)
+{
+    for (int i = 0; i < len; ++i) {
+        UChar c1 = foldCase(a[i]);
+        UChar c2 = foldCase(b[i]);
+        if (c1 != c2)
+            return c1 - c2;
+    }
+    return 0;
+}
+
+inline UChar32 surrogateToUcs4(UChar high, UChar low)
+{
+    return (UChar32(high) << 10) + low - 0x35fdc00;
+}
+
+} // namespace Unicode
+} // namespace WTF
+
+#endif // WTF_UnicodeWinCE_h
diff --git a/wtf/unicode/wince/UnicodeWince.cpp b/wtf/unicode/wince/UnicodeWince.cpp
deleted file mode 100644 (file)
index 2df44f8..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *  Copyright (C) 2006 George Staikos <staikos@kde.org>
- *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- *  Copyright (C) 2007-2009 Torch Mobile, Inc.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "UnicodeWince.h"
-
-#include <wchar.h>
-
-namespace WTF {
-namespace Unicode {
-
-wchar_t toLower(wchar_t c)
-{
-    return towlower(c);
-}
-
-wchar_t toUpper(wchar_t c)
-{
-    return towupper(c);
-}
-
-wchar_t foldCase(wchar_t c)
-{
-    return towlower(c);
-}
-
-bool isPrintableChar(wchar_t c)
-{
-    return !!iswprint(c);
-}
-
-bool isSpace(wchar_t c)
-{
-    return !!iswspace(c);
-}
-
-bool isLetter(wchar_t c)
-{
-    return !!iswalpha(c);
-}
-
-bool isUpper(wchar_t c)
-{
-    return !!iswupper(c);
-}
-
-bool isLower(wchar_t c)
-{
-    return !!iswlower(c);
-}
-
-bool isDigit(wchar_t c)
-{
-    return !!iswdigit(c);
-}
-
-bool isPunct(wchar_t c)
-{
-    return !!iswpunct(c);
-}
-
-int toLower(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError)
-{
-    const UChar* sourceIterator = source;
-    const UChar* sourceEnd = source + sourceLength;
-    UChar* resultIterator = result;
-    UChar* resultEnd = result + resultLength;
-
-    int remainingCharacters = 0;
-    if (sourceLength <= resultLength)
-        while (sourceIterator < sourceEnd)
-            *resultIterator++ = towlower(*sourceIterator++);
-    else
-        while (resultIterator < resultEnd)
-            *resultIterator++ = towlower(*sourceIterator++);
-
-    if (sourceIterator < sourceEnd)
-        remainingCharacters += sourceEnd - sourceIterator;
-    *isError = (remainingCharacters != 0);
-    if (resultIterator < resultEnd)
-        *resultIterator = 0;
-
-    return (resultIterator - result) + remainingCharacters;
-}
-
-int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError)
-{
-    const UChar* sourceIterator = source;
-    const UChar* sourceEnd = source + sourceLength;
-    UChar* resultIterator = result;
-    UChar* resultEnd = result + resultLength;
-
-    int remainingCharacters = 0;
-    if (sourceLength <= resultLength)
-        while (sourceIterator < sourceEnd)
-            *resultIterator++ = towupper(*sourceIterator++);
-    else
-        while (resultIterator < resultEnd)
-            *resultIterator++ = towupper(*sourceIterator++);
-
-    if (sourceIterator < sourceEnd)
-        remainingCharacters += sourceEnd - sourceIterator;
-    *isError = (remainingCharacters != 0);
-    if (resultIterator < resultEnd)
-        *resultIterator = 0;
-
-    return (resultIterator - result) + remainingCharacters;
-}
-
-int foldCase(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError)
-{
-    *isError = false;
-    if (resultLength < sourceLength) {
-        *isError = true;
-        return sourceLength;
-    }
-    for (int i = 0; i < sourceLength; ++i)
-        result[i] = foldCase(source[i]);
-    return sourceLength;
-}
-
-wchar_t toTitleCase(wchar_t c)
-{
-    return towupper(c);
-}
-
-Direction direction(UChar32 c)
-{
-    return static_cast<Direction>(UnicodeCE::direction(c));
-}
-
-CharCategory category(unsigned int c)
-{
-    return static_cast<CharCategory>(TO_MASK((__int8) UnicodeCE::category(c)));
-}
-
-DecompositionType decompositionType(UChar32 c)
-{
-    return static_cast<DecompositionType>(UnicodeCE::decompositionType(c));
-}
-
-unsigned char combiningClass(UChar32 c)
-{
-    return UnicodeCE::combiningClass(c);
-}
-
-wchar_t mirroredChar(UChar32 c)
-{
-    return UnicodeCE::mirroredChar(c);
-}
-
-int digitValue(wchar_t c)
-{
-    return UnicodeCE::digitValue(c);
-}
-
-} // namespace Unicode
-} // namespace WTF
diff --git a/wtf/unicode/wince/UnicodeWince.h b/wtf/unicode/wince/UnicodeWince.h
deleted file mode 100644 (file)
index db656ec..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- *  Copyright (C) 2006 George Staikos <staikos@kde.org>
- *  Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- *  Copyright (C) 2007 Apple Computer, Inc. All rights reserved.
- *  Copyright (C) 2007-2009 Torch Mobile, Inc.
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef UNICODE_WINCE_H
-#define UNICODE_WINCE_H
-
-#include "ce_unicode.h"
-
-#define TO_MASK(x) (1 << (x))
-
-// some defines from ICU needed one or two places
-
-#define U16_IS_LEAD(c) (((c) & 0xfffffc00) == 0xd800)
-#define U16_IS_TRAIL(c) (((c) & 0xfffffc00) == 0xdc00)
-#define U16_SURROGATE_OFFSET ((0xd800 << 10UL) + 0xdc00 - 0x10000)
-#define U16_GET_SUPPLEMENTARY(lead, trail) \
-    (((UChar32)(lead) << 10UL) + (UChar32)(trail) - U16_SURROGATE_OFFSET)
-
-#define U16_LEAD(supplementary) (UChar)(((supplementary) >> 10) + 0xd7c0)
-#define U16_TRAIL(supplementary) (UChar)(((supplementary) & 0x3ff) | 0xdc00)
-
-#define U_IS_SURROGATE(c) (((c) & 0xfffff800) == 0xd800)
-#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c)
-#define U16_IS_SURROGATE_LEAD(c) (((c) & 0x400) == 0)
-
-#define U16_NEXT(s, i, length, c) { \
-    (c)=(s)[(i)++]; \
-    if (U16_IS_LEAD(c)) { \
-        uint16_t __c2; \
-        if ((i) < (length) && U16_IS_TRAIL(__c2 = (s)[(i)])) { \
-            ++(i); \
-            (c) = U16_GET_SUPPLEMENTARY((c), __c2); \
-        } \
-    } \
-}
-
-#define U16_PREV(s, start, i, c) { \
-    (c)=(s)[--(i)]; \
-    if (U16_IS_TRAIL(c)) { \
-        uint16_t __c2; \
-        if ((i) > (start) && U16_IS_LEAD(__c2 = (s)[(i) - 1])) { \
-            --(i); \
-            (c) = U16_GET_SUPPLEMENTARY(__c2, (c)); \
-        } \
-    } \
-}
-
-#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c)
-
-namespace WTF {
-
-    namespace Unicode {
-
-        enum Direction {
-            LeftToRight = UnicodeCE::U_LEFT_TO_RIGHT,
-            RightToLeft = UnicodeCE::U_RIGHT_TO_LEFT,
-            EuropeanNumber = UnicodeCE::U_EUROPEAN_NUMBER,
-            EuropeanNumberSeparator = UnicodeCE::U_EUROPEAN_NUMBER_SEPARATOR,
-            EuropeanNumberTerminator = UnicodeCE::U_EUROPEAN_NUMBER_TERMINATOR,
-            ArabicNumber = UnicodeCE::U_ARABIC_NUMBER,
-            CommonNumberSeparator = UnicodeCE::U_COMMON_NUMBER_SEPARATOR,
-            BlockSeparator = UnicodeCE::U_BLOCK_SEPARATOR,
-            SegmentSeparator = UnicodeCE::U_SEGMENT_SEPARATOR,
-            WhiteSpaceNeutral = UnicodeCE::U_WHITE_SPACE_NEUTRAL,
-            OtherNeutral = UnicodeCE::U_OTHER_NEUTRAL,
-            LeftToRightEmbedding = UnicodeCE::U_LEFT_TO_RIGHT_EMBEDDING,
-            LeftToRightOverride = UnicodeCE::U_LEFT_TO_RIGHT_OVERRIDE,
-            RightToLeftArabic = UnicodeCE::U_RIGHT_TO_LEFT_ARABIC,
-            RightToLeftEmbedding = UnicodeCE::U_RIGHT_TO_LEFT_EMBEDDING,
-            RightToLeftOverride = UnicodeCE::U_RIGHT_TO_LEFT_OVERRIDE,
-            PopDirectionalFormat = UnicodeCE::U_POP_DIRECTIONAL_FORMAT,
-            NonSpacingMark = UnicodeCE::U_DIR_NON_SPACING_MARK,
-            BoundaryNeutral = UnicodeCE::U_BOUNDARY_NEUTRAL
-        };
-
-        enum DecompositionType {
-          DecompositionNone = UnicodeCE::U_DT_NONE,
-          DecompositionCanonical = UnicodeCE::U_DT_CANONICAL,
-          DecompositionCompat = UnicodeCE::U_DT_COMPAT,
-          DecompositionCircle = UnicodeCE::U_DT_CIRCLE,
-          DecompositionFinal = UnicodeCE::U_DT_FINAL,
-          DecompositionFont = UnicodeCE::U_DT_FONT,
-          DecompositionFraction = UnicodeCE::U_DT_FRACTION,
-          DecompositionInitial = UnicodeCE::U_DT_INITIAL,
-          DecompositionIsolated = UnicodeCE::U_DT_ISOLATED,
-          DecompositionMedial = UnicodeCE::U_DT_MEDIAL,
-          DecompositionNarrow = UnicodeCE::U_DT_NARROW,
-          DecompositionNoBreak = UnicodeCE::U_DT_NOBREAK,
-          DecompositionSmall = UnicodeCE::U_DT_SMALL,
-          DecompositionSquare = UnicodeCE::U_DT_SQUARE,
-          DecompositionSub = UnicodeCE::U_DT_SUB,
-          DecompositionSuper = UnicodeCE::U_DT_SUPER,
-          DecompositionVertical = UnicodeCE::U_DT_VERTICAL,
-          DecompositionWide = UnicodeCE::U_DT_WIDE,
-        };
-
-        enum CharCategory {
-          NoCategory =  0,
-          Other_NotAssigned = TO_MASK(UnicodeCE::U_GENERAL_OTHER_TYPES),
-          Letter_Uppercase = TO_MASK(UnicodeCE::U_UPPERCASE_LETTER),
-          Letter_Lowercase = TO_MASK(UnicodeCE::U_LOWERCASE_LETTER),
-          Letter_Titlecase = TO_MASK(UnicodeCE::U_TITLECASE_LETTER),
-          Letter_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_LETTER),
-          Letter_Other = TO_MASK(UnicodeCE::U_OTHER_LETTER),
-
-          Mark_NonSpacing = TO_MASK(UnicodeCE::U_NON_SPACING_MARK),
-          Mark_Enclosing = TO_MASK(UnicodeCE::U_ENCLOSING_MARK),
-          Mark_SpacingCombining = TO_MASK(UnicodeCE::U_COMBINING_SPACING_MARK),
-
-          Number_DecimalDigit = TO_MASK(UnicodeCE::U_DECIMAL_DIGIT_NUMBER),
-          Number_Letter = TO_MASK(UnicodeCE::U_LETTER_NUMBER),
-          Number_Other = TO_MASK(UnicodeCE::U_OTHER_NUMBER),
-
-          Separator_Space = TO_MASK(UnicodeCE::U_SPACE_SEPARATOR),
-          Separator_Line = TO_MASK(UnicodeCE::U_LINE_SEPARATOR),
-          Separator_Paragraph = TO_MASK(UnicodeCE::U_PARAGRAPH_SEPARATOR),
-
-          Other_Control = TO_MASK(UnicodeCE::U_CONTROL_CHAR),
-          Other_Format = TO_MASK(UnicodeCE::U_FORMAT_CHAR),
-          Other_PrivateUse = TO_MASK(UnicodeCE::U_PRIVATE_USE_CHAR),
-          Other_Surrogate = TO_MASK(UnicodeCE::U_SURROGATE),
-
-          Punctuation_Dash = TO_MASK(UnicodeCE::U_DASH_PUNCTUATION),
-          Punctuation_Open = TO_MASK(UnicodeCE::U_START_PUNCTUATION),
-          Punctuation_Close = TO_MASK(UnicodeCE::U_END_PUNCTUATION),
-          Punctuation_Connector = TO_MASK(UnicodeCE::U_CONNECTOR_PUNCTUATION),
-          Punctuation_Other = TO_MASK(UnicodeCE::U_OTHER_PUNCTUATION),
-
-          Symbol_Math = TO_MASK(UnicodeCE::U_MATH_SYMBOL),
-          Symbol_Currency = TO_MASK(UnicodeCE::U_CURRENCY_SYMBOL),
-          Symbol_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_SYMBOL),
-          Symbol_Other = TO_MASK(UnicodeCE::U_OTHER_SYMBOL),
-
-          Punctuation_InitialQuote = TO_MASK(UnicodeCE::U_INITIAL_PUNCTUATION),
-          Punctuation_FinalQuote = TO_MASK(UnicodeCE::U_FINAL_PUNCTUATION)
-        };
-
-        CharCategory category(unsigned int);
-
-        bool isSpace(wchar_t);
-        bool isLetter(wchar_t);
-        bool isPrintableChar(wchar_t);
-        bool isUpper(wchar_t);
-        bool isLower(wchar_t);
-        bool isPunct(wchar_t);
-        bool isDigit(wchar_t);
-        inline bool isSeparatorSpace(wchar_t c) { return category(c) == Separator_Space; }
-        inline bool isHighSurrogate(wchar_t c) { return (c & 0xfc00) == 0xd800; }
-        inline bool isLowSurrogate(wchar_t c) { return (c & 0xfc00) == 0xdc00; }
-
-        wchar_t toLower(wchar_t);
-        wchar_t toUpper(wchar_t);
-        wchar_t foldCase(wchar_t);
-        wchar_t toTitleCase(wchar_t);
-        int toLower(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError);
-        int toUpper(wchar_t* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError);
-        int foldCase(UChar* result, int resultLength, const wchar_t* source, int sourceLength, bool* isError);
-
-        int digitValue(wchar_t);
-
-        wchar_t mirroredChar(UChar32);
-        unsigned char combiningClass(UChar32);
-        DecompositionType decompositionType(UChar32);
-        Direction direction(UChar32);
-        inline bool isArabicChar(UChar32)
-        {
-            return false; // FIXME: implement!
-        }
-
-        inline bool hasLineBreakingPropertyComplexContext(UChar32)
-        {
-            return false; // FIXME: implement!
-        }
-
-        inline int umemcasecmp(const wchar_t* a, const wchar_t* b, int len)
-        {
-            for (int i = 0; i < len; ++i) {
-                wchar_t c1 = foldCase(a[i]);
-                wchar_t c2 = foldCase(b[i]);
-                if (c1 != c2)
-                    return c1 - c2;
-            }
-            return 0;
-        }
-
-        inline UChar32 surrogateToUcs4(wchar_t high, wchar_t low)
-        {
-            return (UChar32(high) << 10) + low - 0x35fdc00;
-        }
-
-    }   // namespace Unicode
-
-}   // namespace WTF
-
-#endif
-// vim: ts=2 sw=2 et
diff --git a/wtf/url/api/ParsedURL.cpp b/wtf/url/api/ParsedURL.cpp
new file mode 100644 (file)
index 0000000..abe0061
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 Google, 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. 
+ */
+
+#include "config.h"
+#include "ParsedURL.h"
+
+#include "URLComponent.h"
+#include "URLParser.h"
+
+namespace WTF {
+
+ParsedURL::ParsedURL(const URLString& spec)
+    : m_spec(spec)
+{
+    // FIXME: Handle non-standard URLs.
+    if (spec.string().isEmpty())
+        return;
+    URLParser<UChar>::parseStandardURL(spec.string().characters(), spec.string().length(), m_segments);
+}
+
+String ParsedURL::scheme() const
+{
+    return segment(m_segments.scheme);
+}
+
+String ParsedURL::username() const
+{
+    return segment(m_segments.username);
+}
+
+String ParsedURL::password() const
+{
+    return segment(m_segments.password);
+}
+
+String ParsedURL::host() const
+{
+    return segment(m_segments.host);
+}
+
+String ParsedURL::port() const
+{
+    return segment(m_segments.port);
+}
+
+String ParsedURL::path() const
+{
+    return segment(m_segments.path);
+}
+
+String ParsedURL::query() const
+{
+    return segment(m_segments.query);
+}
+
+String ParsedURL::fragment() const
+{
+    return segment(m_segments.fragment);
+}
+
+String ParsedURL::segment(const URLComponent& component) const
+{
+    if (!component.isValid())
+        return String();
+    return m_spec.string().substring(component.begin(), component.length());
+}
+
+}
diff --git a/wtf/url/api/ParsedURL.h b/wtf/url/api/ParsedURL.h
new file mode 100644 (file)
index 0000000..ebc19b7
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 Google, 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 ParsedURL_h
+#define ParsedURL_h
+
+#include "URLSegments.h"
+#include "URLString.h"
+
+namespace WTF {
+
+class URLComponent;
+
+class ParsedURL {
+public:
+    explicit ParsedURL(const URLString&);
+
+    // FIXME: Add a method for parsing non-canonicalized URLs.
+
+    String scheme() const;
+    String username() const;
+    String password() const;
+    String host() const;
+    String port() const;
+    String path() const;
+    String query() const;
+    String fragment() const;
+
+    URLString spec() { return m_spec; }
+
+private:
+    inline String segment(const URLComponent&) const;
+
+    URLString m_spec;
+    URLSegments m_segments;
+};
+
+}
+
+#endif
diff --git a/wtf/url/api/URLString.h b/wtf/url/api/URLString.h
new file mode 100644 (file)
index 0000000..7395d49
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 Google, 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 URLString_h
+#define URLString_h
+
+#include "WTFString.h"
+
+namespace WTF {
+
+// URLString represents a string that's a canonicalized URL.
+class URLString {
+public:
+    URLString() { }
+
+    const String& string() const { return m_string;}
+
+private:
+    friend class ParsedURL;
+
+    // URLString can only be constructed by a ParsedURL.
+    explicit URLString(const String& string)
+        : m_string(string)
+    {
+    }
+
+    String m_string;
+};
+
+}
+
+#endif
+
diff --git a/wtf/url/src/RawURLBuffer.h b/wtf/url/src/RawURLBuffer.h
new file mode 100644 (file)
index 0000000..9bb2e8e
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 RawURLBuffer_h
+#define RawURLBuffer_h
+
+#include "URLBuffer.h"
+#include <stdlib.h>
+
+namespace WTF {
+
+// Simple implementation of the URLBuffer using new[]. This class
+// also supports a static buffer so if it is allocated on the stack, most
+// URLs can be canonicalized with no heap allocations.
+template<typename CHAR, int inlineCapacity = 1024>
+class RawURLBuffer : public URLBuffer<CHAR> {
+public:
+    RawURLBuffer() : URLBuffer<CHAR>()
+    {
+        this->m_buffer = m_inlineBuffer;
+        this->m_capacity = inlineCapacity;
+    }
+
+    virtual ~RawURLBuffer()
+    {
+        if (this->m_buffer != m_inlineBuffer)
+            delete[] this->m_buffer;
+    }
+
+    virtual void resize(int size)
+    {
+        CHAR* newBuffer = new CHAR[size];
+        memcpy(newBuffer, this->m_buffer, sizeof(CHAR) * (this->m_length < size ? this->m_length : size));
+        if (this->m_buffer != m_inlineBuffer)
+            delete[] this->m_buffer;
+        this->m_buffer = newBuffer;
+        this->m_capacity = size;
+    }
+
+protected:
+    CHAR m_inlineBuffer[inlineCapacity];
+};
+
+} // namespace WTF
+
+#endif // RawURLBuffer_h
diff --git a/wtf/url/src/URLBuffer.h b/wtf/url/src/URLBuffer.h
new file mode 100644 (file)
index 0000000..e07402e
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 URLBuffer_h
+#define URLBuffer_h
+
+namespace WTF {
+
+// Base class for the canonicalizer output, this maintains a buffer and
+// supports simple resizing and append operations on it.
+//
+// It is VERY IMPORTANT that no virtual function calls be made on the common
+// code path. We only have two virtual function calls, the destructor and a
+// resize function that is called when the existing buffer is not big enough.
+// The derived class is then in charge of setting up our buffer which we will
+// manage.
+template<typename CHAR>
+class URLBuffer {
+public:
+    URLBuffer() : m_buffer(0), m_capacity(0), m_length(0) { }
+    virtual ~URLBuffer() { }
+
+    // Implemented to resize the buffer. This function should update the buffer
+    // pointer to point to the new buffer, and any old data up to |m_length| in
+    // the buffer must be copied over.
+    //
+    // The new size must be larger than m_capacity.
+    virtual void resize(int) = 0;
+
+    inline char at(int offset) const { return m_buffer[offset]; }
+    inline void set(int offset, CHAR ch)
+    {
+        // FIXME: Add ASSERT(offset < length());
+        m_buffer[offset] = ch;
+    }
+
+    // Returns the current capacity of the buffer. The length() is the number of
+    // characters that have been declared to be written, but the capacity() is
+    // the number that can be written without reallocation. If the caller must
+    // write many characters at once, it can make sure there is enough capacity,
+    // write the data, then use setLength() to declare the new length().
+    int capacity() const { return m_capacity; }
+    int length() const { return m_length; }
+
+    // The output will NOT be 0-terminated. Call length() to get the length.
+    const CHAR* data() const { return m_buffer; }
+    CHAR* data() { return m_buffer; }
+
+    // Shortens the URL to the new length. Used for "backing up" when processing
+    // relative paths. This can also be used if an external function writes a lot
+    // of data to the buffer (when using the "Raw" version below) beyond the end,
+    // to declare the new length.
+    void setLength(int length)
+    {
+        // FIXME: Add ASSERT(length < capacity());
+        m_length = length;
+    }
+
+    // This is the most performance critical function, since it is called for
+    // every character.
+    void append(CHAR ch)
+    {
+        // In VC2005, putting this common case first speeds up execution
+        // dramatically because this branch is predicted as taken.
+        if (m_length < m_capacity) {
+            m_buffer[m_length] = ch;
+            ++m_length;
+            return;
+        }
+
+        if (!grow(1))
+            return;
+
+        m_buffer[m_length] = ch;
+        ++m_length;
+    }
+
+    void append(const CHAR* str, int strLength)
+    {
+        if (m_length + strLength > m_capacity) {
+            if (!grow(m_length + strLength - m_capacity))
+                return;
+        }
+        for (int i = 0; i < strLength; i++)
+            m_buffer[m_length + i] = str[i];
+        m_length += strLength;
+    }
+
+protected:
+    // Returns true if the buffer could be resized, false on OOM.
+    bool grow(int minimumAdditionalCapacity)
+    {
+        static const int minimumCapacity = 16;
+        int newCapacity = m_capacity ? m_capacity : minimumCapacity;
+        do {
+            if (newCapacity >= (1 << 30)) // Prevent overflow below.
+                return false;
+            newCapacity *= 2;
+        } while (newCapacity < m_capacity + minimumAdditionalCapacity);
+        resize(newCapacity);
+        return true;
+    }
+
+    CHAR* m_buffer;
+    int m_capacity;
+    int m_length; // Used characters in the buffer.
+};
+
+} // namespace WTF
+
+#endif // URLBuffer_h
diff --git a/wtf/url/src/URLCharacterTypes.cpp b/wtf/url/src/URLCharacterTypes.cpp
new file mode 100644 (file)
index 0000000..ee2014e
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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.
+
+#include "config.h"
+#include "URLCharacterTypes.h"
+
+namespace WTF {
+
+const unsigned char URLCharacterTypes::characterTypeTable[0x100] = {
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x00 - 0x0f
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x10 - 0x1f
+    InvalidCharacter, // 0x20  ' ' (escape spaces in queries)
+    QueryCharacter | UserInfoCharacter, // 0x21  !
+    InvalidCharacter, // 0x22  "
+    InvalidCharacter, // 0x23  #  (invalid in query since it marks the ref)
+    QueryCharacter | UserInfoCharacter, // 0x24  $
+    QueryCharacter | UserInfoCharacter, // 0x25  %
+    QueryCharacter | UserInfoCharacter, // 0x26  &
+    QueryCharacter | UserInfoCharacter, // 0x27  '
+    QueryCharacter | UserInfoCharacter, // 0x28  (
+    QueryCharacter | UserInfoCharacter, // 0x29  )
+    QueryCharacter | UserInfoCharacter, // 0x2a  *
+    QueryCharacter | UserInfoCharacter, // 0x2b  +
+    QueryCharacter | UserInfoCharacter, // 0x2c  ,
+    QueryCharacter | UserInfoCharacter, // 0x2d  -
+    QueryCharacter | UserInfoCharacter | IPv4Character, // 0x2e  .
+    QueryCharacter, // 0x2f  /
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x30  0
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x31  1
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x32  2
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x33  3
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x34  4
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x35  5
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x36  6
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x37  7
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x38  8
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x39  9
+    QueryCharacter, // 0x3a  :
+    QueryCharacter, // 0x3b  ;
+    InvalidCharacter, // 0x3c  <
+    QueryCharacter, // 0x3d  =
+    InvalidCharacter, // 0x3e  >
+    QueryCharacter, // 0x3f  ?
+    QueryCharacter, // 0x40  @
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x41  A
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x42  B
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x43  C
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x44  D
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x45  E
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x46  F
+    QueryCharacter | UserInfoCharacter, // 0x47  G
+    QueryCharacter | UserInfoCharacter, // 0x48  H
+    QueryCharacter | UserInfoCharacter, // 0x49  I
+    QueryCharacter | UserInfoCharacter, // 0x4a  J
+    QueryCharacter | UserInfoCharacter, // 0x4b  K
+    QueryCharacter | UserInfoCharacter, // 0x4c  L
+    QueryCharacter | UserInfoCharacter, // 0x4d  M
+    QueryCharacter | UserInfoCharacter, // 0x4e  N
+    QueryCharacter | UserInfoCharacter, // 0x4f  O
+    QueryCharacter | UserInfoCharacter, // 0x50  P
+    QueryCharacter | UserInfoCharacter, // 0x51  Q
+    QueryCharacter | UserInfoCharacter, // 0x52  R
+    QueryCharacter | UserInfoCharacter, // 0x53  S
+    QueryCharacter | UserInfoCharacter, // 0x54  T
+    QueryCharacter | UserInfoCharacter, // 0x55  U
+    QueryCharacter | UserInfoCharacter, // 0x56  V
+    QueryCharacter | UserInfoCharacter, // 0x57  W
+    QueryCharacter | UserInfoCharacter | IPv4Character, // 0x58  X
+    QueryCharacter | UserInfoCharacter, // 0x59  Y
+    QueryCharacter | UserInfoCharacter, // 0x5a  Z
+    QueryCharacter, // 0x5b  [
+    QueryCharacter, // 0x5c  '\'
+    QueryCharacter, // 0x5d  ]
+    QueryCharacter, // 0x5e  ^
+    QueryCharacter | UserInfoCharacter, // 0x5f  _
+    QueryCharacter, // 0x60  `
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x61  a
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x62  b
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x63  c
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x64  d
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x65  e
+    QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x66  f
+    QueryCharacter | UserInfoCharacter, // 0x67  g
+    QueryCharacter | UserInfoCharacter, // 0x68  h
+    QueryCharacter | UserInfoCharacter, // 0x69  i
+    QueryCharacter | UserInfoCharacter, // 0x6a  j
+    QueryCharacter | UserInfoCharacter, // 0x6b  k
+    QueryCharacter | UserInfoCharacter, // 0x6c  l
+    QueryCharacter | UserInfoCharacter, // 0x6d  m
+    QueryCharacter | UserInfoCharacter, // 0x6e  n
+    QueryCharacter | UserInfoCharacter, // 0x6f  o
+    QueryCharacter | UserInfoCharacter, // 0x70  p
+    QueryCharacter | UserInfoCharacter, // 0x71  q
+    QueryCharacter | UserInfoCharacter, // 0x72  r
+    QueryCharacter | UserInfoCharacter, // 0x73  s
+    QueryCharacter | UserInfoCharacter, // 0x74  t
+    QueryCharacter | UserInfoCharacter, // 0x75  u
+    QueryCharacter | UserInfoCharacter, // 0x76  v
+    QueryCharacter | UserInfoCharacter, // 0x77  w
+    QueryCharacter | UserInfoCharacter | IPv4Character, // 0x78  x
+    QueryCharacter | UserInfoCharacter, // 0x79  y
+    QueryCharacter | UserInfoCharacter, // 0x7a  z
+    QueryCharacter, // 0x7b  {
+    QueryCharacter, // 0x7c  |
+    QueryCharacter, // 0x7d  }
+    QueryCharacter | UserInfoCharacter, // 0x7e  ~
+    InvalidCharacter, // 0x7f
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x80 - 0x8f
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x90 - 0x9f
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xa0 - 0xaf
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xb0 - 0xbf
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xc0 - 0xcf
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xd0 - 0xdf
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xe0 - 0xef
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter,
+    InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xf0 - 0xff
+};
+
+}
diff --git a/wtf/url/src/URLCharacterTypes.h b/wtf/url/src/URLCharacterTypes.h
new file mode 100644 (file)
index 0000000..194f6b0
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 URLCharacterTypes_h
+#define URLCharacterTypes_h
+
+namespace WTF {
+
+class URLCharacterTypes {
+public:
+    static inline bool isQueryChar(unsigned char c) { return isCharOfType(c, QueryCharacter); }
+    static inline bool isIPv4Char(unsigned char c) { return isCharOfType(c, IPv4Character); }
+    static inline bool isHexChar(unsigned char c) { return isCharOfType(c, HexCharacter); }
+
+private:
+    enum CharTypes {
+        InvalidCharacter = 0,
+        QueryCharacter = 1 << 0,
+        UserInfoCharacter = 1 << 1,
+        IPv4Character = 1 << 2,
+        HexCharacter = 1 << 3,
+        DecimalCharacter = 1 << 4,
+        OctalCharacter = 1 << 5,
+    };
+
+    static const unsigned char characterTypeTable[0x100];
+
+    static inline bool isCharOfType(unsigned char c, CharTypes type)
+    {
+        return !!(characterTypeTable[c] & type);
+    }
+};
+
+}
+
+#endif
index ca7e6f36bd5f215d311d6a30137af3e42cf5a147..1b7976eb3916c6b04c22321a072732d06170ac98 100644 (file)
@@ -37,13 +37,19 @@ public:
     URLComponent() : m_begin(0), m_length(-1) { }
     URLComponent(int begin, int length) : m_begin(begin), m_length(length) { }
 
+    // Helper that returns a component created with the given begin and ending
+    // points. The ending point is non-inclusive.
+    static inline URLComponent fromRange(int begin, int end)
+    {
+        return URLComponent(begin, end - begin);
+    }
+
     // Returns true if this component is valid, meaning the length is given. Even
     // valid components may be empty to record the fact that they exist.
     bool isValid() const { return m_length != -1; }
 
-    // Returns true if the given component is specified on false, the component
-    // is either empty or invalid.
-    bool isNonempty() const { return m_length > 0; }
+    bool isNonEmpty() const { return m_length > 0; }
+    bool isEmptyOrInvalid() const { return m_length <= 0; }
 
     void reset()
     {
diff --git a/wtf/url/src/URLEscape.cpp b/wtf/url/src/URLEscape.cpp
new file mode 100644 (file)
index 0000000..2987343
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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.
+
+#include "config.h"
+#include "URLEscape.h"
+
+namespace WTF {
+
+const char hexCharacterTable[16] = {
+    '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+};
+
+}
diff --git a/wtf/url/src/URLEscape.h b/wtf/url/src/URLEscape.h
new file mode 100644 (file)
index 0000000..cc2b77f
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 URLEscape_h
+#define URLEscape_h
+
+#include "URLBuffer.h"
+
+namespace WTF {
+
+extern const char hexCharacterTable[16];
+
+template<typename InChar, typename OutChar>
+inline void appendURLEscapedCharacter(InChar ch, URLBuffer<OutChar>& buffer)
+{
+    buffer.append('%');
+    buffer.append(hexCharacterTable[ch >> 4]);
+    buffer.append(hexCharacterTable[ch & 0xf]);
+}
+
+}
+
+#endif
diff --git a/wtf/url/src/URLParser.h b/wtf/url/src/URLParser.h
new file mode 100644 (file)
index 0000000..4d5ca51
--- /dev/null
@@ -0,0 +1,575 @@
+/* Based on nsURLParsers.cc from Mozilla
+ * -------------------------------------
+ * Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Darin Fisher (original author)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of either the Mozilla Public License Version 1.1, found at
+ * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
+ * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
+ * (the "GPL"), in which case the provisions of the MPL or the GPL are
+ * applicable instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of one of those two
+ * licenses (the MPL or the GPL) and not to allow others to use your
+ * version of this file under the LGPL, indicate your decision by
+ * deletingthe provisions above and replace them with the notice and
+ * other provisions required by the MPL or the GPL, as the case may be.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under any of the LGPL, the MPL or the GPL.
+ */
+
+#ifndef URLParser_h
+#define URLParser_h
+
+#include "URLComponent.h"
+#include "URLSegments.h"
+
+namespace WTF {
+
+template<typename CHAR>
+class URLParser {
+public:
+    enum SpecialPort {
+        UnspecifiedPort = -1,
+        InvalidPort = -2,
+    };
+
+    // This handles everything that may be an authority terminator, including
+    // backslash. For special backslash handling see parseAfterScheme.
+    static bool isPossibleAuthorityTerminator(CHAR ch)
+    {
+        return isURLSlash(ch) || ch == '?' || ch == '#' || ch == ';';
+    }
+
+    // Given an already-identified auth section, breaks it into its constituent
+    // parts. The port number will be parsed and the resulting integer will be
+    // filled into the given *port variable, or -1 if there is no port number
+    // or it is invalid.
+    static void parseAuthority(const CHAR* spec, const URLComponent& auth, URLComponent& username, URLComponent& password, URLComponent& host, URLComponent& port)
+    {
+        // FIXME: add ASSERT(auth.isValid()); // We should always get an authority.
+        if (!auth.length()) {
+            username.reset();
+            password.reset();
+            host.reset();
+            port.reset();
+            return;
+        }
+
+        // Search backwards for @, which is the separator between the user info
+        // and the server info.  RFC 3986 forbids @ from occuring in auth, but
+        // someone might include it in a password unescaped.
+        int i = auth.begin() + auth.length() - 1;
+        while (i > auth.begin() && spec[i] != '@')
+            --i;
+
+        if (spec[i] == '@') {
+            // Found user info: <user-info>@<server-info>
+            parseUserInfo(spec, URLComponent(auth.begin(), i - auth.begin()), username, password);
+            parseServerInfo(spec, URLComponent::fromRange(i + 1, auth.begin() + auth.length()), host, port);
+        } else {
+            // No user info, everything is server info.
+            username.reset();
+            password.reset();
+            parseServerInfo(spec, auth, host, port);
+        }
+    }
+
+    static bool extractScheme(const CHAR* spec, int specLength, URLComponent& scheme)
+    {
+        // Skip leading whitespace and control characters.
+        int begin = 0;
+        while (begin < specLength && shouldTrimFromURL(spec[begin]))
+            begin++;
+        if (begin == specLength)
+            return false; // Input is empty or all whitespace.
+
+        // Find the first colon character.
+        for (int i = begin; i < specLength; i++) {
+            if (spec[i] == ':') {
+                scheme = URLComponent::fromRange(begin, i);
+                return true;
+            }
+        }
+        return false; // No colon found: no scheme
+    }
+
+    // Fills in all members of the URLSegments structure (except for the
+    // scheme) for standard URLs.
+    //
+    // |spec| is the full spec being parsed, of length |specLength|.
+    // |afterScheme| is the character immediately following the scheme (after
+    // the colon) where we'll begin parsing.
+    static void parseAfterScheme(const CHAR* spec, int specLength, int afterScheme, URLSegments& parsed)
+    {
+        int numberOfSlashes = consecutiveSlashes(spec, afterScheme, specLength);
+        int afterSlashes = afterScheme + numberOfSlashes;
+
+        // First split into two main parts, the authority (username, password,
+        // host, and port) and the full path (path, query, and reference).
+        URLComponent authority;
+        URLComponent fullPath;
+
+        // Found "//<some data>", looks like an authority section. Treat
+        // everything from there to the next slash (or end of spec) to be the
+        // authority. Note that we ignore the number of slashes and treat it as
+        // the authority.
+        int authEnd = nextAuthorityTerminator(spec, afterSlashes, specLength);
+        authority = URLComponent(afterSlashes, authEnd - afterSlashes);
+
+        if (authEnd == specLength) // No beginning of path found.
+            fullPath = URLComponent();
+        else // Everything starting from the slash to the end is the path.
+            fullPath = URLComponent(authEnd, specLength - authEnd);
+
+        // Now parse those two sub-parts.
+        parseAuthority(spec, authority, parsed.username, parsed.password, parsed.host, parsed.port);
+        parsePath(spec, fullPath, parsed.path, parsed.query, parsed.fragment);
+    }
+
+    // The main parsing function for standard URLs. Standard URLs have a scheme,
+    // host, path, etc.
+    static void parseStandardURL(const CHAR* spec, int specLength, URLSegments& parsed)
+    {
+        // FIXME: add ASSERT(specLength >= 0);
+
+        // Strip leading & trailing spaces and control characters.
+        int begin = 0;
+        trimURL(spec, begin, specLength);
+
+        int afterScheme;
+        if (extractScheme(spec, specLength, parsed.scheme))
+            afterScheme = parsed.scheme.end() + 1; // Skip past the colon.
+        else {
+            // Say there's no scheme when there is a colon. We could also say
+            // that everything is the scheme. Both would produce an invalid
+            // URL, but this way seems less wrong in more cases.
+            parsed.scheme.reset();
+            afterScheme = begin;
+        }
+        parseAfterScheme(spec, specLength, afterScheme, parsed);
+    }
+
+    static void parsePath(const CHAR* spec, const URLComponent& path, URLComponent& filepath, URLComponent& query, URLComponent& fragment)
+    {
+        // path = [/]<segment1>/<segment2>/<...>/<segmentN>;<param>?<query>#<fragment>
+
+        // Special case when there is no path.
+        if (!path.isValid()) {
+            filepath.reset();
+            query.reset();
+            fragment.reset();
+            return;
+        }
+        // FIXME: add ASSERT(path.length() > 0); // We should never have 0 length paths.
+
+        // Search for first occurrence of either ? or #.
+        int pathEnd = path.begin() + path.length();
+
+        int querySeparator = -1; // Index of the '?'
+        int refSeparator = -1; // Index of the '#'
+        for (int i = path.begin(); i < pathEnd; i++) {
+            switch (spec[i]) {
+            case '?':
+                if (querySeparator < 0)
+                    querySeparator = i;
+                break;
+            case '#':
+                refSeparator = i;
+                i = pathEnd; // Break out of the loop.
+                break;
+            default:
+                break;
+            }
+        }
+
+        // Markers pointing to the character after each of these corresponding
+        // components. The code below works from the end back to the beginning,
+        // and will update these indices as it finds components that exist.
+        int fileEnd, queryEnd;
+
+        // Fragment: from the # to the end of the path.
+        if (refSeparator >= 0) {
+            fileEnd = refSeparator;
+            queryEnd = refSeparator;
+            fragment = URLComponent::fromRange(refSeparator + 1, pathEnd);
+        } else {
+            fileEnd = pathEnd;
+            queryEnd = pathEnd;
+            fragment.reset();
+        }
+
+        // Query fragment: everything from the ? to the next boundary (either
+        // the end of the path or the fragment fragment).
+        if (querySeparator >= 0) {
+            fileEnd = querySeparator;
+            query = URLComponent::fromRange(querySeparator + 1, queryEnd);
+        } else
+            query.reset();
+
+        // File path: treat an empty file path as no file path.
+        if (fileEnd != path.begin())
+            filepath = URLComponent::fromRange(path.begin(), fileEnd);
+        else
+            filepath.reset();
+    }
+
+    // Initializes a path URL which is merely a scheme followed by a path.
+    // Examples include "about:foo" and "javascript:alert('bar');"
+    static void parsePathURL(const CHAR* spec, int specLength, URLSegments& parsed)
+    {
+        // Get the non-path and non-scheme parts of the URL out of the way, we
+        // never use them.
+        parsed.username.reset();
+        parsed.password.reset();
+        parsed.host.reset();
+        parsed.port.reset();
+        parsed.query.reset();
+        parsed.fragment.reset();
+
+        // Strip leading & trailing spaces and control characters.
+        // FIXME: Perhaps this is unnecessary?
+        int begin = 0;
+        trimURL(spec, begin, specLength);
+
+        // Handle empty specs or ones that contain only whitespace or control
+        // chars.
+        if (begin == specLength) {
+            parsed.scheme.reset();
+            parsed.path.reset();
+            return;
+        }
+
+        // Extract the scheme, with the path being everything following. We also
+        // handle the case where there is no scheme.
+        if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) {
+            // Offset the results since we gave extractScheme a substring.
+            parsed.scheme.setBegin(parsed.scheme.begin() + begin);
+
+            // For compatibility with the standard URL parser, we treat no path
+            // as -1, rather than having a length of 0 (we normally wouldn't
+            // care so much for these non-standard URLs).
+            if (parsed.scheme.end() == specLength - 1)
+                parsed.path.reset();
+            else
+                parsed.path = URLComponent::fromRange(parsed.scheme.end() + 1, specLength);
+        } else {
+            // No scheme found, just path.
+            parsed.scheme.reset();
+            parsed.path = URLComponent::fromRange(begin, specLength);
+        }
+    }
+
+    static void parseMailtoURL(const CHAR* spec, int specLength, URLSegments& parsed)
+    {
+        // FIXME: add ASSERT(specLength >= 0);
+
+        // Get the non-path and non-scheme parts of the URL out of the way, we
+        // never use them.
+        parsed.username.reset();
+        parsed.password.reset();
+        parsed.host.reset();
+        parsed.port.reset();
+        parsed.fragment.reset();
+        parsed.query.reset(); // May use this; reset for convenience.
+
+        // Strip leading & trailing spaces and control characters.
+        int begin = 0;
+        trimURL(spec, begin, specLength);
+
+        // Handle empty specs or ones that contain only whitespace or control
+        // chars.
+        if (begin == specLength) {
+            parsed.scheme.reset();
+            parsed.path.reset();
+            return;
+        }
+
+        int pathBegin = -1;
+        int pathEnd = -1;
+
+        // Extract the scheme, with the path being everything following. We also
+        // handle the case where there is no scheme.
+        if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) {
+            // Offset the results since we gave extractScheme a substring.
+            parsed.scheme.setBegin(parsed.scheme.begin() + begin);
+
+            if (parsed.scheme.end() != specLength - 1) {
+                pathBegin = parsed.scheme.end() + 1;
+                pathEnd = specLength;
+            }
+        } else {
+            // No scheme found, just path.
+            parsed.scheme.reset();
+            pathBegin = begin;
+            pathEnd = specLength;
+        }
+
+        // Split [pathBegin, pathEnd) into a path + query.
+        for (int i = pathBegin; i < pathEnd; ++i) {
+            if (spec[i] == '?') {
+                parsed.query = URLComponent::fromRange(i + 1, pathEnd);
+                pathEnd = i;
+                break;
+            }
+        }
+
+        // For compatibility with the standard URL parser, treat no path as
+        // -1, rather than having a length of 0
+        if (pathBegin == pathEnd)
+            parsed.path.reset();
+        else
+            parsed.path = URLComponent::fromRange(pathBegin, pathEnd);
+    }
+
+    static int parsePort(const CHAR* spec, const URLComponent& component)
+    {
+        // Easy success case when there is no port.
+        const int maxDigits = 5;
+        if (component.isEmptyOrInvalid())
+            return UnspecifiedPort;
+
+        URLComponent nonZeroDigits(component.end(), 0);
+        for (int i = 0; i < component.length(); ++i) {
+            if (spec[component.begin() + i] != '0') {
+                nonZeroDigits = URLComponent::fromRange(component.begin() + i, component.end());
+                break;
+            }
+        }
+        if (!nonZeroDigits.length())
+            return 0; // All digits were 0.
+
+        if (nonZeroDigits.length() > maxDigits)
+            return InvalidPort;
+
+        int port = 0;
+        for (int i = 0; i < nonZeroDigits.length(); ++i) {
+            CHAR ch = spec[nonZeroDigits.begin() + i];
+            if (!isPortDigit(ch))
+                return InvalidPort;
+            port *= 10;
+            port += static_cast<char>(ch) - '0';
+        }
+        if (port > 65535)
+            return InvalidPort;
+        return port;
+    }
+
+    static void extractFileName(const CHAR* spec, const URLComponent& path, URLComponent& fileName)
+    {
+        // Handle empty paths: they have no file names.
+        if (path.isEmptyOrInvalid()) {
+            fileName.reset();
+            return;
+        }
+
+        // Search backwards for a parameter, which is a normally unused field
+        // in a URL delimited by a semicolon. We parse the parameter as part of
+        // the path, but here, we don't want to count it. The last semicolon is
+        // the parameter.
+        int fileEnd = path.end();
+        for (int i = path.end() - 1; i > path.begin(); --i) {
+            if (spec[i] == ';') {
+                fileEnd = i;
+                break;
+            }
+        }
+
+        // Now search backwards from the filename end to the previous slash
+        // to find the beginning of the filename.
+        for (int i = fileEnd - 1; i >= path.begin(); --i) {
+            if (isURLSlash(spec[i])) {
+                // File name is everything following this character to the end
+                fileName = URLComponent::fromRange(i + 1, fileEnd);
+                return;
+            }
+        }
+
+        // No slash found, this means the input was degenerate (generally paths
+        // will start with a slash). Let's call everything the file name.
+        fileName = URLComponent::fromRange(path.begin(), fileEnd);
+    }
+
+    static bool extractQueryKeyValue(const CHAR* spec, URLComponent& query, URLComponent& key, URLComponent& value)
+    {
+        if (query.isEmptyOrInvalid())
+            return false;
+
+        int start = query.begin();
+        int current = start;
+        int end = query.end();
+
+        // We assume the beginning of the input is the beginning of the "key"
+        // and we skip to the end of it.
+        key.setBegin(current);
+        while (current < end && spec[current] != '&' && spec[current] != '=')
+            ++current;
+        key.setLength(current - key.begin());
+
+        // Skip the separator after the key (if any).
+        if (current < end && spec[current] == '=')
+            ++current;
+
+        // Find the value part.
+        value.setBegin(current);
+        while (current < end && spec[current] != '&')
+            ++current;
+        value.setLength(current - value.begin());
+
+        // Finally skip the next separator if any
+        if (current < end && spec[current] == '&')
+            ++current;
+
+        // Save the new query
+        query = URLComponent::fromRange(current, end);
+        return true;
+    }
+
+// FIXME: This should be protected or private.
+public:
+    // We treat slashes and backslashes the same for IE compatibility.
+    static inline bool isURLSlash(CHAR ch)
+    {
+        return ch == '/' || ch == '\\';
+    }
+
+    // Returns true if we should trim this character from the URL because it is
+    // a space or a control character.
+    static inline bool shouldTrimFromURL(CHAR ch)
+    {
+        return ch <= ' ';
+    }
+
+    // Given an already-initialized begin index and end index (the index after
+    // the last CHAR in spec), this shrinks the range to eliminate
+    // "should-be-trimmed" characters.
+    static inline void trimURL(const CHAR* spec, int& begin, int& end)
+    {
+        // Strip leading whitespace and control characters.
+        while (begin < end && shouldTrimFromURL(spec[begin]))
+            ++begin;
+
+        // Strip trailing whitespace and control characters. We need the >i
+        // test for when the input string is all blanks; we don't want to back
+        // past the input.
+        while (end > begin && shouldTrimFromURL(spec[end - 1]))
+            --end;
+    }
+
+    // Counts the number of consecutive slashes starting at the given offset
+    // in the given string of the given length.
+    static inline int consecutiveSlashes(const CHAR *string, int beginOffset, int stringLength)
+    {
+        int count = 0;
+        while (beginOffset + count < stringLength && isURLSlash(string[beginOffset + count]))
+            ++count;
+        return count;
+    }
+
+private:
+    // URLParser cannot be constructed.
+    URLParser();
+
+    // Returns true if the given character is a valid digit to use in a port.
+    static inline bool isPortDigit(CHAR ch)
+    {
+        return ch >= '0' && ch <= '9';
+    }
+
+    // Returns the offset of the next authority terminator in the input starting
+    // from startOffset. If no terminator is found, the return value will be equal
+    // to specLength.
+    static int nextAuthorityTerminator(const CHAR* spec, int startOffset, int specLength)
+    {
+        for (int i = startOffset; i < specLength; i++) {
+            if (isPossibleAuthorityTerminator(spec[i]))
+                return i;
+        }
+        return specLength; // Not found.
+    }
+
+    static void parseUserInfo(const CHAR* spec, const URLComponent& user, URLComponent& username, URLComponent& password)
+    {
+        // Find the first colon in the user section, which separates the
+        // username and password.
+        int colonOffset = 0;
+        while (colonOffset < user.length() && spec[user.begin() + colonOffset] != ':')
+            ++colonOffset;
+
+        if (colonOffset < user.length()) {
+            // Found separator: <username>:<password>
+            username = URLComponent(user.begin(), colonOffset);
+            password = URLComponent::fromRange(user.begin() + colonOffset + 1, user.begin() + user.length());
+        } else {
+            // No separator, treat everything as the username
+            username = user;
+            password = URLComponent();
+        }
+    }
+
+    static void parseServerInfo(const CHAR* spec, const URLComponent& serverInfo, URLComponent& host, URLComponent& port)
+    {
+        if (!serverInfo.length()) {
+            // No server info, host name is empty.
+            host.reset();
+            port.reset();
+            return;
+        }
+
+        // If the host starts with a left-bracket, assume the entire host is an
+        // IPv6 literal.  Otherwise, assume none of the host is an IPv6 literal.
+        // This assumption will be overridden if we find a right-bracket.
+        //
+        // Our IPv6 address canonicalization code requires both brackets to
+        // exist, but the ability to locate an incomplete address can still be
+        // useful.
+        int ipv6Terminator = spec[serverInfo.begin()] == '[' ? serverInfo.end() : -1;
+        int colon = -1;
+
+        // Find the last right-bracket, and the last colon.
+        for (int i = serverInfo.begin(); i < serverInfo.end(); i++) {
+            switch (spec[i]) {
+            case ']':
+                ipv6Terminator = i;
+                break;
+            case ':':
+                colon = i;
+                break;
+            default:
+                break;
+            }
+        }
+
+        if (colon > ipv6Terminator) {
+            // Found a port number: <hostname>:<port>
+            host = URLComponent::fromRange(serverInfo.begin(), colon);
+            if (!host.length())
+                host.reset();
+            port = URLComponent::fromRange(colon + 1, serverInfo.end());
+        } else {
+            // No port: <hostname>
+            host = serverInfo;
+            port.reset();
+        }
+    }
+};
+
+} // namespace WTF
+
+#endif // URLParser_h
diff --git a/wtf/url/src/URLQueryCanonicalizer.h b/wtf/url/src/URLQueryCanonicalizer.h
new file mode 100644 (file)
index 0000000..7740200
--- /dev/null
@@ -0,0 +1,107 @@
+// Copyright 2010, Google 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:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "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 THE COPYRIGHT
+// OWNER 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 URLQueryCanonicalizer_h
+#define URLQueryCanonicalizer_h
+
+#include "RawURLBuffer.h"
+#include "URLBuffer.h"
+#include "URLCharacterTypes.h"
+#include "URLComponent.h"
+#include "URLEscape.h"
+
+namespace WTF {
+
+template<typename InChar, typename OutChar, void convertCharset(const InChar*, int length, URLBuffer<char>&)>
+class URLQueryCanonicalizer {
+public:
+    static void canonicalize(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer, URLComponent& resultQuery)
+    {
+        if (query.length() < 0) {
+            resultQuery = URLComponent();
+            return;
+        }
+
+        buffer->append('?');
+        resultQuery.setBegin(buffer->length());
+        convertToQueryEncoding(spec, query, buffer);
+        resultQuery.setLength(buffer->length() - resultQuery.begin());
+    }
+
+private:
+    static bool isAllASCII(const InChar* spec, const URLComponent& query)
+    {
+        int end = query.end();
+        for (int i = query.begin(); i < end; ++i) {
+            if (static_cast<unsigned>(spec[i]) >= 0x80)
+                return false;
+        }
+        return true;
+    }
+
+#ifndef NDEBUG
+    static bool isRaw8Bit(const InChar* source, int length)
+    {
+        for (int i = source; i < length; ++i) {
+            if (source[i] & 0xFF != source[i])
+                return false;
+        }
+        return true;
+    }
+#endif
+
+    static void appendRaw8BitQueryString(const InChar* source, int length, URLBuffer<OutChar>* buffer)
+    {
+        ASSERT(isRaw8Bit(source, length));
+        for (int i = 0; i < length; ++i) {
+            if (!URLCharacterTypes::isQueryChar(source[i]))
+                appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), buffer);
+            else
+                buffer->append(static_cast<char>(source[i]));
+        }
+    }
+
+    static void convertToQueryEncoding(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer)
+    {
+        if (isAllASCII(spec, query)) {
+            appendRaw8BitQueryString(&spec[query.begin()], query.length(), buffer);
+            return;
+        }
+
+        RawURLBuffer<char, 1024> convertedQuery;
+        convertCharset(spec, query, convertedQuery);
+        appendRaw8BitQueryString(convertedQuery.data(), convertedQuery.length(), buffer);
+    }
+};
+
+}
+
+#endif
+
+
diff --git a/wtf/wince/FastMallocWinCE.h b/wtf/wince/FastMallocWinCE.h
new file mode 100644 (file)
index 0000000..d91a5f2
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2007-2009 Torch Mobile, 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
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WTF_FastMallocWinCE_h
+#define WTF_FastMallocWinCE_h
+
+#include <new.h>
+
+#ifdef __cplusplus
+#include <new>
+#include "MemoryManager.h"
+extern "C" {
+#endif
+
+void* fastMalloc(size_t n);
+void* fastCalloc(size_t n_elements, size_t element_size);
+void fastFree(void* p);
+void* fastRealloc(void* p, size_t n);
+void* fastZeroedMalloc(size_t n);
+// These functions return 0 if an allocation fails.
+void* tryFastMalloc(size_t n);
+void* tryFastZeroedMalloc(size_t n);
+void* tryFastCalloc(size_t n_elements, size_t element_size);
+void* tryFastRealloc(void* p, size_t n);
+char* fastStrDup(const char*);
+
+#ifndef NDEBUG
+void fastMallocForbid();
+void fastMallocAllow();
+#endif
+
+#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC
+
+#define malloc(n)                           fastMalloc(n)
+#define calloc(n_elements, element_size)    fastCalloc(n_elements, element_size)
+#define realloc(p, n)                       fastRealloc(p, n)
+#define free(p)                             fastFree(p)
+#define strdup(p)                           fastStrDup(p)
+
+#else
+
+#define strdup(p)                           _strdup(p)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC
+static inline void* __cdecl operator new(size_t s) { return fastMalloc(s); }
+static inline void __cdecl operator delete(void* p) { fastFree(p); }
+static inline void* __cdecl operator new[](size_t s) { return fastMalloc(s); }
+static inline void __cdecl operator delete[](void* p) { fastFree(p); }
+static inline void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+static inline void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
+static inline void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
+static inline void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
+#endif
+
+namespace WTF {
+    // This defines a type which holds an unsigned integer and is the same
+    // size as the minimally aligned memory allocation.
+    typedef unsigned long long AllocAlignmentInteger;
+
+    namespace Internal {
+        enum AllocType {                    // Start with an unusual number instead of zero, because zero is common.
+            AllocTypeMalloc = 0x375d6750,   // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc.
+            AllocTypeClassNew,              // Encompasses class operator new from FastAllocBase.
+            AllocTypeClassNewArray,         // Encompasses class operator new[] from FastAllocBase.
+            AllocTypeFastNew,               // Encompasses fastNew.
+            AllocTypeFastNewArray,          // Encompasses fastNewArray.
+            AllocTypeNew,                   // Encompasses global operator new.
+            AllocTypeNewArray               // Encompasses global operator new[].
+        };
+    }
+
+
+#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+
+    // Malloc validation is a scheme whereby a tag is attached to an
+    // allocation which identifies how it was originally allocated.
+    // This allows us to verify that the freeing operation matches the
+    // allocation operation. If memory is allocated with operator new[]
+    // but freed with free or delete, this system would detect that.
+    // In the implementation here, the tag is an integer prepended to
+    // the allocation memory which is assigned one of the AllocType
+    // enumeration values. An alternative implementation of this
+    // scheme could store the tag somewhere else or ignore it.
+    // Users of FastMalloc don't need to know or care how this tagging
+    // is implemented.
+
+    namespace Internal {
+
+        // Return the AllocType tag associated with the allocated block p.
+        inline AllocType fastMallocMatchValidationType(const void* p)
+        {
+            const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1;
+            return static_cast<AllocType>(*type);
+        }
+
+        // Return the address of the AllocType tag associated with the allocated block p.
+        inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p)
+        {
+            return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger));
+        }
+
+        // Set the AllocType tag to be associaged with the allocated block p.
+        inline void setFastMallocMatchValidationType(void* p, AllocType allocType)
+        {
+            AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1;
+            *type = static_cast<AllocAlignmentInteger>(allocType);
+        }
+
+        // Handle a detected alloc/free mismatch. By default this calls CRASH().
+        void fastMallocMatchFailed(void* p);
+
+    } // namespace Internal
+
+    // This is a higher level function which is used by FastMalloc-using code.
+    inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType)
+    {
+        if (!p)
+            return;
+
+        Internal::setFastMallocMatchValidationType(p, allocType);
+    }
+
+    // This is a higher level function which is used by FastMalloc-using code.
+    inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType)
+    {
+        if (!p)
+            return;
+
+        if (Internal::fastMallocMatchValidationType(p) != allocType)
+            Internal::fastMallocMatchFailed(p);
+        Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc);  // Set it to this so that fastFree thinks it's OK.
+    }
+
+#else
+
+    inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType)
+    {
+    }
+
+    inline void fastMallocMatchValidateFree(void*, Internal::AllocType)
+    {
+    }
+
+#endif
+
+} // namespace WTF
+
+#endif
+
+#endif // WTF_FastMallocWinCE_h
diff --git a/wtf/wince/FastMallocWince.h b/wtf/wince/FastMallocWince.h
deleted file mode 100644 (file)
index 37174f0..0000000
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *  Copyright (C) 2007-2009 Torch Mobile, 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
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- *  You should have received a copy of the GNU Library General Public License
- *  along with this library; see the file COPYING.LIB.  If not, write to
- *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- *  Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef FastMallocWince_h
-#define FastMallocWince_h
-
-#include <new.h>
-
-#ifdef __cplusplus
-#include <new>
-#include "MemoryManager.h"
-extern "C" {
-#endif
-
-void* fastMalloc(size_t n);
-void* fastCalloc(size_t n_elements, size_t element_size);
-void fastFree(void* p);
-void* fastRealloc(void* p, size_t n);
-void* fastZeroedMalloc(size_t n);
-// These functions return 0 if an allocation fails.
-void* tryFastMalloc(size_t n);
-void* tryFastZeroedMalloc(size_t n);
-void* tryFastCalloc(size_t n_elements, size_t element_size);
-void* tryFastRealloc(void* p, size_t n);
-char* fastStrDup(const char*);
-
-#ifndef NDEBUG
-void fastMallocForbid();
-void fastMallocAllow();
-#endif
-
-#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC
-
-#define malloc(n)                           fastMalloc(n)
-#define calloc(n_elements, element_size)    fastCalloc(n_elements, element_size)
-#define realloc(p, n)                       fastRealloc(p, n)
-#define free(p)                             fastFree(p)
-#define strdup(p)                           fastStrDup(p)
-
-#else
-
-#define strdup(p)                           _strdup(p)
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC
-static inline void* __cdecl operator new(size_t s) { return fastMalloc(s); }
-static inline void __cdecl operator delete(void* p) { fastFree(p); }
-static inline void* __cdecl operator new[](size_t s) { return fastMalloc(s); }
-static inline void __cdecl operator delete[](void* p) { fastFree(p); }
-static inline void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
-static inline void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); }
-static inline void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); }
-static inline void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); }
-#endif
-
-namespace WTF {
-    // This defines a type which holds an unsigned integer and is the same
-    // size as the minimally aligned memory allocation.
-    typedef unsigned long long AllocAlignmentInteger;
-
-    namespace Internal {
-        enum AllocType {                    // Start with an unusual number instead of zero, because zero is common.
-            AllocTypeMalloc = 0x375d6750,   // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc.
-            AllocTypeClassNew,              // Encompasses class operator new from FastAllocBase.
-            AllocTypeClassNewArray,         // Encompasses class operator new[] from FastAllocBase.
-            AllocTypeFastNew,               // Encompasses fastNew.
-            AllocTypeFastNewArray,          // Encompasses fastNewArray.
-            AllocTypeNew,                   // Encompasses global operator new.
-            AllocTypeNewArray               // Encompasses global operator new[].
-        };
-    }
-
-
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
-
-    // Malloc validation is a scheme whereby a tag is attached to an
-    // allocation which identifies how it was originally allocated.
-    // This allows us to verify that the freeing operation matches the
-    // allocation operation. If memory is allocated with operator new[]
-    // but freed with free or delete, this system would detect that.
-    // In the implementation here, the tag is an integer prepended to
-    // the allocation memory which is assigned one of the AllocType
-    // enumeration values. An alternative implementation of this
-    // scheme could store the tag somewhere else or ignore it.
-    // Users of FastMalloc don't need to know or care how this tagging
-    // is implemented.
-
-    namespace Internal {
-
-        // Return the AllocType tag associated with the allocated block p.
-        inline AllocType fastMallocMatchValidationType(const void* p)
-        {
-            const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1;
-            return static_cast<AllocType>(*type);
-        }
-
-        // Return the address of the AllocType tag associated with the allocated block p.
-        inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p)
-        {
-            return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger));
-        }
-
-        // Set the AllocType tag to be associaged with the allocated block p.
-        inline void setFastMallocMatchValidationType(void* p, AllocType allocType)
-        {
-            AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1;
-            *type = static_cast<AllocAlignmentInteger>(allocType);
-        }
-
-        // Handle a detected alloc/free mismatch. By default this calls CRASH().
-        void fastMallocMatchFailed(void* p);
-
-    } // namespace Internal
-
-    // This is a higher level function which is used by FastMalloc-using code.
-    inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType)
-    {
-        if (!p)
-            return;
-
-        Internal::setFastMallocMatchValidationType(p, allocType);
-    }
-
-    // This is a higher level function which is used by FastMalloc-using code.
-    inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType)
-    {
-        if (!p)
-            return;
-
-        if (Internal::fastMallocMatchValidationType(p) != allocType)
-            Internal::fastMallocMatchFailed(p);
-        Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc);  // Set it to this so that fastFree thinks it's OK.
-    }
-
-#else
-
-    inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType)
-    {
-    }
-
-    inline void fastMallocMatchValidateFree(void*, Internal::AllocType)
-    {
-    }
-
-#endif
-
-} // namespace WTF
-
-#endif
-
-#endif // FastMallocWince_h
-
diff --git a/wtf/wince/mt19937ar.c b/wtf/wince/mt19937ar.c
deleted file mode 100644 (file)
index 4715958..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-   A C-program for MT19937, with initialization improved 2002/1/26.
-   Coded by Takuji Nishimura and Makoto Matsumoto.
-
-   Before using, initialize the state by using init_genrand(seed)
-   or init_by_array(init_key, key_length).
-
-   Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
-   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.
-
-     3. The names of its contributors may not be used to endorse or promote
-        products derived from this software without specific prior written
-        permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   "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 THE COPYRIGHT OWNER 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.
-
-
-   Any feedback is very welcome.
-   http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
-   email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
-*/
-
-#include <stdio.h>
-
-/* Period parameters */
-#define N 624
-#define M 397
-#define MATRIX_A 0x9908b0dfUL   /* constant vector a */
-#define UPPER_MASK 0x80000000UL /* most significant w-r bits */
-#define LOWER_MASK 0x7fffffffUL /* least significant r bits */
-
-static unsigned long mt[N]; /* the array for the state vector  */
-static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
-
-/* initializes mt[N] with a seed */
-void init_genrand(unsigned long s)
-{
-    mt[0]= s & 0xffffffffUL;
-    for (mti=1; mti<N; mti++) {
-        mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
-        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
-        /* In the previous versions, MSBs of the seed affect   */
-        /* only MSBs of the array mt[].                        */
-        /* 2002/01/09 modified by Makoto Matsumoto             */
-        mt[mti] &= 0xffffffffUL;
-        /* for >32 bit machines */
-    }
-}
-
-/* initialize by an array with array-length */
-/* init_key is the array for initializing keys */
-/* key_length is its length */
-/* slight change for C++, 2004/2/26 */
-void init_by_array(unsigned long init_key[],int key_length)
-{
-    int i, j, k;
-    init_genrand(19650218UL);
-    i=1; j=0;
-    k = (N>key_length ? N : key_length);
-    for (; k; k--) {
-        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
-          + init_key[j] + j; /* non linear */
-        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
-        i++; j++;
-        if (i>=N) { mt[0] = mt[N-1]; i=1; }
-        if (j>=key_length) j=0;
-    }
-    for (k=N-1; k; k--) {
-        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
-          - i; /* non linear */
-        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
-        i++;
-        if (i>=N) { mt[0] = mt[N-1]; i=1; }
-    }
-
-    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
-}
-
-/* generates a random number on [0,0xffffffff]-interval */
-unsigned long genrand_int32(void)
-{
-    unsigned long y;
-    static unsigned long mag01[2]={0x0UL, MATRIX_A};
-    /* mag01[x] = x * MATRIX_A  for x=0,1 */
-
-    if (mti >= N) { /* generate N words at one time */
-        int kk;
-
-        if (mti == N+1)   /* if init_genrand() has not been called, */
-            init_genrand(5489UL); /* a default initial seed is used */
-
-        for (kk=0;kk<N-M;kk++) {
-            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
-            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
-        }
-        for (;kk<N-1;kk++) {
-            y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
-            mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
-        }
-        y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
-        mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
-
-        mti = 0;
-    }
-
-    y = mt[mti++];
-
-    /* Tempering */
-    y ^= (y >> 11);
-    y ^= (y << 7) & 0x9d2c5680UL;
-    y ^= (y << 15) & 0xefc60000UL;
-    y ^= (y >> 18);
-
-    return y;
-}
-
-/* generates a random number on [0,0x7fffffff]-interval */
-long genrand_int31(void)
-{
-    return (long)(genrand_int32()>>1);
-}
-
-/* generates a random number on [0,1]-real-interval */
-double genrand_real1(void)
-{
-    return genrand_int32()*(1.0/4294967295.0);
-    /* divided by 2^32-1 */
-}
-
-/* generates a random number on [0,1)-real-interval */
-double genrand_real2(void)
-{
-    return genrand_int32()*(1.0/4294967296.0);
-    /* divided by 2^32 */
-}
-
-/* generates a random number on (0,1)-real-interval */
-double genrand_real3(void)
-{
-    return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0);
-    /* divided by 2^32 */
-}
-
-/* generates a random number on [0,1) with 53-bit resolution*/
-double genrand_res53(void)
-{
-    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6;
-    return(a*67108864.0+b)*(1.0/9007199254740992.0);
-}
diff --git a/wtf/wtf.pri b/wtf/wtf.pri
new file mode 100644 (file)
index 0000000..10b41e4
--- /dev/null
@@ -0,0 +1,52 @@
+# wtf - qmake build info
+
+SOURCES += \
+    wtf/Assertions.cpp \
+    wtf/ByteArray.cpp \
+    wtf/CryptographicallyRandomNumber.cpp \
+    wtf/CurrentTime.cpp \
+    wtf/DateMath.cpp \
+    wtf/dtoa.cpp \
+    wtf/DecimalNumber.cpp \
+    wtf/FastMalloc.cpp \
+    wtf/gobject/GOwnPtr.cpp \
+    wtf/gobject/GRefPtr.cpp \
+    wtf/HashTable.cpp \
+    wtf/MD5.cpp \
+    wtf/MainThread.cpp \
+    wtf/NullPtr.cpp \
+    wtf/OSRandomSource.cpp \
+    wtf/qt/MainThreadQt.cpp \
+    wtf/qt/StringQt.cpp \
+    wtf/qt/ThreadingQt.cpp \
+    wtf/PageAllocationAligned.cpp \
+    wtf/PageBlock.cpp \
+    wtf/ParallelJobsGeneric.cpp \
+    wtf/RandomNumber.cpp \
+    wtf/RefCountedLeakCounter.cpp \
+    wtf/SHA1.cpp \
+    wtf/StackBounds.cpp \
+    wtf/TCSystemAlloc.cpp \
+    wtf/ThreadingNone.cpp \
+    wtf/Threading.cpp \
+    wtf/TypeTraits.cpp \
+    wtf/WTFThreadData.cpp \
+    wtf/text/AtomicString.cpp \
+    wtf/text/CString.cpp \
+    wtf/text/StringBuilder.cpp \
+    wtf/text/StringImpl.cpp \
+    wtf/text/StringStatics.cpp \
+    wtf/text/WTFString.cpp \
+    wtf/unicode/CollatorDefault.cpp \
+    wtf/unicode/icu/CollatorICU.cpp \
+    wtf/unicode/UTF8.cpp
+
+contains(DEFINES, USE_GSTREAMER=1) {
+    DEFINES += ENABLE_GLIB_SUPPORT=1
+    PKGCONFIG += glib-2.0 gio-2.0
+    CONFIG += link_pkgconfig
+}
+
+unix:!symbian: SOURCES += wtf/OSAllocatorPosix.cpp
+symbian: SOURCES += wtf/OSAllocatorSymbian.cpp
+win*|wince*: SOURCES += wtf/OSAllocatorWin.cpp
diff --git a/wtf/wx/StringWx.cpp b/wtf/wx/StringWx.cpp
new file mode 100644 (file)
index 0000000..d5f6c57
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2007 Vaclav Slavik, Kevin Ollivier <kevino@theolliviers.com>
+ *
+ * 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 COMPUTER, 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 COMPUTER, 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. 
+ */
+
+#include "config.h"
+
+// The wx headers must come first in this case, because the wtf/text headers
+// import windows.h, and we need to allow the wx headers to set its configuration
+// first.
+#include <wx/defs.h>
+#include <wx/string.h>
+
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+String::String(const wxString& wxstr)
+{
+#if !wxUSE_UNICODE
+    #error "This code only works in Unicode build of wxWidgets"
+#endif
+
+#if SIZEOF_WCHAR_T == 2
+
+    const UChar* str = wxstr.wc_str(); 
+    const size_t len = wxstr.length(); 
+
+#else // SIZEOF_WCHAR_T == 4
+
+    // NB: we can't simply use wxstr.mb_str(wxMBConvUTF16()) here because
+    //     the number of characters in UTF-16 encoding of the string may differ
+    //     from the number of UTF-32 values and we can't get the length from
+    //     returned buffer:
+
+#if defined(wxUSE_UNICODE_UTF8) && wxUSE_UNICODE_UTF8
+    // in wx3's UTF8 mode, wc_str() returns a buffer, not raw pointer
+    wxWCharBuffer wideString(wxstr.wc_str());
+#else
+    const wxChar *wideString = wxstr.wc_str();
+#endif
+    size_t wideLength = wxstr.length();
+
+    wxMBConvUTF16 conv;
+
+    const size_t utf16bufLen = conv.FromWChar(0, 0, wideString, wideLength); 
+    wxCharBuffer utf16buf(utf16bufLen); 
+
+    const UChar* str = (const UChar*)utf16buf.data(); 
+    size_t len = conv.FromWChar(utf16buf.data(), utf16bufLen, wideString, wideLength) / 2; 
+
+#endif // SIZEOF_WCHAR_T == 2
+
+    m_impl = StringImpl::create(str, len);
+
+}
+
+String::operator wxString() const
+{
+    return wxString(utf8().data(), wxConvUTF8);
+}
+
+} // namespace WTF
diff --git a/yarr/RegexCompiler.cpp b/yarr/RegexCompiler.cpp
deleted file mode 100644 (file)
index 9fbe213..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- * Copyright (C) 2009 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. 
- */
-
-#include "config.h"
-#include "RegexCompiler.h"
-
-#include "RegexInterpreter.h"
-#include "RegexPattern.h"
-#include <wtf/Vector.h>
-
-#if ENABLE(YARR)
-
-using namespace WTF;
-
-namespace JSC { namespace Yarr {
-
-#include "RegExpJitTables.h"
-
-class CharacterClassConstructor {
-public:
-    CharacterClassConstructor(bool isCaseInsensitive = false)
-        : m_isCaseInsensitive(isCaseInsensitive)
-    {
-    }
-    
-    void reset()
-    {
-        m_matches.clear();
-        m_ranges.clear();
-        m_matchesUnicode.clear();
-        m_rangesUnicode.clear();
-    }
-
-    void append(const CharacterClass* other)
-    {
-        for (size_t i = 0; i < other->m_matches.size(); ++i)
-            addSorted(m_matches, other->m_matches[i]);
-        for (size_t i = 0; i < other->m_ranges.size(); ++i)
-            addSortedRange(m_ranges, other->m_ranges[i].begin, other->m_ranges[i].end);
-        for (size_t i = 0; i < other->m_matchesUnicode.size(); ++i)
-            addSorted(m_matchesUnicode, other->m_matchesUnicode[i]);
-        for (size_t i = 0; i < other->m_rangesUnicode.size(); ++i)
-            addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end);
-    }
-
-    void putChar(UChar ch)
-    {
-        if (ch <= 0x7f) {
-            if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
-                addSorted(m_matches, toASCIIUpper(ch));
-                addSorted(m_matches, toASCIILower(ch));
-            } else
-                addSorted(m_matches, ch);
-        } else {
-            UChar upper, lower;
-            if (m_isCaseInsensitive && ((upper = Unicode::toUpper(ch)) != (lower = Unicode::toLower(ch)))) {
-                addSorted(m_matchesUnicode, upper);
-                addSorted(m_matchesUnicode, lower);
-            } else
-                addSorted(m_matchesUnicode, ch);
-        }
-    }
-
-    // returns true if this character has another case, and 'ch' is the upper case form.
-    static inline bool isUnicodeUpper(UChar ch)
-    {
-        return ch != Unicode::toLower(ch);
-    }
-
-    // returns true if this character has another case, and 'ch' is the lower case form.
-    static inline bool isUnicodeLower(UChar ch)
-    {
-        return ch != Unicode::toUpper(ch);
-    }
-
-    void putRange(UChar lo, UChar hi)
-    {
-        if (lo <= 0x7f) {
-            char asciiLo = lo;
-            char asciiHi = std::min(hi, (UChar)0x7f);
-            addSortedRange(m_ranges, lo, asciiHi);
-            
-            if (m_isCaseInsensitive) {
-                if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
-                    addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A'));
-                if ((asciiLo <= 'z') && (asciiHi >= 'a'))
-                    addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a'));
-            }
-        }
-        if (hi >= 0x80) {
-            uint32_t unicodeCurr = std::max(lo, (UChar)0x80);
-            addSortedRange(m_rangesUnicode, unicodeCurr, hi);
-            
-            if (m_isCaseInsensitive) {
-                while (unicodeCurr <= hi) {
-                    // If the upper bound of the range (hi) is 0xffff, the increments to
-                    // unicodeCurr in this loop may take it to 0x10000.  This is fine
-                    // (if so we won't re-enter the loop, since the loop condition above
-                    // will definitely fail) - but this does mean we cannot use a UChar
-                    // to represent unicodeCurr, we must use a 32-bit value instead.
-                    ASSERT(unicodeCurr <= 0xffff);
-
-                    if (isUnicodeUpper(unicodeCurr)) {
-                        UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr);
-                        UChar lowerCaseRangeEnd = lowerCaseRangeBegin;
-                        while ((++unicodeCurr <= hi) && isUnicodeUpper(unicodeCurr) && (Unicode::toLower(unicodeCurr) == (lowerCaseRangeEnd + 1)))
-                            lowerCaseRangeEnd++;
-                        addSortedRange(m_rangesUnicode, lowerCaseRangeBegin, lowerCaseRangeEnd);
-                    } else if (isUnicodeLower(unicodeCurr)) {
-                        UChar upperCaseRangeBegin = Unicode::toUpper(unicodeCurr);
-                        UChar upperCaseRangeEnd = upperCaseRangeBegin;
-                        while ((++unicodeCurr <= hi) && isUnicodeLower(unicodeCurr) && (Unicode::toUpper(unicodeCurr) == (upperCaseRangeEnd + 1)))
-                            upperCaseRangeEnd++;
-                        addSortedRange(m_rangesUnicode, upperCaseRangeBegin, upperCaseRangeEnd);
-                    } else
-                        ++unicodeCurr;
-                }
-            }
-        }
-    }
-
-    CharacterClass* charClass()
-    {
-        CharacterClass* characterClass = new CharacterClass(0);
-
-        characterClass->m_matches.append(m_matches);
-        characterClass->m_ranges.append(m_ranges);
-        characterClass->m_matchesUnicode.append(m_matchesUnicode);
-        characterClass->m_rangesUnicode.append(m_rangesUnicode);
-
-        reset();
-
-        return characterClass;
-    }
-
-private:
-    void addSorted(Vector<UChar>& matches, UChar ch)
-    {
-        unsigned pos = 0;
-        unsigned range = matches.size();
-
-        // binary chop, find position to insert char.
-        while (range) {
-            unsigned index = range >> 1;
-
-            int val = matches[pos+index] - ch;
-            if (!val)
-                return;
-            else if (val > 0)
-                range = index;
-            else {
-                pos += (index+1);
-                range -= (index+1);
-            }
-        }
-        
-        if (pos == matches.size())
-            matches.append(ch);
-        else
-            matches.insert(pos, ch);
-    }
-
-    void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi)
-    {
-        unsigned end = ranges.size();
-        
-        // Simple linear scan - I doubt there are that many ranges anyway...
-        // feel free to fix this with something faster (eg binary chop).
-        for (unsigned i = 0; i < end; ++i) {
-            // does the new range fall before the current position in the array
-            if (hi < ranges[i].begin) {
-                // optional optimization: concatenate appending ranges? - may not be worthwhile.
-                if (hi == (ranges[i].begin - 1)) {
-                    ranges[i].begin = lo;
-                    return;
-                }
-                ranges.insert(i, CharacterRange(lo, hi));
-                return;
-            }
-            // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the begining
-            // If the new range start at or before the end of the last range, then the overlap (if it starts one after the
-            // end of the last range they concatenate, which is just as good.
-            if (lo <= (ranges[i].end + 1)) {
-                // found an intersect! we'll replace this entry in the array.
-                ranges[i].begin = std::min(ranges[i].begin, lo);
-                ranges[i].end = std::max(ranges[i].end, hi);
-
-                // now check if the new range can subsume any subsequent ranges.
-                unsigned next = i+1;
-                // each iteration of the loop we will either remove something from the list, or break the loop.
-                while (next < ranges.size()) {
-                    if (ranges[next].begin <= (ranges[i].end + 1)) {
-                        // the next entry now overlaps / concatenates this one.
-                        ranges[i].end = std::max(ranges[i].end, ranges[next].end);
-                        ranges.remove(next);
-                    } else
-                        break;
-                }
-                
-                return;
-            }
-        }
-
-        // CharacterRange comes after all existing ranges.
-        ranges.append(CharacterRange(lo, hi));
-    }
-
-    bool m_isCaseInsensitive;
-
-    Vector<UChar> m_matches;
-    Vector<CharacterRange> m_ranges;
-    Vector<UChar> m_matchesUnicode;
-    Vector<CharacterRange> m_rangesUnicode;
-};
-
-class RegexPatternConstructor {
-public:
-    RegexPatternConstructor(RegexPattern& pattern)
-        : m_pattern(pattern)
-        , m_characterClassConstructor(pattern.m_ignoreCase)
-    {
-    }
-
-    ~RegexPatternConstructor()
-    {
-    }
-
-    void reset()
-    {
-        m_pattern.reset();
-        m_characterClassConstructor.reset();
-    }
-    
-    void assertionBOL()
-    {
-        m_alternative->m_terms.append(PatternTerm::BOL());
-    }
-    void assertionEOL()
-    {
-        m_alternative->m_terms.append(PatternTerm::EOL());
-    }
-    void assertionWordBoundary(bool invert)
-    {
-        m_alternative->m_terms.append(PatternTerm::WordBoundary(invert));
-    }
-
-    void atomPatternCharacter(UChar ch)
-    {
-        // We handle case-insensitive checking of unicode characters which do have both
-        // cases by handling them as if they were defined using a CharacterClass.
-        if (m_pattern.m_ignoreCase && !isASCII(ch) && (Unicode::toUpper(ch) != Unicode::toLower(ch))) {
-            atomCharacterClassBegin();
-            atomCharacterClassAtom(ch);
-            atomCharacterClassEnd();
-        } else
-            m_alternative->m_terms.append(PatternTerm(ch));
-    }
-
-    void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
-    {
-        switch (classID) {
-        case DigitClassID:
-            m_alternative->m_terms.append(PatternTerm(m_pattern.digitsCharacterClass(), invert));
-            break;
-        case SpaceClassID:
-            m_alternative->m_terms.append(PatternTerm(m_pattern.spacesCharacterClass(), invert));
-            break;
-        case WordClassID:
-            m_alternative->m_terms.append(PatternTerm(m_pattern.wordcharCharacterClass(), invert));
-            break;
-        case NewlineClassID:
-            m_alternative->m_terms.append(PatternTerm(m_pattern.newlineCharacterClass(), invert));
-            break;
-        }
-    }
-
-    void atomCharacterClassBegin(bool invert = false)
-    {
-        m_invertCharacterClass = invert;
-    }
-
-    void atomCharacterClassAtom(UChar ch)
-    {
-        m_characterClassConstructor.putChar(ch);
-    }
-
-    void atomCharacterClassRange(UChar begin, UChar end)
-    {
-        m_characterClassConstructor.putRange(begin, end);
-    }
-
-    void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
-    {
-        ASSERT(classID != NewlineClassID);
-
-        switch (classID) {
-        case DigitClassID:
-            m_characterClassConstructor.append(invert ? m_pattern.nondigitsCharacterClass() : m_pattern.digitsCharacterClass());
-            break;
-        
-        case SpaceClassID:
-            m_characterClassConstructor.append(invert ? m_pattern.nonspacesCharacterClass() : m_pattern.spacesCharacterClass());
-            break;
-        
-        case WordClassID:
-            m_characterClassConstructor.append(invert ? m_pattern.nonwordcharCharacterClass() : m_pattern.wordcharCharacterClass());
-            break;
-        
-        default:
-            ASSERT_NOT_REACHED();
-        }
-    }
-
-    void atomCharacterClassEnd()
-    {
-        CharacterClass* newCharacterClass = m_characterClassConstructor.charClass();
-        m_pattern.m_userCharacterClasses.append(newCharacterClass);
-        m_alternative->m_terms.append(PatternTerm(newCharacterClass, m_invertCharacterClass));
-    }
-
-    void atomParenthesesSubpatternBegin(bool capture = true)
-    {
-        unsigned subpatternId = m_pattern.m_numSubpatterns + 1;
-        if (capture)
-            m_pattern.m_numSubpatterns++;
-
-        PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
-        m_pattern.m_disjunctions.append(parenthesesDisjunction);
-        m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture));
-        m_alternative = parenthesesDisjunction->addNewAlternative();
-    }
-
-    void atomParentheticalAssertionBegin(bool invert = false)
-    {
-        PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
-        m_pattern.m_disjunctions.append(parenthesesDisjunction);
-        m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, invert));
-        m_alternative = parenthesesDisjunction->addNewAlternative();
-    }
-
-    void atomParenthesesEnd()
-    {
-        ASSERT(m_alternative->m_parent);
-        ASSERT(m_alternative->m_parent->m_parent);
-        m_alternative = m_alternative->m_parent->m_parent;
-        
-        m_alternative->lastTerm().parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
-    }
-
-    void atomBackReference(unsigned subpatternId)
-    {
-        ASSERT(subpatternId);
-        m_pattern.m_shouldFallBack = true;
-        m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, subpatternId);
-
-        if (subpatternId > m_pattern.m_numSubpatterns) {
-            m_alternative->m_terms.append(PatternTerm::ForwardReference());
-            return;
-        }
-
-        PatternAlternative* currentAlternative = m_alternative;
-        ASSERT(currentAlternative);
-
-        // Note to self: if we waited until the AST was baked, we could also remove forwards refs 
-        while ((currentAlternative = currentAlternative->m_parent->m_parent)) {
-            PatternTerm& term = currentAlternative->lastTerm();
-            ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion));
-
-            if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.invertOrCapture && (subpatternId == term.subpatternId)) {
-                m_alternative->m_terms.append(PatternTerm::ForwardReference());
-                return;
-            }
-        }
-
-        m_alternative->m_terms.append(PatternTerm(subpatternId));
-    }
-
-    PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction)
-    {
-        PatternDisjunction* newDisjunction = new PatternDisjunction();
-
-        newDisjunction->m_parent = disjunction->m_parent;
-        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
-            PatternAlternative* alternative = disjunction->m_alternatives[alt];
-            PatternAlternative* newAlternative = newDisjunction->addNewAlternative();
-            for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
-                newAlternative->m_terms.append(copyTerm(alternative->m_terms[i]));
-        }
-
-        m_pattern.m_disjunctions.append(newDisjunction);
-        return newDisjunction;
-    }
-
-    PatternTerm copyTerm(PatternTerm& term)
-    {
-        if ((term.type != PatternTerm::TypeParenthesesSubpattern) && (term.type != PatternTerm::TypeParentheticalAssertion))
-            return PatternTerm(term);
-
-        PatternTerm termCopy = term;
-        termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction);
-        return termCopy;
-    }
-
-    void quantifyAtom(unsigned min, unsigned max, bool greedy)
-    {
-        ASSERT(min <= max);
-        ASSERT(m_alternative->m_terms.size());
-
-        if (!max) {
-            m_alternative->removeLastTerm();
-            return;
-        }
-
-        PatternTerm& term = m_alternative->lastTerm();
-        ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
-        ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));
-
-        // For any assertion with a zero minimum, not matching is valid and has no effect,
-        // remove it.  Otherwise, we need to match as least once, but there is no point
-        // matching more than once, so remove the quantifier.  It is not entirely clear
-        // from the spec whether or not this behavior is correct, but I believe this
-        // matches Firefox. :-/
-        if (term.type == PatternTerm::TypeParentheticalAssertion) {
-            if (!min)
-                m_alternative->removeLastTerm();
-            return;
-        }
-
-        if (max > 1 && term.type == PatternTerm::TypeParenthesesSubpattern)
-            m_pattern.m_shouldFallBack = true;
-
-        if (min == 0)
-            term.quantify(max, greedy   ? QuantifierGreedy : QuantifierNonGreedy);
-        else if (min == max)
-            term.quantify(min, QuantifierFixedCount);
-        else {
-            term.quantify(min, QuantifierFixedCount);
-            m_alternative->m_terms.append(copyTerm(term));
-            // NOTE: this term is interesting from an analysis perspective, in that it can be ignored.....
-            m_alternative->lastTerm().quantify((max == UINT_MAX) ? max : max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy);
-            if (m_alternative->lastTerm().type == PatternTerm::TypeParenthesesSubpattern)
-                m_alternative->lastTerm().parentheses.isCopy = true;
-        }
-    }
-
-    void disjunction()
-    {
-        m_alternative = m_alternative->m_parent->addNewAlternative();
-    }
-
-    void regexBegin()
-    {
-        m_pattern.m_body = new PatternDisjunction();
-        m_alternative = m_pattern.m_body->addNewAlternative();
-        m_pattern.m_disjunctions.append(m_pattern.m_body);
-    }
-    void regexEnd()
-    {
-    }
-    void regexError()
-    {
-    }
-
-    unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition)
-    {
-        alternative->m_hasFixedSize = true;
-        unsigned currentInputPosition = initialInputPosition;
-
-        for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
-            PatternTerm& term = alternative->m_terms[i];
-
-            switch (term.type) {
-            case PatternTerm::TypeAssertionBOL:
-            case PatternTerm::TypeAssertionEOL:
-            case PatternTerm::TypeAssertionWordBoundary:
-                term.inputPosition = currentInputPosition;
-                break;
-
-            case PatternTerm::TypeBackReference:
-                term.inputPosition = currentInputPosition;
-                term.frameLocation = currentCallFrameSize;
-                currentCallFrameSize += RegexStackSpaceForBackTrackInfoBackReference;
-                alternative->m_hasFixedSize = false;
-                break;
-
-            case PatternTerm::TypeForwardReference:
-                break;
-
-            case PatternTerm::TypePatternCharacter:
-                term.inputPosition = currentInputPosition;
-                if (term.quantityType != QuantifierFixedCount) {
-                    term.frameLocation = currentCallFrameSize;
-                    currentCallFrameSize += RegexStackSpaceForBackTrackInfoPatternCharacter;
-                    alternative->m_hasFixedSize = false;
-                } else
-                    currentInputPosition += term.quantityCount;
-                break;
-
-            case PatternTerm::TypeCharacterClass:
-                term.inputPosition = currentInputPosition;
-                if (term.quantityType != QuantifierFixedCount) {
-                    term.frameLocation = currentCallFrameSize;
-                    currentCallFrameSize += RegexStackSpaceForBackTrackInfoCharacterClass;
-                    alternative->m_hasFixedSize = false;
-                } else
-                    currentInputPosition += term.quantityCount;
-                break;
-
-            case PatternTerm::TypeParenthesesSubpattern:
-                // Note: for fixed once parentheses we will ensure at least the minimum is available; others are on their own.
-                term.frameLocation = currentCallFrameSize;
-                if ((term.quantityCount == 1) && !term.parentheses.isCopy) {
-                    if (term.quantityType == QuantifierFixedCount) {
-                        currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
-                        currentInputPosition += term.parentheses.disjunction->m_minimumSize;
-                    } else {
-                        currentCallFrameSize += RegexStackSpaceForBackTrackInfoParenthesesOnce;
-                        currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
-                    }
-                    term.inputPosition = currentInputPosition;
-                } else {
-                    term.inputPosition = currentInputPosition;
-                    setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition);
-                    currentCallFrameSize += RegexStackSpaceForBackTrackInfoParentheses;
-                }
-                // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length.
-                alternative->m_hasFixedSize = false;
-                break;
-
-            case PatternTerm::TypeParentheticalAssertion:
-                term.inputPosition = currentInputPosition;
-                term.frameLocation = currentCallFrameSize;
-                currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + RegexStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
-                break;
-            }
-        }
-
-        alternative->m_minimumSize = currentInputPosition - initialInputPosition;
-        return currentCallFrameSize;
-    }
-
-    unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition)
-    {
-        if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
-            initialCallFrameSize += RegexStackSpaceForBackTrackInfoAlternative;
-
-        unsigned minimumInputSize = UINT_MAX;
-        unsigned maximumCallFrameSize = 0;
-        bool hasFixedSize = true;
-
-        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
-            PatternAlternative* alternative = disjunction->m_alternatives[alt];
-            unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition);
-            minimumInputSize = min(minimumInputSize, alternative->m_minimumSize);
-            maximumCallFrameSize = max(maximumCallFrameSize, currentAlternativeCallFrameSize);
-            hasFixedSize &= alternative->m_hasFixedSize;
-        }
-        
-        ASSERT(minimumInputSize != UINT_MAX);
-        ASSERT(maximumCallFrameSize >= initialCallFrameSize);
-
-        disjunction->m_hasFixedSize = hasFixedSize;
-        disjunction->m_minimumSize = minimumInputSize;
-        disjunction->m_callFrameSize = maximumCallFrameSize;
-        return maximumCallFrameSize;
-    }
-
-    void setupOffsets()
-    {
-        setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
-    }
-
-private:
-    RegexPattern& m_pattern;
-    PatternAlternative* m_alternative;
-    CharacterClassConstructor m_characterClassConstructor;
-    bool m_invertCharacterClass;
-};
-
-
-const char* compileRegex(const UString& patternString, RegexPattern& pattern)
-{
-    RegexPatternConstructor constructor(pattern);
-
-    if (const char* error = parse(constructor, patternString))
-        return error;
-    
-    // If the pattern contains illegal backreferences reset & reparse.
-    // Quoting Netscape's "What's new in JavaScript 1.2",
-    //      "Note: if the number of left parentheses is less than the number specified
-    //       in \#, the \# is taken as an octal escape as described in the next row."
-    if (pattern.containsIllegalBackReference()) {
-        unsigned numSubpatterns = pattern.m_numSubpatterns;
-
-        constructor.reset();
-#if !ASSERT_DISABLED
-        const char* error =
-#endif
-            parse(constructor, patternString, numSubpatterns);
-
-        ASSERT(!error);
-        ASSERT(numSubpatterns == pattern.m_numSubpatterns);
-    }
-
-    constructor.setupOffsets();
-
-    return false;
-};
-
-
-} }
-
-#endif
diff --git a/yarr/RegexCompiler.h b/yarr/RegexCompiler.h
deleted file mode 100644 (file)
index 9d2443a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2009 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 RegexCompiler_h
-#define RegexCompiler_h
-
-#if ENABLE(YARR)
-
-#include "RegexParser.h"
-#include "RegexPattern.h"
-#include <wtf/unicode/Unicode.h>
-
-namespace JSC { namespace Yarr {
-
-const char* compileRegex(const UString& patternString, RegexPattern& pattern);
-
-} } // namespace JSC::Yarr
-
-#endif
-
-#endif // RegexCompiler_h
diff --git a/yarr/RegexInterpreter.cpp b/yarr/RegexInterpreter.cpp
deleted file mode 100644 (file)
index 647b20a..0000000
+++ /dev/null
@@ -1,1607 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#include "config.h"
-#include "RegexInterpreter.h"
-
-#include "RegexCompiler.h"
-#include "RegexPattern.h"
-
-#ifndef NDEBUG
-#include <stdio.h>
-#endif
-
-#if ENABLE(YARR)
-
-using namespace WTF;
-
-namespace JSC { namespace Yarr {
-
-class Interpreter {
-public:
-    struct ParenthesesDisjunctionContext;
-
-    struct BackTrackInfoPatternCharacter {
-        uintptr_t matchAmount;
-    };
-    struct BackTrackInfoCharacterClass {
-        uintptr_t matchAmount;
-    };
-    struct BackTrackInfoBackReference {
-        uintptr_t begin; // Not really needed for greedy quantifiers.
-        uintptr_t matchAmount; // Not really needed for fixed quantifiers.
-    };
-    struct BackTrackInfoAlternative {
-        uintptr_t offset;
-    };
-    struct BackTrackInfoParentheticalAssertion {
-        uintptr_t begin;
-    };
-    struct BackTrackInfoParenthesesOnce {
-        uintptr_t inParentheses;
-    };
-    struct BackTrackInfoParentheses {
-        uintptr_t matchAmount;
-        ParenthesesDisjunctionContext* lastContext;
-        uintptr_t prevBegin;
-        uintptr_t prevEnd;
-    };
-
-    static inline void appendParenthesesDisjunctionContext(BackTrackInfoParentheses* backTrack, ParenthesesDisjunctionContext* context)
-    {
-        context->next = backTrack->lastContext;
-        backTrack->lastContext = context;
-        ++backTrack->matchAmount;
-    }
-
-    static inline void popParenthesesDisjunctionContext(BackTrackInfoParentheses* backTrack)
-    {
-        ASSERT(backTrack->matchAmount);
-        ASSERT(backTrack->lastContext);
-        backTrack->lastContext = backTrack->lastContext->next;
-        --backTrack->matchAmount;
-    }
-
-    struct DisjunctionContext
-    {
-        DisjunctionContext()
-            : term(0)
-        {
-        }
-
-        void* operator new(size_t, void* where)
-        {
-            return where;
-        }
-
-        int term;
-        unsigned matchBegin;
-        unsigned matchEnd;
-        uintptr_t frame[1];
-    };
-
-    DisjunctionContext* allocDisjunctionContext(ByteDisjunction* disjunction)
-    {
-        return new(malloc(sizeof(DisjunctionContext) + (disjunction->m_frameSize - 1) * sizeof(uintptr_t))) DisjunctionContext();
-    }
-
-    void freeDisjunctionContext(DisjunctionContext* context)
-    {
-        free(context);
-    }
-
-    struct ParenthesesDisjunctionContext
-    {
-        ParenthesesDisjunctionContext(int* output, ByteTerm& term)
-            : next(0)
-        {
-            unsigned firstSubpatternId = term.atom.subpatternId;
-            unsigned numNestedSubpatterns = term.atom.parenthesesDisjunction->m_numSubpatterns;
-
-            for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) {
-                subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
-                output[(firstSubpatternId << 1) + i] = -1;
-            }
-
-            new(getDisjunctionContext(term)) DisjunctionContext();
-        }
-
-        void* operator new(size_t, void* where)
-        {
-            return where;
-        }
-
-        void restoreOutput(int* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns)
-        {
-            for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
-                output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
-        }
-
-        DisjunctionContext* getDisjunctionContext(ByteTerm& term)
-        {
-            return reinterpret_cast<DisjunctionContext*>(&(subpatternBackup[term.atom.parenthesesDisjunction->m_numSubpatterns << 1]));
-        }
-
-        ParenthesesDisjunctionContext* next;
-        int subpatternBackup[1];
-    };
-
-    ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, int* output, ByteTerm& term)
-    {
-        return new(malloc(sizeof(ParenthesesDisjunctionContext) + (((term.atom.parenthesesDisjunction->m_numSubpatterns << 1) - 1) * sizeof(int)) + sizeof(DisjunctionContext) + (disjunction->m_frameSize - 1) * sizeof(uintptr_t))) ParenthesesDisjunctionContext(output, term);
-    }
-
-    void freeParenthesesDisjunctionContext(ParenthesesDisjunctionContext* context)
-    {
-        free(context);
-    }
-
-    class InputStream {
-    public:
-        InputStream(const UChar* input, unsigned start, unsigned length)
-            : input(input)
-            , pos(start)
-            , length(length)
-        {
-        }
-
-        void next()
-        {
-            ++pos;
-        }
-
-        void rewind(unsigned amount)
-        {
-            ASSERT(pos >= amount);
-            pos -= amount;
-        }
-
-        int read()
-        {
-            ASSERT(pos < length);
-            if (pos < length)
-                return input[pos];
-            return -1;
-        }
-
-        int readChecked(int position)
-        {
-            ASSERT(position < 0);
-            ASSERT((unsigned)-position <= pos);
-            unsigned p = pos + position;
-            ASSERT(p < length);
-            return input[p];
-        }
-
-        int reread(unsigned from)
-        {
-            ASSERT(from < length);
-            return input[from];
-        }
-
-        int prev()
-        {
-            ASSERT(!(pos > length));
-            if (pos && length)
-                return input[pos - 1];
-            return -1;
-        }
-
-        unsigned getPos()
-        {
-            return pos;
-        }
-
-        void setPos(unsigned p)
-        {
-            pos = p;
-        }
-
-        bool atStart()
-        {
-            return pos == 0;
-        }
-
-        bool atEnd()
-        {
-            return pos == length;
-        }
-
-        bool checkInput(int count)
-        {
-            if ((pos + count) <= length) {
-                pos += count;
-                return true;
-            } else
-                return false;
-        }
-
-        void uncheckInput(int count)
-        {
-            pos -= count;
-        }
-
-        bool atStart(int position)
-        {
-            return (pos + position) == 0;
-        }
-
-        bool atEnd(int position)
-        {
-            return (pos + position) == length;
-        }
-
-    private:
-        const UChar* input;
-        unsigned pos;
-        unsigned length;
-    };
-
-    bool testCharacterClass(CharacterClass* characterClass, int ch)
-    {
-        if (ch & 0xFF80) {
-            for (unsigned i = 0; i < characterClass->m_matchesUnicode.size(); ++i)
-                if (ch == characterClass->m_matchesUnicode[i])
-                    return true;
-            for (unsigned i = 0; i < characterClass->m_rangesUnicode.size(); ++i)
-                if ((ch >= characterClass->m_rangesUnicode[i].begin) && (ch <= characterClass->m_rangesUnicode[i].end))
-                    return true;
-        } else {
-            for (unsigned i = 0; i < characterClass->m_matches.size(); ++i)
-                if (ch == characterClass->m_matches[i])
-                    return true;
-            for (unsigned i = 0; i < characterClass->m_ranges.size(); ++i)
-                if ((ch >= characterClass->m_ranges[i].begin) && (ch <= characterClass->m_ranges[i].end))
-                    return true;
-        }
-
-        return false;
-    }
-
-    bool checkCharacter(int testChar, int inputPosition)
-    {
-        return testChar == input.readChecked(inputPosition);
-    }
-
-    bool checkCasedCharacter(int loChar, int hiChar, int inputPosition)
-    {
-        int ch = input.readChecked(inputPosition);
-        return (loChar == ch) || (hiChar == ch);
-    }
-
-    bool checkCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition)
-    {
-        bool match = testCharacterClass(characterClass, input.readChecked(inputPosition));
-        return invert ? !match : match;
-    }
-
-    bool tryConsumeBackReference(int matchBegin, int matchEnd, int inputOffset)
-    {
-        int matchSize = matchEnd - matchBegin;
-
-        if (!input.checkInput(matchSize))
-            return false;
-
-        for (int i = 0; i < matchSize; ++i) {
-            if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) {
-                input.uncheckInput(matchSize);
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    bool matchAssertionBOL(ByteTerm& term)
-    {
-        return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition - 1)));
-    }
-
-    bool matchAssertionEOL(ByteTerm& term)
-    {
-        if (term.inputPosition)
-            return (input.atEnd(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition)));
-        else
-            return (input.atEnd()) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.read()));
-    }
-
-    bool matchAssertionWordBoundary(ByteTerm& term)
-    {
-        bool prevIsWordchar = !input.atStart(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition - 1));
-        bool readIsWordchar;
-        if (term.inputPosition)
-            readIsWordchar = !input.atEnd(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition));
-        else
-            readIsWordchar = !input.atEnd() && testCharacterClass(pattern->wordcharCharacterClass, input.read());
-
-        bool wordBoundary = prevIsWordchar != readIsWordchar;
-        return term.invert() ? !wordBoundary : wordBoundary;
-    }
-
-    bool backtrackPatternCharacter(ByteTerm& term, DisjunctionContext* context)
-    {
-        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount:
-            break;
-
-        case QuantifierGreedy:
-            if (backTrack->matchAmount) {
-                --backTrack->matchAmount;
-                input.uncheckInput(1);
-                return true;
-            }
-            break;
-
-        case QuantifierNonGreedy:
-            if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
-                ++backTrack->matchAmount;
-                if (checkCharacter(term.atom.patternCharacter, term.inputPosition - 1))
-                    return true;
-            }
-            input.uncheckInput(backTrack->matchAmount);
-            break;
-        }
-
-        return false;
-    }
-
-    bool backtrackPatternCasedCharacter(ByteTerm& term, DisjunctionContext* context)
-    {
-        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount:
-            break;
-
-        case QuantifierGreedy:
-            if (backTrack->matchAmount) {
-                --backTrack->matchAmount;
-                input.uncheckInput(1);
-                return true;
-            }
-            break;
-
-        case QuantifierNonGreedy:
-            if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
-                ++backTrack->matchAmount;
-                if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition - 1))
-                    return true;
-            }
-            input.uncheckInput(backTrack->matchAmount);
-            break;
-        }
-
-        return false;
-    }
-
-    bool matchCharacterClass(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeCharacterClass);
-        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount: {
-            for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
-                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + matchAmount))
-                    return false;
-            }
-            return true;
-        }
-
-        case QuantifierGreedy: {
-            unsigned matchAmount = 0;
-            while ((matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
-                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1)) {
-                    input.uncheckInput(1);
-                    break;
-                }
-                ++matchAmount;
-            }
-            backTrack->matchAmount = matchAmount;
-
-            return true;
-        }
-
-        case QuantifierNonGreedy:
-            backTrack->matchAmount = 0;
-            return true;
-        }
-
-        ASSERT_NOT_REACHED();
-        return false;
-    }
-
-    bool backtrackCharacterClass(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeCharacterClass);
-        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount:
-            break;
-
-        case QuantifierGreedy:
-            if (backTrack->matchAmount) {
-                --backTrack->matchAmount;
-                input.uncheckInput(1);
-                return true;
-            }
-            break;
-
-        case QuantifierNonGreedy:
-            if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
-                ++backTrack->matchAmount;
-                if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1))
-                    return true;
-            }
-            input.uncheckInput(backTrack->matchAmount);
-            break;
-        }
-
-        return false;
-    }
-
-    bool matchBackReference(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeBackReference);
-        BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
-
-        int matchBegin = output[(term.atom.subpatternId << 1)];
-        int matchEnd = output[(term.atom.subpatternId << 1) + 1];
-        ASSERT((matchBegin == -1) == (matchEnd == -1));
-        ASSERT(matchBegin <= matchEnd);
-
-        if (matchBegin == matchEnd)
-            return true;
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount: {
-            backTrack->begin = input.getPos();
-            for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
-                if (!tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {
-                    input.setPos(backTrack->begin);
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        case QuantifierGreedy: {
-            unsigned matchAmount = 0;
-            while ((matchAmount < term.atom.quantityCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition))
-                ++matchAmount;
-            backTrack->matchAmount = matchAmount;
-            return true;
-        }
-
-        case QuantifierNonGreedy:
-            backTrack->begin = input.getPos();
-            backTrack->matchAmount = 0;
-            return true;
-        }
-
-        ASSERT_NOT_REACHED();
-        return false;
-    }
-
-    bool backtrackBackReference(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeBackReference);
-        BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
-
-        int matchBegin = output[(term.atom.subpatternId << 1)];
-        int matchEnd = output[(term.atom.subpatternId << 1) + 1];
-        ASSERT((matchBegin == -1) == (matchEnd == -1));
-        ASSERT(matchBegin <= matchEnd);
-
-        if (matchBegin == matchEnd)
-            return false;
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount:
-            // for quantityCount == 1, could rewind.
-            input.setPos(backTrack->begin);
-            break;
-
-        case QuantifierGreedy:
-            if (backTrack->matchAmount) {
-                --backTrack->matchAmount;
-                input.rewind(matchEnd - matchBegin);
-                return true;
-            }
-            break;
-
-        case QuantifierNonGreedy:
-            if ((backTrack->matchAmount < term.atom.quantityCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {
-                ++backTrack->matchAmount;
-                return true;
-            } else
-                input.setPos(backTrack->begin);
-            break;
-        }
-
-        return false;
-    }
-
-    void recordParenthesesMatch(ByteTerm& term, ParenthesesDisjunctionContext* context)
-    {
-        if (term.capture()) {
-            unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1)] = context->getDisjunctionContext(term)->matchBegin + term.inputPosition;
-            output[(subpatternId << 1) + 1] = context->getDisjunctionContext(term)->matchEnd + term.inputPosition;
-        }
-    }
-    void resetMatches(ByteTerm& term, ParenthesesDisjunctionContext* context)
-    {
-        unsigned firstSubpatternId = term.atom.subpatternId;
-        unsigned count = term.atom.parenthesesDisjunction->m_numSubpatterns;
-        context->restoreOutput(output, firstSubpatternId, count);
-    }
-    void resetAssertionMatches(ByteTerm& term)
-    {
-        unsigned firstSubpatternId = term.atom.subpatternId;
-        unsigned count = term.atom.parenthesesDisjunction->m_numSubpatterns;
-        for (unsigned i = 0; i < (count << 1); ++i)
-            output[(firstSubpatternId << 1) + i] = -1;
-    }
-    bool parenthesesDoBacktrack(ByteTerm& term, BackTrackInfoParentheses* backTrack)
-    {
-        while (backTrack->matchAmount) {
-            ParenthesesDisjunctionContext* context = backTrack->lastContext;
-
-            if (matchDisjunction(term.atom.parenthesesDisjunction, context->getDisjunctionContext(term), true))
-                return true;
-
-            resetMatches(term, context);
-            popParenthesesDisjunctionContext(backTrack);
-            freeParenthesesDisjunctionContext(context);
-        }
-
-        return false;
-    }
-
-    bool matchParenthesesOnceBegin(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
-        ASSERT(term.atom.quantityCount == 1);
-
-        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
-
-        switch (term.atom.quantityType) {
-        case QuantifierGreedy: {
-            // set this speculatively; if we get to the parens end this will be true.
-            backTrack->inParentheses = 1;
-            break;
-        }
-        case QuantifierNonGreedy: {
-            backTrack->inParentheses = 0;
-            context->term += term.atom.parenthesesWidth;
-            return true;
-        }
-        case QuantifierFixedCount:
-            break;
-        }
-
-        if (term.capture()) {
-            unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1)] = input.getPos() + term.inputPosition;
-        }
-
-        return true;
-    }
-
-    bool matchParenthesesOnceEnd(ByteTerm& term, DisjunctionContext*)
-    {
-        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd);
-        ASSERT(term.atom.quantityCount == 1);
-
-        if (term.capture()) {
-            unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1) + 1] = input.getPos() + term.inputPosition;
-        }
-        return true;
-    }
-
-    bool backtrackParenthesesOnceBegin(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
-        ASSERT(term.atom.quantityCount == 1);
-
-        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
-
-        if (term.capture()) {
-            unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1)] = -1;
-            output[(subpatternId << 1) + 1] = -1;
-        }
-
-        switch (term.atom.quantityType) {
-        case QuantifierGreedy:
-            // if we backtrack to this point, there is another chance - try matching nothing.
-            ASSERT(backTrack->inParentheses);
-            backTrack->inParentheses = 0;
-            context->term += term.atom.parenthesesWidth;
-            return true;
-        case QuantifierNonGreedy:
-            ASSERT(backTrack->inParentheses);
-        case QuantifierFixedCount:
-            break;
-        }
-
-        return false;
-    }
-
-    bool backtrackParenthesesOnceEnd(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd);
-        ASSERT(term.atom.quantityCount == 1);
-
-        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
-
-        switch (term.atom.quantityType) {
-        case QuantifierGreedy:
-            if (!backTrack->inParentheses) {
-                context->term -= term.atom.parenthesesWidth;
-                return false;
-            }
-        case QuantifierNonGreedy:
-            if (!backTrack->inParentheses) {
-                // now try to match the parens; set this speculatively.
-                backTrack->inParentheses = 1;
-                if (term.capture()) {
-                    unsigned subpatternId = term.atom.subpatternId;
-                    output[(subpatternId << 1) + 1] = input.getPos() + term.inputPosition;
-                }
-                context->term -= term.atom.parenthesesWidth;
-                return true;
-            }
-        case QuantifierFixedCount:
-            break;
-        }
-
-        return false;
-    }
-
-    bool matchParentheticalAssertionBegin(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin);
-        ASSERT(term.atom.quantityCount == 1);
-
-        BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
-
-        backTrack->begin = input.getPos();
-        return true;
-    }
-
-    bool matchParentheticalAssertionEnd(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd);
-        ASSERT(term.atom.quantityCount == 1);
-
-        BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
-
-        input.setPos(backTrack->begin);
-
-        // We've reached the end of the parens; if they are inverted, this is failure.
-        if (term.invert()) {
-            context->term -= term.atom.parenthesesWidth;
-            return false;
-        }
-
-        return true;
-    }
-
-    bool backtrackParentheticalAssertionBegin(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin);
-        ASSERT(term.atom.quantityCount == 1);
-
-        // We've failed to match parens; if they are inverted, this is win!
-        if (term.invert()) {
-            context->term += term.atom.parenthesesWidth;
-            return true;
-        }
-
-        return false;
-    }
-
-    bool backtrackParentheticalAssertionEnd(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd);
-        ASSERT(term.atom.quantityCount == 1);
-
-        BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
-
-        input.setPos(backTrack->begin);
-
-        context->term -= term.atom.parenthesesWidth;
-        return false;
-    }
-
-    bool matchParentheses(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParenthesesSubpattern);
-
-        BackTrackInfoParentheses* backTrack = reinterpret_cast<BackTrackInfoParentheses*>(context->frame + term.frameLocation);
-
-        unsigned subpatternId = term.atom.subpatternId;
-        ByteDisjunction* disjunctionBody = term.atom.parenthesesDisjunction;
-
-        backTrack->prevBegin = output[(subpatternId << 1)];
-        backTrack->prevEnd = output[(subpatternId << 1) + 1];
-
-        backTrack->matchAmount = 0;
-        backTrack->lastContext = 0;
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount: {
-            // While we haven't yet reached our fixed limit,
-            while (backTrack->matchAmount < term.atom.quantityCount) {
-                // Try to do a match, and it it succeeds, add it to the list.
-                ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
-                if (matchDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
-                    appendParenthesesDisjunctionContext(backTrack, context);
-                else {
-                    // The match failed; try to find an alternate point to carry on from.
-                    resetMatches(term, context);
-                    freeParenthesesDisjunctionContext(context);
-                    if (!parenthesesDoBacktrack(term, backTrack))
-                        return false;
-                }
-            }
-
-            ASSERT(backTrack->matchAmount == term.atom.quantityCount);
-            ParenthesesDisjunctionContext* context = backTrack->lastContext;
-            recordParenthesesMatch(term, context);
-            return true;
-        }
-
-        case QuantifierGreedy: {
-            while (backTrack->matchAmount < term.atom.quantityCount) {
-                ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
-                if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
-                    appendParenthesesDisjunctionContext(backTrack, context);
-                else {
-                    resetMatches(term, context);
-                    freeParenthesesDisjunctionContext(context);
-                    break;
-                }
-            }
-
-            if (backTrack->matchAmount) {
-                ParenthesesDisjunctionContext* context = backTrack->lastContext;
-                recordParenthesesMatch(term, context);
-            }
-            return true;
-        }
-
-        case QuantifierNonGreedy:
-            return true;
-        }
-
-        ASSERT_NOT_REACHED();
-        return false;
-    }
-
-    // Rules for backtracking differ depending on whether this is greedy or non-greedy.
-    //
-    // Greedy matches never should try just adding more - you should already have done
-    // the 'more' cases.  Always backtrack, at least a leetle bit.  However cases where
-    // you backtrack an item off the list needs checking, since we'll never have matched
-    // the one less case.  Tracking forwards, still add as much as possible.
-    //
-    // Non-greedy, we've already done the one less case, so don't match on popping.
-    // We haven't done the one more case, so always try to add that.
-    //
-    bool backtrackParentheses(ByteTerm& term, DisjunctionContext* context)
-    {
-        ASSERT(term.type == ByteTerm::TypeParenthesesSubpattern);
-
-        BackTrackInfoParentheses* backTrack = reinterpret_cast<BackTrackInfoParentheses*>(context->frame + term.frameLocation);
-
-        if (term.capture()) {
-            unsigned subpatternId = term.atom.subpatternId;
-            output[(subpatternId << 1)] = backTrack->prevBegin;
-            output[(subpatternId << 1) + 1] = backTrack->prevEnd;
-        }
-
-        ByteDisjunction* disjunctionBody = term.atom.parenthesesDisjunction;
-
-        switch (term.atom.quantityType) {
-        case QuantifierFixedCount: {
-            ASSERT(backTrack->matchAmount == term.atom.quantityCount);
-
-            ParenthesesDisjunctionContext* context = 0;
-
-            if (!parenthesesDoBacktrack(term, backTrack))
-                return false;
-
-            // While we haven't yet reached our fixed limit,
-            while (backTrack->matchAmount < term.atom.quantityCount) {
-                // Try to do a match, and it it succeeds, add it to the list.
-                context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
-                if (matchDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
-                    appendParenthesesDisjunctionContext(backTrack, context);
-                else {
-                    // The match failed; try to find an alternate point to carry on from.
-                    resetMatches(term, context);
-                    freeParenthesesDisjunctionContext(context);
-                    if (!parenthesesDoBacktrack(term, backTrack))
-                        return false;
-                }
-            }
-
-            ASSERT(backTrack->matchAmount == term.atom.quantityCount);
-            context = backTrack->lastContext;
-            recordParenthesesMatch(term, context);
-            return true;
-        }
-
-        case QuantifierGreedy: {
-            if (!backTrack->matchAmount)
-                return false;
-
-            ParenthesesDisjunctionContext* context = backTrack->lastContext;
-            if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true)) {
-                while (backTrack->matchAmount < term.atom.quantityCount) {
-                    ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
-                    if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term)))
-                        appendParenthesesDisjunctionContext(backTrack, context);
-                    else {
-                        resetMatches(term, context);
-                        freeParenthesesDisjunctionContext(context);
-                        break;
-                    }
-                }
-            } else {
-                resetMatches(term, context);
-                popParenthesesDisjunctionContext(backTrack);
-                freeParenthesesDisjunctionContext(context);
-            }
-
-            if (backTrack->matchAmount) {
-                ParenthesesDisjunctionContext* context = backTrack->lastContext;
-                recordParenthesesMatch(term, context);
-            }
-            return true;
-        }
-
-        case QuantifierNonGreedy: {
-            // If we've not reached the limit, try to add one more match.
-            if (backTrack->matchAmount < term.atom.quantityCount) {
-                ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
-                if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term))) {
-                    appendParenthesesDisjunctionContext(backTrack, context);
-                    recordParenthesesMatch(term, context);
-                    return true;
-                } else {
-                    resetMatches(term, context);
-                    freeParenthesesDisjunctionContext(context);
-                }
-            }
-
-            // Nope - okay backtrack looking for an alternative.
-            while (backTrack->matchAmount) {
-                ParenthesesDisjunctionContext* context = backTrack->lastContext;
-                if (matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true)) {
-                    // successful backtrack! we're back in the game!
-                    if (backTrack->matchAmount) {
-                        context = backTrack->lastContext;
-                        recordParenthesesMatch(term, context);
-                    }
-                    return true;
-                }
-
-                // pop a match off the stack
-                resetMatches(term, context);
-                popParenthesesDisjunctionContext(backTrack);
-                freeParenthesesDisjunctionContext(context);
-            }
-
-            return false;
-        }
-        }
-
-        ASSERT_NOT_REACHED();
-        return false;
-    }
-
-#define MATCH_NEXT() { ++context->term; goto matchAgain; }
-#define BACKTRACK() { --context->term; goto backtrack; }
-#define currentTerm() (disjunction->terms[context->term])
-    bool matchDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
-    {
-        if (btrack)
-            BACKTRACK();
-
-        context->matchBegin = input.getPos();
-        context->term = 0;
-
-    matchAgain:
-        ASSERT(context->term < static_cast<int>(disjunction->terms.size()));
-
-        switch (currentTerm().type) {
-        case ByteTerm::TypeSubpatternBegin:
-            MATCH_NEXT();
-        case ByteTerm::TypeSubpatternEnd:
-            context->matchEnd = input.getPos();
-            return true;
-
-        case ByteTerm::TypeBodyAlternativeBegin:
-            MATCH_NEXT();
-        case ByteTerm::TypeBodyAlternativeDisjunction:
-        case ByteTerm::TypeBodyAlternativeEnd:
-            context->matchEnd = input.getPos();
-            return true;
-
-        case ByteTerm::TypeAlternativeBegin:
-            MATCH_NEXT();
-        case ByteTerm::TypeAlternativeDisjunction:
-        case ByteTerm::TypeAlternativeEnd: {
-            int offset = currentTerm().alternative.end;
-            BackTrackInfoAlternative* backTrack = reinterpret_cast<BackTrackInfoAlternative*>(context->frame + currentTerm().frameLocation);
-            backTrack->offset = offset;
-            context->term += offset;
-            MATCH_NEXT();
-        }
-
-        case ByteTerm::TypeAssertionBOL:
-            if (matchAssertionBOL(currentTerm()))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeAssertionEOL:
-            if (matchAssertionEOL(currentTerm()))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeAssertionWordBoundary:
-            if (matchAssertionWordBoundary(currentTerm()))
-                MATCH_NEXT();
-            BACKTRACK();
-
-        case ByteTerm::TypePatternCharacterOnce:
-        case ByteTerm::TypePatternCharacterFixed: {
-            for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
-                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + matchAmount))
-                    BACKTRACK();
-            }
-            MATCH_NEXT();
-        }
-        case ByteTerm::TypePatternCharacterGreedy: {
-            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
-            unsigned matchAmount = 0;
-            while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
-                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - 1)) {
-                    input.uncheckInput(1);
-                    break;
-                }
-                ++matchAmount;
-            }
-            backTrack->matchAmount = matchAmount;
-
-            MATCH_NEXT();
-        }
-        case ByteTerm::TypePatternCharacterNonGreedy: {
-            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
-            backTrack->matchAmount = 0;
-            MATCH_NEXT();
-        }
-
-        case ByteTerm::TypePatternCasedCharacterOnce:
-        case ByteTerm::TypePatternCasedCharacterFixed: {
-            for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
-                if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + matchAmount))
-                    BACKTRACK();
-            }
-            MATCH_NEXT();
-        }
-        case ByteTerm::TypePatternCasedCharacterGreedy: {
-            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
-            unsigned matchAmount = 0;
-            while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
-                if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - 1)) {
-                    input.uncheckInput(1);
-                    break;
-                }
-                ++matchAmount;
-            }
-            backTrack->matchAmount = matchAmount;
-
-            MATCH_NEXT();
-        }
-        case ByteTerm::TypePatternCasedCharacterNonGreedy: {
-            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
-            backTrack->matchAmount = 0;
-            MATCH_NEXT();
-        }
-
-        case ByteTerm::TypeCharacterClass:
-            if (matchCharacterClass(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeBackReference:
-            if (matchBackReference(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeParenthesesSubpattern:
-            if (matchParentheses(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeParenthesesSubpatternOnceBegin:
-            if (matchParenthesesOnceBegin(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeParenthesesSubpatternOnceEnd:
-            if (matchParenthesesOnceEnd(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeParentheticalAssertionBegin:
-            if (matchParentheticalAssertionBegin(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-        case ByteTerm::TypeParentheticalAssertionEnd:
-            if (matchParentheticalAssertionEnd(currentTerm(), context))
-                MATCH_NEXT();
-            BACKTRACK();
-
-        case ByteTerm::TypeCheckInput:
-            if (input.checkInput(currentTerm().checkInputCount))
-                MATCH_NEXT();
-            BACKTRACK();
-        }
-
-        // We should never fall-through to here.
-        ASSERT_NOT_REACHED();
-
-    backtrack:
-        ASSERT(context->term < static_cast<int>(disjunction->terms.size()));
-
-        switch (currentTerm().type) {
-        case ByteTerm::TypeSubpatternBegin:
-            return false;
-        case ByteTerm::TypeSubpatternEnd:
-            ASSERT_NOT_REACHED();
-
-        case ByteTerm::TypeBodyAlternativeBegin:
-        case ByteTerm::TypeBodyAlternativeDisjunction: {
-            int offset = currentTerm().alternative.next;
-            context->term += offset;
-            if (offset > 0)
-                MATCH_NEXT();
-
-            if (input.atEnd())
-                return false;
-
-            input.next();
-            context->matchBegin = input.getPos();
-            MATCH_NEXT();
-        }
-        case ByteTerm::TypeBodyAlternativeEnd:
-            ASSERT_NOT_REACHED();
-
-            case ByteTerm::TypeAlternativeBegin:
-            case ByteTerm::TypeAlternativeDisjunction: {
-                int offset = currentTerm().alternative.next;
-                context->term += offset;
-                if (offset > 0)
-                    MATCH_NEXT();
-                BACKTRACK();
-            }
-            case ByteTerm::TypeAlternativeEnd: {
-                // We should never backtrack back into an alternative of the main body of the regex.
-                BackTrackInfoAlternative* backTrack = reinterpret_cast<BackTrackInfoAlternative*>(context->frame + currentTerm().frameLocation);
-                unsigned offset = backTrack->offset;
-                context->term -= offset;
-                BACKTRACK();
-            }
-
-            case ByteTerm::TypeAssertionBOL:
-            case ByteTerm::TypeAssertionEOL:
-            case ByteTerm::TypeAssertionWordBoundary:
-                BACKTRACK();
-
-            case ByteTerm::TypePatternCharacterOnce:
-            case ByteTerm::TypePatternCharacterFixed:
-            case ByteTerm::TypePatternCharacterGreedy:
-            case ByteTerm::TypePatternCharacterNonGreedy:
-                if (backtrackPatternCharacter(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypePatternCasedCharacterOnce:
-            case ByteTerm::TypePatternCasedCharacterFixed:
-            case ByteTerm::TypePatternCasedCharacterGreedy:
-            case ByteTerm::TypePatternCasedCharacterNonGreedy:
-                if (backtrackPatternCasedCharacter(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeCharacterClass:
-                if (backtrackCharacterClass(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeBackReference:
-                if (backtrackBackReference(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeParenthesesSubpattern:
-                if (backtrackParentheses(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeParenthesesSubpatternOnceBegin:
-                if (backtrackParenthesesOnceBegin(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeParenthesesSubpatternOnceEnd:
-                if (backtrackParenthesesOnceEnd(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeParentheticalAssertionBegin:
-                if (backtrackParentheticalAssertionBegin(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-            case ByteTerm::TypeParentheticalAssertionEnd:
-                if (backtrackParentheticalAssertionEnd(currentTerm(), context))
-                    MATCH_NEXT();
-                BACKTRACK();
-
-            case ByteTerm::TypeCheckInput:
-                input.uncheckInput(currentTerm().checkInputCount);
-                BACKTRACK();
-        }
-
-        ASSERT_NOT_REACHED();
-        return false;
-    }
-
-    bool matchNonZeroDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
-    {
-        if (matchDisjunction(disjunction, context, btrack)) {
-            while (context->matchBegin == context->matchEnd) {
-                if (!matchDisjunction(disjunction, context, true))
-                    return false;
-            }
-            return true;
-        }
-
-        return false;
-    }
-
-    int interpret()
-    {
-        for (unsigned i = 0; i < ((pattern->m_body->m_numSubpatterns + 1) << 1); ++i)
-            output[i] = -1;
-
-        DisjunctionContext* context = allocDisjunctionContext(pattern->m_body.get());
-
-        if (matchDisjunction(pattern->m_body.get(), context)) {
-            output[0] = context->matchBegin;
-            output[1] = context->matchEnd;
-        }
-
-        freeDisjunctionContext(context);
-
-        return output[0];
-    }
-
-    Interpreter(BytecodePattern* pattern, int* output, const UChar* inputChar, unsigned start, unsigned length)
-        : pattern(pattern)
-        , output(output)
-        , input(inputChar, start, length)
-    {
-    }
-
-private:
-    BytecodePattern *pattern;
-    int* output;
-    InputStream input;
-};
-
-
-
-class ByteCompiler {
-    struct ParenthesesStackEntry {
-        unsigned beginTerm;
-        unsigned savedAlternativeIndex;
-        ParenthesesStackEntry(unsigned beginTerm, unsigned savedAlternativeIndex/*, unsigned subpatternId, bool capture = false*/)
-            : beginTerm(beginTerm)
-            , savedAlternativeIndex(savedAlternativeIndex)
-        {
-        }
-    };
-
-public:
-    ByteCompiler(RegexPattern& pattern)
-        : m_pattern(pattern)
-    {
-        m_bodyDisjunction = 0;
-        m_currentAlternativeIndex = 0;
-    }
-
-    BytecodePattern* compile()
-    {
-        regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize);
-        emitDisjunction(m_pattern.m_body);
-        regexEnd();
-
-        return new BytecodePattern(m_bodyDisjunction, m_allParenthesesInfo, m_pattern);
-    }
-
-    void checkInput(unsigned count)
-    {
-        m_bodyDisjunction->terms.append(ByteTerm::CheckInput(count));
-    }
-
-    void assertionBOL(int inputPosition)
-    {
-        m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
-    }
-
-    void assertionEOL(int inputPosition)
-    {
-        m_bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
-    }
-
-    void assertionWordBoundary(bool invert, int inputPosition)
-    {
-        m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
-    }
-
-    void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
-    {
-        if (m_pattern.m_ignoreCase) {
-            UChar lo = Unicode::toLower(ch);
-            UChar hi = Unicode::toUpper(ch);
-
-            if (lo != hi) {
-                m_bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantityCount, quantityType));
-                return;
-            }
-        }
-
-        m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
-    }
-
-    void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
-    {
-        m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
-
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
-    }
-
-    void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
-    {
-        ASSERT(subpatternId);
-
-        m_bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition));
-
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
-    }
-
-    void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
-    {
-        int beginTerm = m_bodyDisjunction->terms.size();
-
-        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, inputPosition));
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
-        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
-
-        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
-        m_currentAlternativeIndex = beginTerm + 1;
-    }
-
-    void atomParentheticalAssertionBegin(unsigned subpatternId, bool invert, unsigned frameLocation, unsigned alternativeFrameLocation)
-    {
-        int beginTerm = m_bodyDisjunction->terms.size();
-
-        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, invert, 0));
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
-        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
-        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
-
-        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
-        m_currentAlternativeIndex = beginTerm + 1;
-    }
-
-    unsigned popParenthesesStack()
-    {
-        ASSERT(m_parenthesesStack.size());
-        int stackEnd = m_parenthesesStack.size() - 1;
-        unsigned beginTerm = m_parenthesesStack[stackEnd].beginTerm;
-        m_currentAlternativeIndex = m_parenthesesStack[stackEnd].savedAlternativeIndex;
-        m_parenthesesStack.shrink(stackEnd);
-
-        ASSERT(beginTerm < m_bodyDisjunction->terms.size());
-        ASSERT(m_currentAlternativeIndex < m_bodyDisjunction->terms.size());
-
-        return beginTerm;
-    }
-
-#ifndef NDEBUG
-    void dumpDisjunction(ByteDisjunction* disjunction)
-    {
-        printf("ByteDisjunction(%p):\n\t", disjunction);
-        for (unsigned i = 0; i < disjunction->terms.size(); ++i)
-            printf("{ %d } ", disjunction->terms[i].type);
-        printf("\n");
-    }
-#endif
-
-    void closeAlternative(int beginTerm)
-    {
-        int origBeginTerm = beginTerm;
-        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeBegin);
-        int endIndex = m_bodyDisjunction->terms.size();
-
-        unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
-
-        if (!m_bodyDisjunction->terms[beginTerm].alternative.next)
-            m_bodyDisjunction->terms.remove(beginTerm);
-        else {
-            while (m_bodyDisjunction->terms[beginTerm].alternative.next) {
-                beginTerm += m_bodyDisjunction->terms[beginTerm].alternative.next;
-                ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeDisjunction);
-                m_bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
-                m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
-            }
-
-            m_bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
-
-            m_bodyDisjunction->terms.append(ByteTerm::AlternativeEnd());
-            m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
-        }
-    }
-
-    void closeBodyAlternative()
-    {
-        int beginTerm = 0;
-        int origBeginTerm = 0;
-        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeBegin);
-        int endIndex = m_bodyDisjunction->terms.size();
-
-        unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
-
-        while (m_bodyDisjunction->terms[beginTerm].alternative.next) {
-            beginTerm += m_bodyDisjunction->terms[beginTerm].alternative.next;
-            ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeDisjunction);
-            m_bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
-            m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
-        }
-
-        m_bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
-
-        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeEnd());
-        m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
-    }
-
-    void atomParenthesesEnd(bool doInline, unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
-    {
-        unsigned beginTerm = popParenthesesStack();
-        closeAlternative(beginTerm + 1);
-        unsigned endTerm = m_bodyDisjunction->terms.size();
-
-        bool isAssertion = m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParentheticalAssertionBegin;
-        bool invertOrCapture = m_bodyDisjunction->terms[beginTerm].invertOrCapture;
-        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
-
-        m_bodyDisjunction->terms.append(ByteTerm(isAssertion ? ByteTerm::TypeParentheticalAssertionEnd : ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, invertOrCapture, inputPosition));
-        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
-        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
-        m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
-
-        if (doInline) {
-            m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
-            m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
-            m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
-            m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
-        } else {
-            ByteTerm& parenthesesBegin = m_bodyDisjunction->terms[beginTerm];
-            ASSERT(parenthesesBegin.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
-
-            bool invertOrCapture = parenthesesBegin.invertOrCapture;
-            unsigned subpatternId = parenthesesBegin.atom.subpatternId;
-
-            unsigned numSubpatterns = lastSubpatternId - subpatternId + 1;
-            ByteDisjunction* parenthesesDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
-
-            parenthesesDisjunction->terms.append(ByteTerm::SubpatternBegin());
-            for (unsigned termInParentheses = beginTerm + 1; termInParentheses < endTerm; ++termInParentheses)
-                parenthesesDisjunction->terms.append(m_bodyDisjunction->terms[termInParentheses]);
-            parenthesesDisjunction->terms.append(ByteTerm::SubpatternEnd());
-
-            m_bodyDisjunction->terms.shrink(beginTerm);
-
-            m_allParenthesesInfo.append(parenthesesDisjunction);
-            m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, invertOrCapture, inputPosition));
-
-            m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
-            m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
-            m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
-        }
-    }
-
-    void regexBegin(unsigned numSubpatterns, unsigned callFrameSize)
-    {
-        m_bodyDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
-        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin());
-        m_bodyDisjunction->terms[0].frameLocation = 0;
-        m_currentAlternativeIndex = 0;
-    }
-
-    void regexEnd()
-    {
-        closeBodyAlternative();
-    }
-
-    void alternativeBodyDisjunction()
-    {
-        int newAlternativeIndex = m_bodyDisjunction->terms.size();
-        m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
-        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeDisjunction());
-
-        m_currentAlternativeIndex = newAlternativeIndex;
-    }
-
-    void alternativeDisjunction()
-    {
-        int newAlternativeIndex = m_bodyDisjunction->terms.size();
-        m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
-        m_bodyDisjunction->terms.append(ByteTerm::AlternativeDisjunction());
-
-        m_currentAlternativeIndex = newAlternativeIndex;
-    }
-
-    void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0)
-    {
-        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
-            unsigned currentCountAlreadyChecked = inputCountAlreadyChecked;
-
-            if (alt) {
-                if (disjunction == m_pattern.m_body)
-                    alternativeBodyDisjunction();
-                else
-                    alternativeDisjunction();
-            }
-
-            PatternAlternative* alternative = disjunction->m_alternatives[alt];
-            unsigned minimumSize = alternative->m_minimumSize;
-
-            ASSERT(minimumSize >= parenthesesInputCountAlreadyChecked);
-            unsigned countToCheck = minimumSize - parenthesesInputCountAlreadyChecked;
-            if (countToCheck)
-                checkInput(countToCheck);
-            currentCountAlreadyChecked += countToCheck;
-
-            for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
-                PatternTerm& term = alternative->m_terms[i];
-
-                switch (term.type) {
-                case PatternTerm::TypeAssertionBOL:
-                    assertionBOL(term.inputPosition - currentCountAlreadyChecked);
-                    break;
-
-                case PatternTerm::TypeAssertionEOL:
-                    assertionEOL(term.inputPosition - currentCountAlreadyChecked);
-                    break;
-
-                case PatternTerm::TypeAssertionWordBoundary:
-                    assertionWordBoundary(term.invertOrCapture, term.inputPosition - currentCountAlreadyChecked);
-                    break;
-
-                case PatternTerm::TypePatternCharacter:
-                    atomPatternCharacter(term.patternCharacter, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
-                    break;
-
-                case PatternTerm::TypeCharacterClass:
-                    atomCharacterClass(term.characterClass, term.invertOrCapture, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
-                    break;
-
-                case PatternTerm::TypeBackReference:
-                    atomBackReference(term.subpatternId, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
-                        break;
-
-                case PatternTerm::TypeForwardReference:
-                    break;
-
-                case PatternTerm::TypeParenthesesSubpattern: {
-                    unsigned disjunctionAlreadyCheckedCount = 0;
-                    if ((term.quantityCount == 1) && !term.parentheses.isCopy) {
-                        if (term.quantityType == QuantifierFixedCount) {
-                            disjunctionAlreadyCheckedCount = term.parentheses.disjunction->m_minimumSize;
-                            unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                            atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation);
-                            emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, term.parentheses.disjunction->m_minimumSize);
-                            atomParenthesesEnd(true, term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
-                        } else {
-                            unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                            atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + RegexStackSpaceForBackTrackInfoParenthesesOnce);
-                            emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
-                            atomParenthesesEnd(true, term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
-                        }
-                    } else {
-                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
-                        atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.invertOrCapture, delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, 0);
-                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
-                        atomParenthesesEnd(false, term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
-                    }
-                    break;
-                }
-
-                case PatternTerm::TypeParentheticalAssertion: {
-                    unsigned alternativeFrameLocation = term.frameLocation + RegexStackSpaceForBackTrackInfoParentheticalAssertion;
-
-                    atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invertOrCapture, term.frameLocation, alternativeFrameLocation);
-                    emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
-                    atomParenthesesEnd(true, term.parentheses.lastSubpatternId, 0, term.frameLocation, term.quantityCount, term.quantityType);
-                    break;
-                }
-                }
-            }
-        }
-    }
-
-private:
-    RegexPattern& m_pattern;
-    ByteDisjunction* m_bodyDisjunction;
-    unsigned m_currentAlternativeIndex;
-    Vector<ParenthesesStackEntry> m_parenthesesStack;
-    Vector<ByteDisjunction*> m_allParenthesesInfo;
-};
-
-
-BytecodePattern* byteCompileRegex(const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline)
-{
-    RegexPattern pattern(ignoreCase, multiline);
-
-    if ((error = compileRegex(patternString, pattern)))
-        return 0;
-
-    numSubpatterns = pattern.m_numSubpatterns;
-
-    return ByteCompiler(pattern).compile();
-}
-
-int interpretRegex(BytecodePattern* regex, const UChar* input, unsigned start, unsigned length, int* output)
-{
-    return Interpreter(regex, output, input, start, length).interpret();
-}
-
-
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoPatternCharacter) == (RegexStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoPatternCharacter);
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoCharacterClass) == (RegexStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoCharacterClass);
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoBackReference) == (RegexStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoBackReference);
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoAlternative) == (RegexStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoAlternative);
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheticalAssertion) == (RegexStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParentheticalAssertion);
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParenthesesOnce) == (RegexStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParenthesesOnce);
-COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheses) == (RegexStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckRegexStackSpaceForBackTrackInfoParentheses);
-
-
-} }
-
-#endif
diff --git a/yarr/RegexInterpreter.h b/yarr/RegexInterpreter.h
deleted file mode 100644 (file)
index e3c3122..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2009 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 RegexInterpreter_h
-#define RegexInterpreter_h
-
-#if ENABLE(YARR)
-
-#include "RegexParser.h"
-#include "RegexPattern.h"
-#include <wtf/unicode/Unicode.h>
-
-namespace JSC { namespace Yarr {
-
-class ByteDisjunction;
-
-struct ByteTerm {
-    enum Type {
-        TypeBodyAlternativeBegin,
-        TypeBodyAlternativeDisjunction,
-        TypeBodyAlternativeEnd,
-        TypeAlternativeBegin,
-        TypeAlternativeDisjunction,
-        TypeAlternativeEnd,
-        TypeSubpatternBegin,
-        TypeSubpatternEnd,
-        TypeAssertionBOL,
-        TypeAssertionEOL,
-        TypeAssertionWordBoundary,
-        TypePatternCharacterOnce,
-        TypePatternCharacterFixed,
-        TypePatternCharacterGreedy,
-        TypePatternCharacterNonGreedy,
-        TypePatternCasedCharacterOnce,
-        TypePatternCasedCharacterFixed,
-        TypePatternCasedCharacterGreedy,
-        TypePatternCasedCharacterNonGreedy,
-        TypeCharacterClass,
-        TypeBackReference,
-        TypeParenthesesSubpattern,
-        TypeParenthesesSubpatternOnceBegin,
-        TypeParenthesesSubpatternOnceEnd,
-        TypeParentheticalAssertionBegin,
-        TypeParentheticalAssertionEnd,
-        TypeCheckInput,
-    } type;
-    bool invertOrCapture;
-    union {
-        struct {
-            union {
-                UChar patternCharacter;
-                struct {
-                    UChar lo;
-                    UChar hi;
-                } casedCharacter;
-                CharacterClass* characterClass;
-                unsigned subpatternId;
-            };
-            union {
-                ByteDisjunction* parenthesesDisjunction;
-                unsigned parenthesesWidth;
-            };
-            QuantifierType quantityType;
-            unsigned quantityCount;
-        } atom;
-        struct {
-            int next;
-            int end;
-        } alternative;
-        unsigned checkInputCount;
-    };
-    unsigned frameLocation;
-    int inputPosition;
-
-    ByteTerm(UChar ch, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
-        : frameLocation(frameLocation)
-    {
-        switch (quantityType) {
-        case QuantifierFixedCount:
-            type = (quantityCount == 1) ? ByteTerm::TypePatternCharacterOnce : ByteTerm::TypePatternCharacterFixed;
-            break;
-        case QuantifierGreedy:
-            type = ByteTerm::TypePatternCharacterGreedy;
-            break;
-        case QuantifierNonGreedy:
-            type = ByteTerm::TypePatternCharacterNonGreedy;
-            break;
-        }
-
-        atom.patternCharacter = ch;
-        atom.quantityType = quantityType;
-        atom.quantityCount = quantityCount;
-        inputPosition = inputPos;
-    }
-
-    ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
-        : frameLocation(frameLocation)
-    {
-        switch (quantityType) {
-        case QuantifierFixedCount:
-            type = (quantityCount == 1) ? ByteTerm::TypePatternCasedCharacterOnce : ByteTerm::TypePatternCasedCharacterFixed;
-            break;
-        case QuantifierGreedy:
-            type = ByteTerm::TypePatternCasedCharacterGreedy;
-            break;
-        case QuantifierNonGreedy:
-            type = ByteTerm::TypePatternCasedCharacterNonGreedy;
-            break;
-        }
-
-        atom.casedCharacter.lo = lo;
-        atom.casedCharacter.hi = hi;
-        atom.quantityType = quantityType;
-        atom.quantityCount = quantityCount;
-        inputPosition = inputPos;
-    }
-
-    ByteTerm(CharacterClass* characterClass, bool invert, int inputPos)
-        : type(ByteTerm::TypeCharacterClass)
-        , invertOrCapture(invert)
-    {
-        atom.characterClass = characterClass;
-        atom.quantityType = QuantifierFixedCount;
-        atom.quantityCount = 1;
-        inputPosition = inputPos;
-    }
-
-    ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool invertOrCapture, int inputPos)
-        : type(type)
-        , invertOrCapture(invertOrCapture)
-    {
-        atom.subpatternId = subpatternId;
-        atom.parenthesesDisjunction = parenthesesInfo;
-        atom.quantityType = QuantifierFixedCount;
-        atom.quantityCount = 1;
-        inputPosition = inputPos;
-    }
-    
-    ByteTerm(Type type, bool invert = false)
-        : type(type)
-        , invertOrCapture(invert)
-    {
-        atom.quantityType = QuantifierFixedCount;
-        atom.quantityCount = 1;
-    }
-
-    ByteTerm(Type type, unsigned subpatternId, bool invertOrCapture, int inputPos)
-        : type(type)
-        , invertOrCapture(invertOrCapture)
-    {
-        atom.subpatternId = subpatternId;
-        atom.quantityType = QuantifierFixedCount;
-        atom.quantityCount = 1;
-        inputPosition = inputPos;
-    }
-
-    static ByteTerm BOL(int inputPos)
-    {
-        ByteTerm term(TypeAssertionBOL);
-        term.inputPosition = inputPos;
-        return term;
-    }
-
-    static ByteTerm CheckInput(unsigned count)
-    {
-        ByteTerm term(TypeCheckInput);
-        term.checkInputCount = count;
-        return term;
-    }
-
-    static ByteTerm EOL(int inputPos)
-    {
-        ByteTerm term(TypeAssertionEOL);
-        term.inputPosition = inputPos;
-        return term;
-    }
-
-    static ByteTerm WordBoundary(bool invert, int inputPos)
-    {
-        ByteTerm term(TypeAssertionWordBoundary, invert);
-        term.inputPosition = inputPos;
-        return term;
-    }
-    
-    static ByteTerm BackReference(unsigned subpatternId, int inputPos)
-    {
-        return ByteTerm(TypeBackReference, subpatternId, false, inputPos);
-    }
-
-    static ByteTerm BodyAlternativeBegin()
-    {
-        ByteTerm term(TypeBodyAlternativeBegin);
-        term.alternative.next = 0;
-        term.alternative.end = 0;
-        return term;
-    }
-
-    static ByteTerm BodyAlternativeDisjunction()
-    {
-        ByteTerm term(TypeBodyAlternativeDisjunction);
-        term.alternative.next = 0;
-        term.alternative.end = 0;
-        return term;
-    }
-
-    static ByteTerm BodyAlternativeEnd()
-    {
-        ByteTerm term(TypeBodyAlternativeEnd);
-        term.alternative.next = 0;
-        term.alternative.end = 0;
-        return term;
-    }
-
-    static ByteTerm AlternativeBegin()
-    {
-        ByteTerm term(TypeAlternativeBegin);
-        term.alternative.next = 0;
-        term.alternative.end = 0;
-        return term;
-    }
-
-    static ByteTerm AlternativeDisjunction()
-    {
-        ByteTerm term(TypeAlternativeDisjunction);
-        term.alternative.next = 0;
-        term.alternative.end = 0;
-        return term;
-    }
-
-    static ByteTerm AlternativeEnd()
-    {
-        ByteTerm term(TypeAlternativeEnd);
-        term.alternative.next = 0;
-        term.alternative.end = 0;
-        return term;
-    }
-
-    static ByteTerm SubpatternBegin()
-    {
-        return ByteTerm(TypeSubpatternBegin);
-    }
-
-    static ByteTerm SubpatternEnd()
-    {
-        return ByteTerm(TypeSubpatternEnd);
-    }
-
-    bool invert()
-    {
-        return invertOrCapture;
-    }
-
-    bool capture()
-    {
-        return invertOrCapture;
-    }
-};
-
-class ByteDisjunction : public FastAllocBase {
-public:
-    ByteDisjunction(unsigned numSubpatterns, unsigned frameSize)
-        : m_numSubpatterns(numSubpatterns)
-        , m_frameSize(frameSize)
-    {
-    }
-
-    Vector<ByteTerm> terms;
-    unsigned m_numSubpatterns;
-    unsigned m_frameSize;
-};
-
-struct BytecodePattern : FastAllocBase {
-    BytecodePattern(ByteDisjunction* body, Vector<ByteDisjunction*> allParenthesesInfo, RegexPattern& pattern)
-        : m_body(body)
-        , m_ignoreCase(pattern.m_ignoreCase)
-        , m_multiline(pattern.m_multiline)
-    {
-        newlineCharacterClass = pattern.newlineCharacterClass();
-        wordcharCharacterClass = pattern.wordcharCharacterClass();
-
-        m_allParenthesesInfo.append(allParenthesesInfo);
-        m_userCharacterClasses.append(pattern.m_userCharacterClasses);
-        // 'Steal' the RegexPattern's CharacterClasses!  We clear its
-        // array, so that it won't delete them on destruction.  We'll
-        // take responsibility for that.
-        pattern.m_userCharacterClasses.clear();
-    }
-
-    ~BytecodePattern()
-    {
-        deleteAllValues(m_allParenthesesInfo);
-        deleteAllValues(m_userCharacterClasses);
-    }
-
-    OwnPtr<ByteDisjunction> m_body;
-    bool m_ignoreCase;
-    bool m_multiline;
-    
-    CharacterClass* newlineCharacterClass;
-    CharacterClass* wordcharCharacterClass;
-private:
-    Vector<ByteDisjunction*> m_allParenthesesInfo;
-    Vector<CharacterClass*> m_userCharacterClasses;
-};
-
-BytecodePattern* byteCompileRegex(const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
-int interpretRegex(BytecodePattern* v_regex, const UChar* input, unsigned start, unsigned length, int* output);
-
-} } // namespace JSC::Yarr
-
-#endif
-
-#endif // RegexInterpreter_h
diff --git a/yarr/RegexJIT.cpp b/yarr/RegexJIT.cpp
deleted file mode 100644 (file)
index b954b1c..0000000
+++ /dev/null
@@ -1,1426 +0,0 @@
-/*
- * Copyright (C) 2009 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. 
- */
-
-#include "config.h"
-#include "RegexJIT.h"
-
-#include "ASCIICType.h"
-#include "JSGlobalData.h"
-#include "LinkBuffer.h"
-#include "MacroAssembler.h"
-#include "RegExpCache.h"
-#include "RegexCompiler.h"
-
-#include "pcre.h" // temporary, remove when fallback is removed.
-
-#if ENABLE(YARR_JIT)
-
-using namespace WTF;
-
-namespace JSC { namespace Yarr {
-
-class RegexGenerator : private MacroAssembler {
-    friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
-
-#if CPU(ARM)
-    static const RegisterID input = ARMRegisters::r0;
-    static const RegisterID index = ARMRegisters::r1;
-    static const RegisterID length = ARMRegisters::r2;
-    static const RegisterID output = ARMRegisters::r4;
-
-    static const RegisterID regT0 = ARMRegisters::r5;
-    static const RegisterID regT1 = ARMRegisters::r6;
-
-    static const RegisterID returnRegister = ARMRegisters::r0;
-#elif CPU(MIPS)
-    static const RegisterID input = MIPSRegisters::a0;
-    static const RegisterID index = MIPSRegisters::a1;
-    static const RegisterID length = MIPSRegisters::a2;
-    static const RegisterID output = MIPSRegisters::a3;
-
-    static const RegisterID regT0 = MIPSRegisters::t4;
-    static const RegisterID regT1 = MIPSRegisters::t5;
-
-    static const RegisterID returnRegister = MIPSRegisters::v0;
-#elif CPU(X86)
-    static const RegisterID input = X86Registers::eax;
-    static const RegisterID index = X86Registers::edx;
-    static const RegisterID length = X86Registers::ecx;
-    static const RegisterID output = X86Registers::edi;
-
-    static const RegisterID regT0 = X86Registers::ebx;
-    static const RegisterID regT1 = X86Registers::esi;
-
-    static const RegisterID returnRegister = X86Registers::eax;
-#elif CPU(X86_64)
-    static const RegisterID input = X86Registers::edi;
-    static const RegisterID index = X86Registers::esi;
-    static const RegisterID length = X86Registers::edx;
-    static const RegisterID output = X86Registers::ecx;
-
-    static const RegisterID regT0 = X86Registers::eax;
-    static const RegisterID regT1 = X86Registers::ebx;
-
-    static const RegisterID returnRegister = X86Registers::eax;
-#endif
-
-    void optimizeAlternative(PatternAlternative* alternative)
-    {
-        if (!alternative->m_terms.size())
-            return;
-
-        for (unsigned i = 0; i < alternative->m_terms.size() - 1; ++i) {
-            PatternTerm& term = alternative->m_terms[i];
-            PatternTerm& nextTerm = alternative->m_terms[i + 1];
-
-            if ((term.type == PatternTerm::TypeCharacterClass)
-                && (term.quantityType == QuantifierFixedCount)
-                && (nextTerm.type == PatternTerm::TypePatternCharacter)
-                && (nextTerm.quantityType == QuantifierFixedCount)) {
-                PatternTerm termCopy = term;
-                alternative->m_terms[i] = nextTerm;
-                alternative->m_terms[i + 1] = termCopy;
-            }
-        }
-    }
-
-    void matchCharacterClassRange(RegisterID character, JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount)
-    {
-        do {
-            // pick which range we're going to generate
-            int which = count >> 1;
-            char lo = ranges[which].begin;
-            char hi = ranges[which].end;
-            
-            // check if there are any ranges or matches below lo.  If not, just jl to failure -
-            // if there is anything else to check, check that first, if it falls through jmp to failure.
-            if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
-                Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
-                
-                // generate code for all ranges before this one
-                if (which)
-                    matchCharacterClassRange(character, failures, matchDest, ranges, which, matchIndex, matches, matchCount);
-                
-                while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
-                    matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex])));
-                    ++*matchIndex;
-                }
-                failures.append(jump());
-
-                loOrAbove.link(this);
-            } else if (which) {
-                Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
-
-                matchCharacterClassRange(character, failures, matchDest, ranges, which, matchIndex, matches, matchCount);
-                failures.append(jump());
-
-                loOrAbove.link(this);
-            } else
-                failures.append(branch32(LessThan, character, Imm32((unsigned short)lo)));
-
-            while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi))
-                ++*matchIndex;
-
-            matchDest.append(branch32(LessThanOrEqual, character, Imm32((unsigned short)hi)));
-            // fall through to here, the value is above hi.
-
-            // shuffle along & loop around if there are any more matches to handle.
-            unsigned next = which + 1;
-            ranges += next;
-            count -= next;
-        } while (count);
-    }
-
-    void matchCharacterClass(RegisterID character, JumpList& matchDest, const CharacterClass* charClass)
-    {
-        if (charClass->m_table) {
-            ExtendedAddress tableEntry(character, reinterpret_cast<intptr_t>(charClass->m_table->m_table));
-            matchDest.append(branchTest8(charClass->m_table->m_inverted ? Zero : NonZero, tableEntry));   
-            return;
-        }
-        Jump unicodeFail;
-        if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size()) {
-            Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f));
-        
-            if (charClass->m_matchesUnicode.size()) {
-                for (unsigned i = 0; i < charClass->m_matchesUnicode.size(); ++i) {
-                    UChar ch = charClass->m_matchesUnicode[i];
-                    matchDest.append(branch32(Equal, character, Imm32(ch)));
-                }
-            }
-            
-            if (charClass->m_rangesUnicode.size()) {
-                for (unsigned i = 0; i < charClass->m_rangesUnicode.size(); ++i) {
-                    UChar lo = charClass->m_rangesUnicode[i].begin;
-                    UChar hi = charClass->m_rangesUnicode[i].end;
-                    
-                    Jump below = branch32(LessThan, character, Imm32(lo));
-                    matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi)));
-                    below.link(this);
-                }
-            }
-
-            unicodeFail = jump();
-            isAscii.link(this);
-        }
-
-        if (charClass->m_ranges.size()) {
-            unsigned matchIndex = 0;
-            JumpList failures; 
-            matchCharacterClassRange(character, failures, matchDest, charClass->m_ranges.begin(), charClass->m_ranges.size(), &matchIndex, charClass->m_matches.begin(), charClass->m_matches.size());
-            while (matchIndex < charClass->m_matches.size())
-                matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass->m_matches[matchIndex++])));
-
-            failures.link(this);
-        } else if (charClass->m_matches.size()) {
-            // optimization: gather 'a','A' etc back together, can mask & test once.
-            Vector<char> matchesAZaz;
-
-            for (unsigned i = 0; i < charClass->m_matches.size(); ++i) {
-                char ch = charClass->m_matches[i];
-                if (m_pattern.m_ignoreCase) {
-                    if (isASCIILower(ch)) {
-                        matchesAZaz.append(ch);
-                        continue;
-                    }
-                    if (isASCIIUpper(ch))
-                        continue;
-                }
-                matchDest.append(branch32(Equal, character, Imm32((unsigned short)ch)));
-            }
-
-            if (unsigned countAZaz = matchesAZaz.size()) {
-                or32(Imm32(32), character);
-                for (unsigned i = 0; i < countAZaz; ++i)
-                    matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i])));
-            }
-        }
-
-        if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size())
-            unicodeFail.link(this);
-    }
-
-    // Jumps if input not available; will have (incorrectly) incremented already!
-    Jump jumpIfNoAvailableInput(unsigned countToCheck)
-    {
-        add32(Imm32(countToCheck), index);
-        return branch32(Above, index, length);
-    }
-
-    Jump jumpIfAvailableInput(unsigned countToCheck)
-    {
-        add32(Imm32(countToCheck), index);
-        return branch32(BelowOrEqual, index, length);
-    }
-
-    Jump checkInput()
-    {
-        return branch32(BelowOrEqual, index, length);
-    }
-
-    Jump atEndOfInput()
-    {
-        return branch32(Equal, index, length);
-    }
-
-    Jump notAtEndOfInput()
-    {
-        return branch32(NotEqual, index, length);
-    }
-
-    Jump jumpIfCharEquals(UChar ch, int inputPosition)
-    {
-        return branch16(Equal, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
-    }
-
-    Jump jumpIfCharNotEquals(UChar ch, int inputPosition)
-    {
-        return branch16(NotEqual, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
-    }
-
-    void readCharacter(int inputPosition, RegisterID reg)
-    {
-        load16(BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), reg);
-    }
-
-    void storeToFrame(RegisterID reg, unsigned frameLocation)
-    {
-        poke(reg, frameLocation);
-    }
-
-    void storeToFrame(Imm32 imm, unsigned frameLocation)
-    {
-        poke(imm, frameLocation);
-    }
-
-    DataLabelPtr storeToFrameWithPatch(unsigned frameLocation)
-    {
-        return storePtrWithPatch(ImmPtr(0), Address(stackPointerRegister, frameLocation * sizeof(void*)));
-    }
-
-    void loadFromFrame(unsigned frameLocation, RegisterID reg)
-    {
-        peek(reg, frameLocation);
-    }
-
-    void loadFromFrameAndJump(unsigned frameLocation)
-    {
-        jump(Address(stackPointerRegister, frameLocation * sizeof(void*)));
-    }
-
-    struct AlternativeBacktrackRecord {
-        DataLabelPtr dataLabel;
-        Label backtrackLocation;
-
-        AlternativeBacktrackRecord(DataLabelPtr dataLabel, Label backtrackLocation)
-            : dataLabel(dataLabel)
-            , backtrackLocation(backtrackLocation)
-        {
-        }
-    };
-
-    struct TermGenerationState {
-        TermGenerationState(PatternDisjunction* disjunction, unsigned checkedTotal)
-            : disjunction(disjunction)
-            , checkedTotal(checkedTotal)
-        {
-        }
-
-        void resetAlternative()
-        {
-            isBackTrackGenerated = false;
-            alt = 0;
-        }
-        bool alternativeValid()
-        {
-            return alt < disjunction->m_alternatives.size();
-        }
-        void nextAlternative()
-        {
-            ++alt;
-        }
-        PatternAlternative* alternative()
-        {
-            return disjunction->m_alternatives[alt];
-        }
-
-        void resetTerm()
-        {
-            ASSERT(alternativeValid());
-            t = 0;
-        }
-        bool termValid()
-        {
-            ASSERT(alternativeValid());
-            return t < alternative()->m_terms.size();
-        }
-        void nextTerm()
-        {
-            ASSERT(alternativeValid());
-            ++t;
-        }
-        PatternTerm& term()
-        {
-            ASSERT(alternativeValid());
-            return alternative()->m_terms[t];
-        }
-
-        PatternTerm& lookaheadTerm()
-        {
-            ASSERT(alternativeValid());
-            ASSERT((t + 1) < alternative()->m_terms.size());
-            return alternative()->m_terms[t + 1];
-        }
-        bool isSinglePatternCharacterLookaheadTerm()
-        {
-            ASSERT(alternativeValid());
-            return ((t + 1) < alternative()->m_terms.size())
-                && (lookaheadTerm().type == PatternTerm::TypePatternCharacter)
-                && (lookaheadTerm().quantityType == QuantifierFixedCount)
-                && (lookaheadTerm().quantityCount == 1);
-        }
-
-        int inputOffset()
-        {
-            return term().inputPosition - checkedTotal;
-        }
-
-        void jumpToBacktrack(Jump jump, MacroAssembler* masm)
-        {
-            if (isBackTrackGenerated)
-                jump.linkTo(backtrackLabel, masm);
-            else
-                backTrackJumps.append(jump);
-        }
-        void jumpToBacktrack(JumpList& jumps, MacroAssembler* masm)
-        {
-            if (isBackTrackGenerated)
-                jumps.linkTo(backtrackLabel, masm);
-            else
-                backTrackJumps.append(jumps);
-        }
-        bool plantJumpToBacktrackIfExists(MacroAssembler* masm)
-        {
-            if (isBackTrackGenerated) {
-                masm->jump(backtrackLabel);
-                return true;
-            }
-            return false;
-        }
-        void addBacktrackJump(Jump jump)
-        {
-            backTrackJumps.append(jump);
-        }
-        void setBacktrackGenerated(Label label)
-        {
-            isBackTrackGenerated = true;
-            backtrackLabel = label;
-        }
-        void linkAlternativeBacktracks(MacroAssembler* masm)
-        {
-            isBackTrackGenerated = false;
-            backTrackJumps.link(masm);
-        }
-        void linkAlternativeBacktracksTo(Label label, MacroAssembler* masm)
-        {
-            isBackTrackGenerated = false;
-            backTrackJumps.linkTo(label, masm);
-        }
-        void propagateBacktrackingFrom(TermGenerationState& nestedParenthesesState, MacroAssembler* masm)
-        {
-            jumpToBacktrack(nestedParenthesesState.backTrackJumps, masm);
-            if (nestedParenthesesState.isBackTrackGenerated)
-                setBacktrackGenerated(nestedParenthesesState.backtrackLabel);
-        }
-
-        PatternDisjunction* disjunction;
-        int checkedTotal;
-    private:
-        unsigned alt;
-        unsigned t;
-        JumpList backTrackJumps;
-        Label backtrackLabel;
-        bool isBackTrackGenerated;
-    };
-
-    void generateAssertionBOL(TermGenerationState& state)
-    {
-        PatternTerm& term = state.term();
-
-        if (m_pattern.m_multiline) {
-            const RegisterID character = regT0;
-
-            JumpList matchDest;
-            if (!term.inputPosition)
-                matchDest.append(branch32(Equal, index, Imm32(state.checkedTotal)));
-
-            readCharacter(state.inputOffset() - 1, character);
-            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
-            state.jumpToBacktrack(jump(), this);
-
-            matchDest.link(this);
-        } else {
-            // Erk, really should poison out these alternatives early. :-/
-            if (term.inputPosition)
-                state.jumpToBacktrack(jump(), this);
-            else
-                state.jumpToBacktrack(branch32(NotEqual, index, Imm32(state.checkedTotal)), this);
-        }
-    }
-
-    void generateAssertionEOL(TermGenerationState& state)
-    {
-        PatternTerm& term = state.term();
-
-        if (m_pattern.m_multiline) {
-            const RegisterID character = regT0;
-
-            JumpList matchDest;
-            if (term.inputPosition == state.checkedTotal)
-                matchDest.append(atEndOfInput());
-
-            readCharacter(state.inputOffset(), character);
-            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
-            state.jumpToBacktrack(jump(), this);
-
-            matchDest.link(this);
-        } else {
-            if (term.inputPosition == state.checkedTotal)
-                state.jumpToBacktrack(notAtEndOfInput(), this);
-            // Erk, really should poison out these alternatives early. :-/
-            else
-                state.jumpToBacktrack(jump(), this);
-        }
-    }
-
-    // Also falls though on nextIsNotWordChar.
-    void matchAssertionWordchar(TermGenerationState& state, JumpList& nextIsWordChar, JumpList& nextIsNotWordChar)
-    {
-        const RegisterID character = regT0;
-        PatternTerm& term = state.term();
-
-        if (term.inputPosition == state.checkedTotal)
-            nextIsNotWordChar.append(atEndOfInput());
-
-        readCharacter(state.inputOffset(), character);
-        matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass());
-    }
-
-    void generateAssertionWordBoundary(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        PatternTerm& term = state.term();
-
-        Jump atBegin;
-        JumpList matchDest;
-        if (!term.inputPosition)
-            atBegin = branch32(Equal, index, Imm32(state.checkedTotal));
-        readCharacter(state.inputOffset() - 1, character);
-        matchCharacterClass(character, matchDest, m_pattern.wordcharCharacterClass());
-        if (!term.inputPosition)
-            atBegin.link(this);
-
-        // We fall through to here if the last character was not a wordchar.
-        JumpList nonWordCharThenWordChar;
-        JumpList nonWordCharThenNonWordChar;
-        if (term.invertOrCapture) {
-            matchAssertionWordchar(state, nonWordCharThenNonWordChar, nonWordCharThenWordChar);
-            nonWordCharThenWordChar.append(jump());
-        } else {
-            matchAssertionWordchar(state, nonWordCharThenWordChar, nonWordCharThenNonWordChar);
-            nonWordCharThenNonWordChar.append(jump());
-        }
-        state.jumpToBacktrack(nonWordCharThenNonWordChar, this);
-
-        // We jump here if the last character was a wordchar.
-        matchDest.link(this);
-        JumpList wordCharThenWordChar;
-        JumpList wordCharThenNonWordChar;
-        if (term.invertOrCapture) {
-            matchAssertionWordchar(state, wordCharThenNonWordChar, wordCharThenWordChar);
-            wordCharThenWordChar.append(jump());
-        } else {
-            matchAssertionWordchar(state, wordCharThenWordChar, wordCharThenNonWordChar);
-            // This can fall-though!
-        }
-
-        state.jumpToBacktrack(wordCharThenWordChar, this);
-        
-        nonWordCharThenWordChar.link(this);
-        wordCharThenNonWordChar.link(this);
-    }
-
-    void generatePatternCharacterSingle(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        UChar ch = state.term().patternCharacter;
-
-        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
-            readCharacter(state.inputOffset(), character);
-            or32(Imm32(32), character);
-            state.jumpToBacktrack(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))), this);
-        } else {
-            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
-            state.jumpToBacktrack(jumpIfCharNotEquals(ch, state.inputOffset()), this);
-        }
-    }
-
-    void generatePatternCharacterPair(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        UChar ch1 = state.term().patternCharacter;
-        UChar ch2 = state.lookaheadTerm().patternCharacter;
-
-        int mask = 0;
-        int chPair = ch1 | (ch2 << 16);
-        
-        if (m_pattern.m_ignoreCase) {
-            if (isASCIIAlpha(ch1))
-                mask |= 32;
-            if (isASCIIAlpha(ch2))
-                mask |= 32 << 16;
-        }
-
-        if (mask) {
-            load32WithUnalignedHalfWords(BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), character);
-            or32(Imm32(mask), character);
-            state.jumpToBacktrack(branch32(NotEqual, character, Imm32(chPair | mask)), this);
-        } else
-            state.jumpToBacktrack(branch32WithUnalignedHalfWords(NotEqual, BaseIndex(input, index, TimesTwo, state.inputOffset() * sizeof(UChar)), Imm32(chPair)), this);
-    }
-
-    void generatePatternCharacterFixed(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        const RegisterID countRegister = regT1;
-        PatternTerm& term = state.term();
-        UChar ch = term.patternCharacter;
-
-        move(index, countRegister);
-        sub32(Imm32(term.quantityCount), countRegister);
-
-        Label loop(this);
-        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
-            load16(BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), character);
-            or32(Imm32(32), character);
-            state.jumpToBacktrack(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))), this);
-        } else {
-            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
-            state.jumpToBacktrack(branch16(NotEqual, BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), Imm32(ch)), this);
-        }
-        add32(Imm32(1), countRegister);
-        branch32(NotEqual, countRegister, index).linkTo(loop, this);
-    }
-
-    void generatePatternCharacterGreedy(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        const RegisterID countRegister = regT1;
-        PatternTerm& term = state.term();
-        UChar ch = term.patternCharacter;
-    
-        move(Imm32(0), countRegister);
-
-        JumpList failures;
-        Label loop(this);
-        failures.append(atEndOfInput());
-        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
-            readCharacter(state.inputOffset(), character);
-            or32(Imm32(32), character);
-            failures.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
-        } else {
-            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
-            failures.append(jumpIfCharNotEquals(ch, state.inputOffset()));
-        }
-
-        add32(Imm32(1), countRegister);
-        add32(Imm32(1), index);
-        if (term.quantityCount != 0xffffffff)
-            branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this);
-        else
-            jump(loop);
-
-        failures.append(jump());
-
-        Label backtrackBegin(this);
-        loadFromFrame(term.frameLocation, countRegister);
-        state.jumpToBacktrack(branchTest32(Zero, countRegister), this);
-        sub32(Imm32(1), countRegister);
-        sub32(Imm32(1), index);
-
-        failures.link(this);
-
-        storeToFrame(countRegister, term.frameLocation);
-
-        state.setBacktrackGenerated(backtrackBegin);
-    }
-
-    void generatePatternCharacterNonGreedy(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        const RegisterID countRegister = regT1;
-        PatternTerm& term = state.term();
-        UChar ch = term.patternCharacter;
-    
-        move(Imm32(0), countRegister);
-
-        Jump firstTimeDoNothing = jump();
-
-        Label hardFail(this);
-        sub32(countRegister, index);
-        state.jumpToBacktrack(jump(), this);
-
-        Label backtrackBegin(this);
-        loadFromFrame(term.frameLocation, countRegister);
-
-        atEndOfInput().linkTo(hardFail, this);
-        if (term.quantityCount != 0xffffffff)
-            branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail);
-        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
-            readCharacter(state.inputOffset(), character);
-            or32(Imm32(32), character);
-            branch32(NotEqual, character, Imm32(Unicode::toLower(ch))).linkTo(hardFail, this);
-        } else {
-            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
-            jumpIfCharNotEquals(ch, state.inputOffset()).linkTo(hardFail, this);
-        }
-
-        add32(Imm32(1), countRegister);
-        add32(Imm32(1), index);
-
-        firstTimeDoNothing.link(this);
-        storeToFrame(countRegister, term.frameLocation);
-
-        state.setBacktrackGenerated(backtrackBegin);
-    }
-
-    void generateCharacterClassSingle(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        PatternTerm& term = state.term();
-
-        JumpList matchDest;
-        readCharacter(state.inputOffset(), character);
-        matchCharacterClass(character, matchDest, term.characterClass);
-
-        if (term.invertOrCapture)
-            state.jumpToBacktrack(matchDest, this);
-        else {
-            state.jumpToBacktrack(jump(), this);
-            matchDest.link(this);
-        }
-    }
-
-    void generateCharacterClassFixed(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        const RegisterID countRegister = regT1;
-        PatternTerm& term = state.term();
-
-        move(index, countRegister);
-        sub32(Imm32(term.quantityCount), countRegister);
-
-        Label loop(this);
-        JumpList matchDest;
-        load16(BaseIndex(input, countRegister, TimesTwo, (state.inputOffset() + term.quantityCount) * sizeof(UChar)), character);
-        matchCharacterClass(character, matchDest, term.characterClass);
-
-        if (term.invertOrCapture)
-            state.jumpToBacktrack(matchDest, this);
-        else {
-            state.jumpToBacktrack(jump(), this);
-            matchDest.link(this);
-        }
-
-        add32(Imm32(1), countRegister);
-        branch32(NotEqual, countRegister, index).linkTo(loop, this);
-    }
-
-    void generateCharacterClassGreedy(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        const RegisterID countRegister = regT1;
-        PatternTerm& term = state.term();
-    
-        move(Imm32(0), countRegister);
-
-        JumpList failures;
-        Label loop(this);
-        failures.append(atEndOfInput());
-
-        if (term.invertOrCapture) {
-            readCharacter(state.inputOffset(), character);
-            matchCharacterClass(character, failures, term.characterClass);
-        } else {
-            JumpList matchDest;
-            readCharacter(state.inputOffset(), character);
-            matchCharacterClass(character, matchDest, term.characterClass);
-            failures.append(jump());
-            matchDest.link(this);
-        }
-
-        add32(Imm32(1), countRegister);
-        add32(Imm32(1), index);
-        if (term.quantityCount != 0xffffffff)
-            branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this);
-        else
-            jump(loop);
-
-        failures.append(jump());
-
-        Label backtrackBegin(this);
-        loadFromFrame(term.frameLocation, countRegister);
-        state.jumpToBacktrack(branchTest32(Zero, countRegister), this);
-        sub32(Imm32(1), countRegister);
-        sub32(Imm32(1), index);
-
-        failures.link(this);
-
-        storeToFrame(countRegister, term.frameLocation);
-
-        state.setBacktrackGenerated(backtrackBegin);
-    }
-
-    void generateCharacterClassNonGreedy(TermGenerationState& state)
-    {
-        const RegisterID character = regT0;
-        const RegisterID countRegister = regT1;
-        PatternTerm& term = state.term();
-    
-        move(Imm32(0), countRegister);
-
-        Jump firstTimeDoNothing = jump();
-
-        Label hardFail(this);
-        sub32(countRegister, index);
-        state.jumpToBacktrack(jump(), this);
-
-        Label backtrackBegin(this);
-        loadFromFrame(term.frameLocation, countRegister);
-
-        atEndOfInput().linkTo(hardFail, this);
-        branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail);
-
-        JumpList matchDest;
-        readCharacter(state.inputOffset(), character);
-        matchCharacterClass(character, matchDest, term.characterClass);
-
-        if (term.invertOrCapture)
-            matchDest.linkTo(hardFail, this);
-        else {
-            jump(hardFail);
-            matchDest.link(this);
-        }
-
-        add32(Imm32(1), countRegister);
-        add32(Imm32(1), index);
-
-        firstTimeDoNothing.link(this);
-        storeToFrame(countRegister, term.frameLocation);
-
-        state.setBacktrackGenerated(backtrackBegin);
-    }
-
-    void generateParenthesesDisjunction(PatternTerm& parenthesesTerm, TermGenerationState& state, unsigned alternativeFrameLocation)
-    {
-        ASSERT((parenthesesTerm.type == PatternTerm::TypeParenthesesSubpattern) || (parenthesesTerm.type == PatternTerm::TypeParentheticalAssertion));
-        ASSERT(parenthesesTerm.quantityCount == 1);
-    
-        PatternDisjunction* disjunction = parenthesesTerm.parentheses.disjunction;
-        unsigned preCheckedCount = ((parenthesesTerm.quantityType == QuantifierFixedCount) && (parenthesesTerm.type != PatternTerm::TypeParentheticalAssertion)) ? disjunction->m_minimumSize : 0;
-
-        if (disjunction->m_alternatives.size() == 1) {
-            state.resetAlternative();
-            ASSERT(state.alternativeValid());
-            PatternAlternative* alternative = state.alternative();
-            optimizeAlternative(alternative);
-
-            int countToCheck = alternative->m_minimumSize - preCheckedCount;
-            if (countToCheck) {
-                ASSERT((parenthesesTerm.type == PatternTerm::TypeParentheticalAssertion) || (parenthesesTerm.quantityType != QuantifierFixedCount));
-
-                // FIXME: This is quite horrible.  The call to 'plantJumpToBacktrackIfExists'
-                // will be forced to always trampoline into here, just to decrement the index.
-                // Ick. 
-                Jump skip = jump();
-
-                Label backtrackBegin(this);
-                sub32(Imm32(countToCheck), index);
-                state.addBacktrackJump(jump());
-                
-                skip.link(this);
-
-                state.setBacktrackGenerated(backtrackBegin);
-
-                state.jumpToBacktrack(jumpIfNoAvailableInput(countToCheck), this);
-                state.checkedTotal += countToCheck;
-            }
-
-            for (state.resetTerm(); state.termValid(); state.nextTerm())
-                generateTerm(state);
-
-            state.checkedTotal -= countToCheck;
-        } else {
-            JumpList successes;
-
-            for (state.resetAlternative(); state.alternativeValid(); state.nextAlternative()) {
-
-                PatternAlternative* alternative = state.alternative();
-                optimizeAlternative(alternative);
-
-                ASSERT(alternative->m_minimumSize >= preCheckedCount);
-                int countToCheck = alternative->m_minimumSize - preCheckedCount;
-                if (countToCheck) {
-                    state.addBacktrackJump(jumpIfNoAvailableInput(countToCheck));
-                    state.checkedTotal += countToCheck;
-                }
-
-                for (state.resetTerm(); state.termValid(); state.nextTerm())
-                    generateTerm(state);
-
-                // Matched an alternative.
-                DataLabelPtr dataLabel = storeToFrameWithPatch(alternativeFrameLocation);
-                successes.append(jump());
-
-                // Alternative did not match.
-                Label backtrackLocation(this);
-                
-                // Can we backtrack the alternative? - if so, do so.  If not, just fall through to the next one.
-                state.plantJumpToBacktrackIfExists(this);
-                
-                state.linkAlternativeBacktracks(this);
-
-                if (countToCheck) {
-                    sub32(Imm32(countToCheck), index);
-                    state.checkedTotal -= countToCheck;
-                }
-
-                m_backtrackRecords.append(AlternativeBacktrackRecord(dataLabel, backtrackLocation));
-            }
-            // We fall through to here when the last alternative fails.
-            // Add a backtrack out of here for the parenthese handling code to link up.
-            state.addBacktrackJump(jump());
-
-            // Generate a trampoline for the parens code to backtrack to, to retry the
-            // next alternative.
-            state.setBacktrackGenerated(label());
-            loadFromFrameAndJump(alternativeFrameLocation);
-
-            // FIXME: both of the above hooks are a little inefficient, in that you
-            // may end up trampolining here, just to trampoline back out to the
-            // parentheses code, or vice versa.  We can probably eliminate a jump
-            // by restructuring, but coding this way for now for simplicity during
-            // development.
-
-            successes.link(this);
-        }
-    }
-
-    void generateParenthesesSingle(TermGenerationState& state)
-    {
-        const RegisterID indexTemporary = regT0;
-        PatternTerm& term = state.term();
-        PatternDisjunction* disjunction = term.parentheses.disjunction;
-        ASSERT(term.quantityCount == 1);
-
-        unsigned preCheckedCount = ((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount)) ? disjunction->m_minimumSize : 0;
-
-        unsigned parenthesesFrameLocation = term.frameLocation;
-        unsigned alternativeFrameLocation = parenthesesFrameLocation;
-        if (term.quantityType != QuantifierFixedCount)
-            alternativeFrameLocation += RegexStackSpaceForBackTrackInfoParenthesesOnce;
-
-        // optimized case - no capture & no quantifier can be handled in a light-weight manner.
-        if (!term.invertOrCapture && (term.quantityType == QuantifierFixedCount)) {
-            TermGenerationState parenthesesState(disjunction, state.checkedTotal);
-            generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
-            // this expects that any backtracks back out of the parentheses will be in the
-            // parenthesesState's backTrackJumps vector, and that if they need backtracking
-            // they will have set an entry point on the parenthesesState's backtrackLabel.
-            state.propagateBacktrackingFrom(parenthesesState, this);
-        } else {
-            Jump nonGreedySkipParentheses;
-            Label nonGreedyTryParentheses;
-            if (term.quantityType == QuantifierGreedy)
-                storeToFrame(Imm32(1), parenthesesFrameLocation);
-            else if (term.quantityType == QuantifierNonGreedy) {
-                storeToFrame(Imm32(0), parenthesesFrameLocation);
-                nonGreedySkipParentheses = jump();
-                nonGreedyTryParentheses = label();
-                storeToFrame(Imm32(1), parenthesesFrameLocation);
-            }
-
-            // store the match start index
-            if (term.invertOrCapture) {
-                int inputOffset = state.inputOffset() - preCheckedCount;
-                if (inputOffset) {
-                    move(index, indexTemporary);
-                    add32(Imm32(inputOffset), indexTemporary);
-                    store32(indexTemporary, Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
-                } else
-                    store32(index, Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
-            }
-
-            // generate the body of the parentheses
-            TermGenerationState parenthesesState(disjunction, state.checkedTotal);
-            generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
-
-            // store the match end index
-            if (term.invertOrCapture) {
-                int inputOffset = state.inputOffset();
-                if (inputOffset) {
-                    move(index, indexTemporary);
-                    add32(Imm32(state.inputOffset()), indexTemporary);
-                    store32(indexTemporary, Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
-                } else
-                    store32(index, Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
-            }
-            Jump success = jump();
-
-            // A failure AFTER the parens jumps here
-            Label backtrackFromAfterParens(this);
-
-            if (term.quantityType == QuantifierGreedy) {
-                // If this is zero we have now tested with both with and without the parens.
-                loadFromFrame(parenthesesFrameLocation, indexTemporary);
-                state.jumpToBacktrack(branchTest32(Zero, indexTemporary), this);
-            } else if (term.quantityType == QuantifierNonGreedy) {
-                // If this is zero we have now tested with both with and without the parens.
-                loadFromFrame(parenthesesFrameLocation, indexTemporary);
-                branchTest32(Zero, indexTemporary).linkTo(nonGreedyTryParentheses, this);
-            }
-
-            parenthesesState.plantJumpToBacktrackIfExists(this);
-            // A failure WITHIN the parens jumps here
-            parenthesesState.linkAlternativeBacktracks(this);
-            if (term.invertOrCapture) {
-                store32(Imm32(-1), Address(output, (term.parentheses.subpatternId << 1) * sizeof(int)));
-                store32(Imm32(-1), Address(output, ((term.parentheses.subpatternId << 1) + 1) * sizeof(int)));
-            }
-
-            if (term.quantityType == QuantifierGreedy)
-                storeToFrame(Imm32(0), parenthesesFrameLocation);
-            else
-                state.jumpToBacktrack(jump(), this);
-
-            state.setBacktrackGenerated(backtrackFromAfterParens);
-            if (term.quantityType == QuantifierNonGreedy)
-                nonGreedySkipParentheses.link(this);
-            success.link(this);
-        }
-    }
-
-    void generateParentheticalAssertion(TermGenerationState& state)
-    {
-        PatternTerm& term = state.term();
-        PatternDisjunction* disjunction = term.parentheses.disjunction;
-        ASSERT(term.quantityCount == 1);
-        ASSERT(term.quantityType == QuantifierFixedCount);
-
-        unsigned parenthesesFrameLocation = term.frameLocation;
-        unsigned alternativeFrameLocation = parenthesesFrameLocation + RegexStackSpaceForBackTrackInfoParentheticalAssertion;
-
-        int countCheckedAfterAssertion = state.checkedTotal - term.inputPosition;
-
-        if (term.invertOrCapture) {
-            // Inverted case
-            storeToFrame(index, parenthesesFrameLocation);
-
-            state.checkedTotal -= countCheckedAfterAssertion;
-            if (countCheckedAfterAssertion)
-                sub32(Imm32(countCheckedAfterAssertion), index);
-
-            TermGenerationState parenthesesState(disjunction, state.checkedTotal);
-            generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
-            // Success! - which means - Fail!
-            loadFromFrame(parenthesesFrameLocation, index);
-            state.jumpToBacktrack(jump(), this);
-
-            // And fail means success.
-            parenthesesState.linkAlternativeBacktracks(this);
-            loadFromFrame(parenthesesFrameLocation, index);
-
-            state.checkedTotal += countCheckedAfterAssertion;
-        } else {
-            // Normal case
-            storeToFrame(index, parenthesesFrameLocation);
-
-            state.checkedTotal -= countCheckedAfterAssertion;
-            if (countCheckedAfterAssertion)
-                sub32(Imm32(countCheckedAfterAssertion), index);
-
-            TermGenerationState parenthesesState(disjunction, state.checkedTotal);
-            generateParenthesesDisjunction(state.term(), parenthesesState, alternativeFrameLocation);
-            // Success! - which means - Success!
-            loadFromFrame(parenthesesFrameLocation, index);
-            Jump success = jump();
-
-            parenthesesState.linkAlternativeBacktracks(this);
-            loadFromFrame(parenthesesFrameLocation, index);
-            state.jumpToBacktrack(jump(), this);
-
-            success.link(this);
-
-            state.checkedTotal += countCheckedAfterAssertion;
-        }
-    }
-
-    void generateTerm(TermGenerationState& state)
-    {
-        PatternTerm& term = state.term();
-
-        switch (term.type) {
-        case PatternTerm::TypeAssertionBOL:
-            generateAssertionBOL(state);
-            break;
-        
-        case PatternTerm::TypeAssertionEOL:
-            generateAssertionEOL(state);
-            break;
-        
-        case PatternTerm::TypeAssertionWordBoundary:
-            generateAssertionWordBoundary(state);
-            break;
-        
-        case PatternTerm::TypePatternCharacter:
-            switch (term.quantityType) {
-            case QuantifierFixedCount:
-                if (term.quantityCount == 1) {
-                    if (state.isSinglePatternCharacterLookaheadTerm() && (state.lookaheadTerm().inputPosition == (term.inputPosition + 1))) {
-                        generatePatternCharacterPair(state);
-                        state.nextTerm();
-                    } else
-                        generatePatternCharacterSingle(state);
-                } else
-                    generatePatternCharacterFixed(state);
-                break;
-            case QuantifierGreedy:
-                generatePatternCharacterGreedy(state);
-                break;
-            case QuantifierNonGreedy:
-                generatePatternCharacterNonGreedy(state);
-                break;
-            }
-            break;
-
-        case PatternTerm::TypeCharacterClass:
-            switch (term.quantityType) {
-            case QuantifierFixedCount:
-                if (term.quantityCount == 1)
-                    generateCharacterClassSingle(state);
-                else
-                    generateCharacterClassFixed(state);
-                break;
-            case QuantifierGreedy:
-                generateCharacterClassGreedy(state);
-                break;
-            case QuantifierNonGreedy:
-                generateCharacterClassNonGreedy(state);
-                break;
-            }
-            break;
-
-        case PatternTerm::TypeBackReference:
-            ASSERT_NOT_REACHED();
-            break;
-
-        case PatternTerm::TypeForwardReference:
-            break;
-
-        case PatternTerm::TypeParenthesesSubpattern:
-            ASSERT((term.quantityCount == 1) && !term.parentheses.isCopy); // must fallback to pcre before this point
-            generateParenthesesSingle(state);
-            break;
-
-        case PatternTerm::TypeParentheticalAssertion:
-            generateParentheticalAssertion(state);
-            break;
-        }
-    }
-
-    void generateDisjunction(PatternDisjunction* disjunction)
-    {
-        TermGenerationState state(disjunction, 0);
-        state.resetAlternative();
-
-        // Plant a check to see if there is sufficient input available to run the first alternative.
-        // Jumping back to the label 'firstAlternative' will get to this check, jumping to
-        // 'firstAlternativeInputChecked' will jump directly to matching the alternative having
-        // skipped this check.
-
-        Label firstAlternative(this);
-
-        // check availability for the next alternative
-        int countCheckedForCurrentAlternative = 0;
-        int countToCheckForFirstAlternative = 0;
-        bool hasShorterAlternatives = false;
-        JumpList notEnoughInputForPreviousAlternative;
-
-        if (state.alternativeValid()) {
-            PatternAlternative* alternative = state.alternative();
-            countToCheckForFirstAlternative = alternative->m_minimumSize;
-            state.checkedTotal += countToCheckForFirstAlternative;
-            if (countToCheckForFirstAlternative)
-                notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForFirstAlternative));
-            countCheckedForCurrentAlternative = countToCheckForFirstAlternative;
-        }
-
-        Label firstAlternativeInputChecked(this);
-
-        while (state.alternativeValid()) {
-            // Track whether any alternatives are shorter than the first one.
-            hasShorterAlternatives = hasShorterAlternatives || (countCheckedForCurrentAlternative < countToCheckForFirstAlternative);
-
-            PatternAlternative* alternative = state.alternative();
-            optimizeAlternative(alternative);
-
-            for (state.resetTerm(); state.termValid(); state.nextTerm())
-                generateTerm(state);
-
-            // If we get here, the alternative matched.
-            if (m_pattern.m_body->m_callFrameSize)
-                addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
-            
-            ASSERT(index != returnRegister);
-            if (m_pattern.m_body->m_hasFixedSize) {
-                move(index, returnRegister);
-                if (alternative->m_minimumSize)
-                    sub32(Imm32(alternative->m_minimumSize), returnRegister);
-            } else
-                pop(returnRegister);
-            store32(index, Address(output, 4));
-            store32(returnRegister, output);
-
-            generateReturn();
-
-            state.nextAlternative();
-
-            // if there are any more alternatives, plant the check for input before looping.
-            if (state.alternativeValid()) {
-                PatternAlternative* nextAlternative = state.alternative();
-                int countToCheckForNextAlternative = nextAlternative->m_minimumSize;
-
-                if (countCheckedForCurrentAlternative > countToCheckForNextAlternative) { // CASE 1: current alternative was longer than the next one.
-                    // If we get here, there the last input checked failed.
-                    notEnoughInputForPreviousAlternative.link(this);
-
-                    // Check if sufficent input available to run the next alternative 
-                    notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForNextAlternative - countCheckedForCurrentAlternative));
-                    // We are now in the correct state to enter the next alternative; this add is only required
-                    // to mirror and revert operation of the sub32, just below.
-                    add32(Imm32(countCheckedForCurrentAlternative - countToCheckForNextAlternative), index);
-
-                    // If we get here, there the last input checked passed.
-                    state.linkAlternativeBacktracks(this);
-                    // No need to check if we can run the next alternative, since it is shorter -
-                    // just update index.
-                    sub32(Imm32(countCheckedForCurrentAlternative - countToCheckForNextAlternative), index);
-                } else if (countCheckedForCurrentAlternative < countToCheckForNextAlternative) { // CASE 2: next alternative is longer than the current one.
-                    // If we get here, there the last input checked failed.
-                    // If there is insufficient input to run the current alternative, and the next alternative is longer,
-                    // then there is definitely not enough input to run it - don't even check. Just adjust index, as if
-                    // we had checked.
-                    notEnoughInputForPreviousAlternative.link(this);
-                    add32(Imm32(countToCheckForNextAlternative - countCheckedForCurrentAlternative), index);
-                    notEnoughInputForPreviousAlternative.append(jump());
-
-                    // The next alternative is longer than the current one; check the difference.
-                    state.linkAlternativeBacktracks(this);
-                    notEnoughInputForPreviousAlternative.append(jumpIfNoAvailableInput(countToCheckForNextAlternative - countCheckedForCurrentAlternative));
-                } else { // CASE 3: Both alternatives are the same length.
-                    ASSERT(countCheckedForCurrentAlternative == countToCheckForNextAlternative);
-
-                    // If the next alterative is the same length as this one, then no need to check the input -
-                    // if there was sufficent input to run the current alternative then there is sufficient
-                    // input to run the next one; if not, there isn't.
-                    state.linkAlternativeBacktracks(this);
-                }
-
-                state.checkedTotal -= countCheckedForCurrentAlternative;
-                countCheckedForCurrentAlternative = countToCheckForNextAlternative;
-                state.checkedTotal += countCheckedForCurrentAlternative;
-            }
-        }
-        
-        // If we get here, all Alternatives failed...
-
-        state.checkedTotal -= countCheckedForCurrentAlternative;
-
-        // How much more input need there be to be able to retry from the first alternative?
-        // examples:
-        //   /yarr_jit/ or /wrec|pcre/
-        //     In these examples we need check for one more input before looping.
-        //   /yarr_jit|pcre/
-        //     In this case we need check for 5 more input to loop (+4 to allow for the first alterative
-        //     being four longer than the last alternative checked, and another +1 to effectively move
-        //     the start position along by one).
-        //   /yarr|rules/ or /wrec|notsomuch/
-        //     In these examples, provided that there was sufficient input to have just been matching for
-        //     the second alternative we can loop without checking for available input (since the second
-        //     alternative is longer than the first).  In the latter example we need to decrement index
-        //     (by 4) so the start position is only progressed by 1 from the last iteration.
-        int incrementForNextIter = (countToCheckForFirstAlternative - countCheckedForCurrentAlternative) + 1;
-
-        // First, deal with the cases where there was sufficient input to try the last alternative.
-        if (incrementForNextIter > 0) // We need to check for more input anyway, fall through to the checking below.
-            state.linkAlternativeBacktracks(this);
-        else if (m_pattern.m_body->m_hasFixedSize && !incrementForNextIter) // No need to update anything, link these backtracks straight to the to pof the loop!
-            state.linkAlternativeBacktracksTo(firstAlternativeInputChecked, this);
-        else { // no need to check the input, but we do have some bookkeeping to do first.
-            state.linkAlternativeBacktracks(this);
-
-            // Where necessary update our preserved start position.
-            if (!m_pattern.m_body->m_hasFixedSize) {
-                move(index, regT0);
-                sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0);
-                poke(regT0, m_pattern.m_body->m_callFrameSize);
-            }
-
-            // Update index if necessary, and loop (without checking).
-            if (incrementForNextIter)
-                add32(Imm32(incrementForNextIter), index);
-            jump().linkTo(firstAlternativeInputChecked, this);
-        }
-
-        notEnoughInputForPreviousAlternative.link(this);
-        // Update our idea of the start position, if we're tracking this.
-        if (!m_pattern.m_body->m_hasFixedSize) {
-            if (countCheckedForCurrentAlternative - 1) {
-                move(index, regT0);
-                sub32(Imm32(countCheckedForCurrentAlternative - 1), regT0);
-                poke(regT0, m_pattern.m_body->m_callFrameSize);
-            } else
-                poke(index, m_pattern.m_body->m_callFrameSize);
-        }
-        // Check if there is sufficent input to run the first alternative again.
-        jumpIfAvailableInput(incrementForNextIter).linkTo(firstAlternativeInputChecked, this);
-        // No - insufficent input to run the first alteranative, are there any other alternatives we
-        // might need to check?  If so, the last check will have left the index incremented by
-        // (countToCheckForFirstAlternative + 1), so we need test whether countToCheckForFirstAlternative
-        // LESS input is available, to have the effect of just progressing the start position by 1
-        // from the last iteration.  If this check passes we can just jump up to the check associated
-        // with the first alternative in the loop.  This is a bit sad, since we'll end up trying the
-        // first alternative again, and this check will fail (otherwise the check planted just above
-        // here would have passed).  This is a bit sad, however it saves trying to do something more
-        // complex here in compilation, and in the common case we should end up coallescing the checks.
-        //
-        // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least
-        // of the minimum-alternative-lengths.  E.g. if I have two alternatives of length 200 and 150,
-        // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there
-        // is sufficient input to run either alternative (constantly failing).  If there had been only
-        // one alternative, or if the shorter alternative had come first, we would have terminated
-        // immediately. :-/
-        if (hasShorterAlternatives)
-            jumpIfAvailableInput(-countToCheckForFirstAlternative).linkTo(firstAlternative, this);
-        // index will now be a bit garbled (depending on whether 'hasShorterAlternatives' is true,
-        // it has either been incremented by 1 or by (countToCheckForFirstAlternative + 1) ... 
-        // but since we're about to return a failure this doesn't really matter!)
-
-        unsigned frameSize = m_pattern.m_body->m_callFrameSize;
-        if (!m_pattern.m_body->m_hasFixedSize)
-            ++frameSize;
-        if (frameSize)
-            addPtr(Imm32(frameSize * sizeof(void*)), stackPointerRegister);
-
-        move(Imm32(-1), returnRegister);
-
-        generateReturn();
-    }
-
-    void generateEnter()
-    {
-#if CPU(X86_64)
-        push(X86Registers::ebp);
-        move(stackPointerRegister, X86Registers::ebp);
-        push(X86Registers::ebx);
-#elif CPU(X86)
-        push(X86Registers::ebp);
-        move(stackPointerRegister, X86Registers::ebp);
-        // TODO: do we need spill registers to fill the output pointer if there are no sub captures?
-        push(X86Registers::ebx);
-        push(X86Registers::edi);
-        push(X86Registers::esi);
-        // load output into edi (2 = saved ebp + return address).
-    #if COMPILER(MSVC)
-        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), input);
-        loadPtr(Address(X86Registers::ebp, 3 * sizeof(void*)), index);
-        loadPtr(Address(X86Registers::ebp, 4 * sizeof(void*)), length);
-        loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output);
-    #else
-        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
-    #endif
-#elif CPU(ARM)
-        push(ARMRegisters::r4);
-        push(ARMRegisters::r5);
-        push(ARMRegisters::r6);
-        move(ARMRegisters::r3, output);
-#elif CPU(MIPS)
-        // Do nothing.
-#endif
-    }
-
-    void generateReturn()
-    {
-#if CPU(X86_64)
-        pop(X86Registers::ebx);
-        pop(X86Registers::ebp);
-#elif CPU(X86)
-        pop(X86Registers::esi);
-        pop(X86Registers::edi);
-        pop(X86Registers::ebx);
-        pop(X86Registers::ebp);
-#elif CPU(ARM)
-        pop(ARMRegisters::r6);
-        pop(ARMRegisters::r5);
-        pop(ARMRegisters::r4);
-#elif CPU(MIPS)
-        // Do nothing
-#endif
-        ret();
-    }
-
-public:
-    RegexGenerator(RegexPattern& pattern)
-        : m_pattern(pattern)
-    {
-    }
-
-    void generate()
-    {
-        generateEnter();
-
-        // TODO: do I really want this on the stack?
-        if (!m_pattern.m_body->m_hasFixedSize)
-            push(index);
-
-        if (m_pattern.m_body->m_callFrameSize)
-            subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
-
-        generateDisjunction(m_pattern.m_body);
-    }
-
-    void compile(JSGlobalData* globalData, RegexCodeBlock& jitObject)
-    {
-        generate();
-
-        LinkBuffer patchBuffer(this, globalData->regexAllocator.poolForSize(size()), 0);
-
-        for (unsigned i = 0; i < m_backtrackRecords.size(); ++i)
-            patchBuffer.patch(m_backtrackRecords[i].dataLabel, patchBuffer.locationOf(m_backtrackRecords[i].backtrackLocation));
-
-        jitObject.set(patchBuffer.finalizeCode());
-    }
-
-private:
-    RegexPattern& m_pattern;
-    Vector<AlternativeBacktrackRecord> m_backtrackRecords;
-};
-
-void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline)
-{
-    RegexPattern pattern(ignoreCase, multiline);
-    if ((error = compileRegex(patternString, pattern)))
-        return;
-    numSubpatterns = pattern.m_numSubpatterns;
-
-    if (!pattern.m_shouldFallBack && globalData->canUseJIT() && RegExpCache::isCacheable(patternString)) {
-        RegexGenerator generator(pattern);
-        generator.compile(globalData, jitObject);
-        return;
-    }
-
-    JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase;
-    JSRegExpMultilineOption multilineOption = multiline ? JSRegExpMultiline : JSRegExpSingleLine;
-    jitObject.setFallback(jsRegExpCompile(reinterpret_cast<const UChar*>(patternString.data()), patternString.size(), ignoreCaseOption, multilineOption, &numSubpatterns, &error));
-}
-
-}}
-
-#endif
-
-
-
-
-
diff --git a/yarr/RegexJIT.h b/yarr/RegexJIT.h
deleted file mode 100644 (file)
index 7f9c16e..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2009 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 RegexJIT_h
-#define RegexJIT_h
-
-#if ENABLE(YARR_JIT)
-
-#include "MacroAssembler.h"
-#include "RegexPattern.h"
-#include <UString.h>
-
-#include <pcre.h>
-struct JSRegExp; // temporary, remove when fallback is removed.
-
-#if CPU(X86) && !COMPILER(MSVC)
-#define YARR_CALL __attribute__ ((regparm (3)))
-#else
-#define YARR_CALL
-#endif
-
-namespace JSC {
-
-class JSGlobalData;
-class ExecutablePool;
-
-namespace Yarr {
-
-class RegexCodeBlock {
-    typedef int (*RegexJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
-
-public:
-    RegexCodeBlock()
-        : m_fallback(0)
-    {
-    }
-
-    ~RegexCodeBlock()
-    {
-        if (m_fallback)
-            jsRegExpFree(m_fallback);
-    }
-
-    JSRegExp* getFallback() { return m_fallback; }
-    void setFallback(JSRegExp* fallback) { m_fallback = fallback; }
-
-    bool operator!() { return (!m_ref.m_code.executableAddress() && !m_fallback); }
-    void set(MacroAssembler::CodeRef ref) { m_ref = ref; }
-
-    int execute(const UChar* input, unsigned start, unsigned length, int* output)
-    {
-        return reinterpret_cast<RegexJITCode>(m_ref.m_code.executableAddress())(input, start, length, output);
-    }
-
-private:
-    MacroAssembler::CodeRef m_ref;
-    JSRegExp* m_fallback;
-};
-
-void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false);
-
-inline int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize)
-{
-    if (JSRegExp* fallback = jitObject.getFallback())
-        return (jsRegExpExecute(fallback, input, length, start, output, outputArraySize) < 0) ? -1 : output[0];
-
-    return jitObject.execute(input, start, length, output);
-}
-
-} } // namespace JSC::Yarr
-
-#endif
-
-#endif // RegexJIT_h
diff --git a/yarr/RegexParser.h b/yarr/RegexParser.h
deleted file mode 100644 (file)
index c946c2e..0000000
+++ /dev/null
@@ -1,852 +0,0 @@
-/*
- * Copyright (C) 2009 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 RegexParser_h
-#define RegexParser_h
-
-#if ENABLE(YARR)
-
-#include <UString.h>
-#include <limits.h>
-#include <wtf/ASCIICType.h>
-#include <wtf/unicode/Unicode.h>
-
-namespace JSC { namespace Yarr {
-
-enum BuiltInCharacterClassID {
-    DigitClassID,
-    SpaceClassID,
-    WordClassID,
-    NewlineClassID,
-};
-
-// The Parser class should not be used directly - only via the Yarr::parse() method.
-template<class Delegate>
-class Parser {
-private:
-    template<class FriendDelegate>
-    friend const char* parse(FriendDelegate& delegate, const UString& pattern, unsigned backReferenceLimit);
-
-    enum ErrorCode {
-        NoError,
-        PatternTooLarge,
-        QuantifierOutOfOrder,
-        QuantifierWithoutAtom,
-        MissingParentheses,
-        ParenthesesUnmatched,
-        ParenthesesTypeInvalid,
-        CharacterClassUnmatched,
-        CharacterClassOutOfOrder,
-        EscapeUnterminated,
-        NumberOfErrorCodes
-    };
-
-    /*
-     * CharacterClassParserDelegate:
-     *
-     * The class CharacterClassParserDelegate is used in the parsing of character
-     * classes.  This class handles detection of character ranges.  This class
-     * implements enough of the delegate interface such that it can be passed to
-     * parseEscape() as an EscapeDelegate.  This allows parseEscape() to be reused
-     * to perform the parsing of escape characters in character sets.
-     */
-    class CharacterClassParserDelegate {
-    public:
-        CharacterClassParserDelegate(Delegate& delegate, ErrorCode& err)
-            : m_delegate(delegate)
-            , m_err(err)
-            , m_state(empty)
-        {
-        }
-
-        /*
-         * begin():
-         *
-         * Called at beginning of construction.
-         */
-        void begin(bool invert)
-        {
-            m_delegate.atomCharacterClassBegin(invert);
-        }
-
-        /*
-         * atomPatternCharacterUnescaped():
-         *
-         * This method is called directly from parseCharacterClass(), to report a new
-         * pattern character token.  This method differs from atomPatternCharacter(),
-         * which will be called from parseEscape(), since a hypen provided via this
-         * method may be indicating a character range, but a hyphen parsed by
-         * parseEscape() cannot be interpreted as doing so.
-         */
-        void atomPatternCharacterUnescaped(UChar ch)
-        {
-            switch (m_state) {
-            case empty:
-                m_character = ch;
-                m_state = cachedCharacter;
-                break;
-
-            case cachedCharacter:
-                if (ch == '-')
-                    m_state = cachedCharacterHyphen;
-                else {
-                    m_delegate.atomCharacterClassAtom(m_character);
-                    m_character = ch;
-                }
-                break;
-
-            case cachedCharacterHyphen:
-                if (ch >= m_character)
-                    m_delegate.atomCharacterClassRange(m_character, ch);
-                else
-                    m_err = CharacterClassOutOfOrder;
-                m_state = empty;
-            }
-        }
-
-        /*
-         * atomPatternCharacter():
-         *
-         * Adds a pattern character, called by parseEscape(), as such will not
-         * interpret a hyphen as indicating a character range.
-         */
-        void atomPatternCharacter(UChar ch)
-        {
-            // Flush if a character is already pending to prevent the
-            // hyphen from begin interpreted as indicating a range.
-            if((ch == '-') && (m_state == cachedCharacter))
-                flush();
-
-            atomPatternCharacterUnescaped(ch);
-        }
-
-        /*
-         * atomBuiltInCharacterClass():
-         *
-         * Adds a built-in character class, called by parseEscape().
-         */
-        void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
-        {
-            flush();
-            m_delegate.atomCharacterClassBuiltIn(classID, invert);
-        }
-
-        /*
-         * end():
-         *
-         * Called at end of construction.
-         */
-        void end()
-        {
-            flush();
-            m_delegate.atomCharacterClassEnd();
-        }
-
-        // parseEscape() should never call these delegate methods when
-        // invoked with inCharacterClass set.
-        void assertionWordBoundary(bool) { ASSERT_NOT_REACHED(); }
-        void atomBackReference(unsigned) { ASSERT_NOT_REACHED(); }
-
-    private:
-        void flush()
-        {
-            if (m_state != empty) // either cachedCharacter or cachedCharacterHyphen
-                m_delegate.atomCharacterClassAtom(m_character);
-            if (m_state == cachedCharacterHyphen)
-                m_delegate.atomCharacterClassAtom('-');
-            m_state = empty;
-        }
-    
-        Delegate& m_delegate;
-        ErrorCode& m_err;
-        enum CharacterClassConstructionState {
-            empty,
-            cachedCharacter,
-            cachedCharacterHyphen,
-        } m_state;
-        UChar m_character;
-    };
-
-    Parser(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit)
-        : m_delegate(delegate)
-        , m_backReferenceLimit(backReferenceLimit)
-        , m_err(NoError)
-        , m_data(pattern.data())
-        , m_size(pattern.size())
-        , m_index(0)
-        , m_parenthesesNestingDepth(0)
-    {
-    }
-    
-    /*
-     * parseEscape():
-     *
-     * Helper for parseTokens() AND parseCharacterClass().
-     * Unlike the other parser methods, this function does not report tokens
-     * directly to the member delegate (m_delegate), instead tokens are
-     * emitted to the delegate provided as an argument.  In the case of atom
-     * escapes, parseTokens() will call parseEscape() passing m_delegate as
-     * an argument, and as such the escape will be reported to the delegate.
-     *
-     * However this method may also be used by parseCharacterClass(), in which
-     * case a CharacterClassParserDelegate will be passed as the delegate that
-     * tokens should be added to.  A boolean flag is also provided to indicate
-     * whether that an escape in a CharacterClass is being parsed (some parsing
-     * rules change in this context).
-     *
-     * The boolean value returned by this method indicates whether the token
-     * parsed was an atom (outside of a characted class \b and \B will be
-     * interpreted as assertions).
-     */
-    template<bool inCharacterClass, class EscapeDelegate>
-    bool parseEscape(EscapeDelegate& delegate)
-    {
-        ASSERT(!m_err);
-        ASSERT(peek() == '\\');
-        consume();
-
-        if (atEndOfPattern()) {
-            m_err = EscapeUnterminated;
-            return false;
-        }
-
-        switch (peek()) {
-        // Assertions
-        case 'b':
-            consume();
-            if (inCharacterClass)
-                delegate.atomPatternCharacter('\b');
-            else {
-                delegate.assertionWordBoundary(false);
-                return false;
-            }
-            break;
-        case 'B':
-            consume();
-            if (inCharacterClass)
-                delegate.atomPatternCharacter('B');
-            else {
-                delegate.assertionWordBoundary(true);
-                return false;
-            }
-            break;
-
-        // CharacterClassEscape
-        case 'd':
-            consume();
-            delegate.atomBuiltInCharacterClass(DigitClassID, false);
-            break;
-        case 's':
-            consume();
-            delegate.atomBuiltInCharacterClass(SpaceClassID, false);
-            break;
-        case 'w':
-            consume();
-            delegate.atomBuiltInCharacterClass(WordClassID, false);
-            break;
-        case 'D':
-            consume();
-            delegate.atomBuiltInCharacterClass(DigitClassID, true);
-            break;
-        case 'S':
-            consume();
-            delegate.atomBuiltInCharacterClass(SpaceClassID, true);
-            break;
-        case 'W':
-            consume();
-            delegate.atomBuiltInCharacterClass(WordClassID, true);
-            break;
-
-        // DecimalEscape
-        case '1':
-        case '2':
-        case '3':
-        case '4':
-        case '5':
-        case '6':
-        case '7':
-        case '8':
-        case '9': {
-            // To match Firefox, we parse an invalid backreference in the range [1-7] as an octal escape.
-            // First, try to parse this as backreference.
-            if (!inCharacterClass) {
-                ParseState state = saveState();
-
-                unsigned backReference = consumeNumber();
-                if (backReference <= m_backReferenceLimit) {
-                    delegate.atomBackReference(backReference);
-                    break;
-                }
-
-                restoreState(state);
-            }
-            
-            // Not a backreference, and not octal.
-            if (peek() >= '8') {
-                delegate.atomPatternCharacter('\\');
-                break;
-            }
-
-            // Fall-through to handle this as an octal escape.
-        }
-
-        // Octal escape
-        case '0':
-            delegate.atomPatternCharacter(consumeOctal());
-            break;
-
-        // ControlEscape
-        case 'f':
-            consume();
-            delegate.atomPatternCharacter('\f');
-            break;
-        case 'n':
-            consume();
-            delegate.atomPatternCharacter('\n');
-            break;
-        case 'r':
-            consume();
-            delegate.atomPatternCharacter('\r');
-            break;
-        case 't':
-            consume();
-            delegate.atomPatternCharacter('\t');
-            break;
-        case 'v':
-            consume();
-            delegate.atomPatternCharacter('\v');
-            break;
-
-        // ControlLetter
-        case 'c': {
-            ParseState state = saveState();
-            consume();
-            if (!atEndOfPattern()) {
-                int control = consume();
-
-                // To match Firefox, inside a character class, we also accept numbers and '_' as control characters.
-                if (inCharacterClass ? WTF::isASCIIAlphanumeric(control) || (control == '_') : WTF::isASCIIAlpha(control)) {
-                    delegate.atomPatternCharacter(control & 0x1f);
-                    break;
-                }
-            }
-            restoreState(state);
-            delegate.atomPatternCharacter('\\');
-            break;
-        }
-
-        // HexEscape
-        case 'x': {
-            consume();
-            int x = tryConsumeHex(2);
-            if (x == -1)
-                delegate.atomPatternCharacter('x');
-            else
-                delegate.atomPatternCharacter(x);
-            break;
-        }
-
-        // UnicodeEscape
-        case 'u': {
-            consume();
-            int u = tryConsumeHex(4);
-            if (u == -1)
-                delegate.atomPatternCharacter('u');
-            else
-                delegate.atomPatternCharacter(u);
-            break;
-        }
-
-        // IdentityEscape
-        default:
-            delegate.atomPatternCharacter(consume());
-        }
-        
-        return true;
-    }
-
-    /*
-     * parseAtomEscape(), parseCharacterClassEscape():
-     *
-     * These methods alias to parseEscape().
-     */
-    bool parseAtomEscape()
-    {
-        return parseEscape<false>(m_delegate);
-    }
-    void parseCharacterClassEscape(CharacterClassParserDelegate& delegate)
-    {
-        parseEscape<true>(delegate);
-    }
-
-    /*
-     * parseCharacterClass():
-     *
-     * Helper for parseTokens(); calls dirctly and indirectly (via parseCharacterClassEscape)
-     * to an instance of CharacterClassParserDelegate, to describe the character class to the
-     * delegate.
-     */
-    void parseCharacterClass()
-    {
-        ASSERT(!m_err);
-        ASSERT(peek() == '[');
-        consume();
-
-        CharacterClassParserDelegate characterClassConstructor(m_delegate, m_err);
-
-        characterClassConstructor.begin(tryConsume('^'));
-
-        while (!atEndOfPattern()) {
-            switch (peek()) {
-            case ']':
-                consume();
-                characterClassConstructor.end();
-                return;
-
-            case '\\':
-                parseCharacterClassEscape(characterClassConstructor);
-                break;
-
-            default:
-                characterClassConstructor.atomPatternCharacterUnescaped(consume());
-            }
-
-            if (m_err)
-                return;
-        }
-
-        m_err = CharacterClassUnmatched;
-    }
-
-    /*
-     * parseParenthesesBegin():
-     *
-     * Helper for parseTokens(); checks for parentheses types other than regular capturing subpatterns.
-     */
-    void parseParenthesesBegin()
-    {
-        ASSERT(!m_err);
-        ASSERT(peek() == '(');
-        consume();
-
-        if (tryConsume('?')) {
-            if (atEndOfPattern()) {
-                m_err = ParenthesesTypeInvalid;
-                return;
-            }
-
-            switch (consume()) {
-            case ':':
-                m_delegate.atomParenthesesSubpatternBegin(false);
-                break;
-            
-            case '=':
-                m_delegate.atomParentheticalAssertionBegin();
-                break;
-
-            case '!':
-                m_delegate.atomParentheticalAssertionBegin(true);
-                break;
-            
-            default:
-                m_err = ParenthesesTypeInvalid;
-            }
-        } else
-            m_delegate.atomParenthesesSubpatternBegin();
-
-        ++m_parenthesesNestingDepth;
-    }
-
-    /*
-     * parseParenthesesEnd():
-     *
-     * Helper for parseTokens(); checks for parse errors (due to unmatched parentheses).
-     */
-    void parseParenthesesEnd()
-    {
-        ASSERT(!m_err);
-        ASSERT(peek() == ')');
-        consume();
-
-        if (m_parenthesesNestingDepth > 0)
-            m_delegate.atomParenthesesEnd();
-        else
-            m_err = ParenthesesUnmatched;
-
-        --m_parenthesesNestingDepth;
-    }
-
-    /*
-     * parseQuantifier():
-     *
-     * Helper for parseTokens(); checks for parse errors and non-greedy quantifiers.
-     */
-    void parseQuantifier(bool lastTokenWasAnAtom, unsigned min, unsigned max)
-    {
-        ASSERT(!m_err);
-        ASSERT(min <= max);
-
-        if (lastTokenWasAnAtom)
-            m_delegate.quantifyAtom(min, max, !tryConsume('?'));
-        else
-            m_err = QuantifierWithoutAtom;
-    }
-
-    /*
-     * parseTokens():
-     *
-     * This method loops over the input pattern reporting tokens to the delegate.
-     * The method returns when a parse error is detected, or the end of the pattern
-     * is reached.  One piece of state is tracked around the loop, which is whether
-     * the last token passed to the delegate was an atom (this is necessary to detect
-     * a parse error when a quantifier provided without an atom to quantify).
-     */
-    void parseTokens()
-    {
-        bool lastTokenWasAnAtom = false;
-
-        while (!atEndOfPattern()) {
-            switch (peek()) {
-            case '|':
-                consume();
-                m_delegate.disjunction();
-                lastTokenWasAnAtom = false;
-                break;
-
-            case '(':
-                parseParenthesesBegin();
-                lastTokenWasAnAtom = false;
-                break;
-
-            case ')':
-                parseParenthesesEnd();
-                lastTokenWasAnAtom = true;
-                break;
-
-            case '^':
-                consume();
-                m_delegate.assertionBOL();
-                lastTokenWasAnAtom = false;
-                break;
-
-            case '$':
-                consume();
-                m_delegate.assertionEOL();
-                lastTokenWasAnAtom = false;
-                break;
-
-            case '.':
-                consume();
-                m_delegate.atomBuiltInCharacterClass(NewlineClassID, true);
-                lastTokenWasAnAtom = true;
-                break;
-
-            case '[':
-                parseCharacterClass();
-                lastTokenWasAnAtom = true;
-                break;
-
-            case '\\':
-                lastTokenWasAnAtom = parseAtomEscape();
-                break;
-
-            case '*':
-                consume();
-                parseQuantifier(lastTokenWasAnAtom, 0, UINT_MAX);
-                lastTokenWasAnAtom = false;
-                break;
-
-            case '+':
-                consume();
-                parseQuantifier(lastTokenWasAnAtom, 1, UINT_MAX);
-                lastTokenWasAnAtom = false;
-                break;
-
-            case '?':
-                consume();
-                parseQuantifier(lastTokenWasAnAtom, 0, 1);
-                lastTokenWasAnAtom = false;
-                break;
-
-            case '{': {
-                ParseState state = saveState();
-
-                consume();
-                if (peekIsDigit()) {
-                    unsigned min = consumeNumber();
-                    unsigned max = min;
-                    
-                    if (tryConsume(','))
-                        max = peekIsDigit() ? consumeNumber() : UINT_MAX;
-
-                    if (tryConsume('}')) {
-                        if (min <= max)
-                            parseQuantifier(lastTokenWasAnAtom, min, max);
-                        else
-                            m_err = QuantifierOutOfOrder;
-                        lastTokenWasAnAtom = false;
-                        break;
-                    }
-                }
-
-                restoreState(state);
-            } // if we did not find a complete quantifer, fall through to the default case.
-
-            default:
-                m_delegate.atomPatternCharacter(consume());
-                lastTokenWasAnAtom = true;
-            }
-
-            if (m_err)
-                return;
-        }
-
-        if (m_parenthesesNestingDepth > 0)
-            m_err = MissingParentheses;
-    }
-
-    /*
-     * parse():
-     *
-     * This method calls regexBegin(), calls parseTokens() to parse over the input
-     * patterns, calls regexEnd() or regexError() as appropriate, and converts any
-     * error code to a const char* for a result.
-     */
-    const char* parse()
-    {
-        m_delegate.regexBegin();
-
-        if (m_size > MAX_PATTERN_SIZE)
-            m_err = PatternTooLarge;
-        else
-            parseTokens();
-        ASSERT(atEndOfPattern() || m_err);
-
-        if (m_err)
-            m_delegate.regexError();
-        else
-            m_delegate.regexEnd();
-
-        // The order of this array must match the ErrorCode enum.
-        static const char* errorMessages[NumberOfErrorCodes] = {
-            0, // NoError
-            "regular expression too large",
-            "numbers out of order in {} quantifier",
-            "nothing to repeat",
-            "missing )",
-            "unmatched parentheses",
-            "unrecognized character after (?",
-            "missing terminating ] for character class",
-            "range out of order in character class",
-            "\\ at end of pattern"
-        };
-
-        return errorMessages[m_err];
-    }
-
-
-    // Misc helper functions:
-
-    typedef unsigned ParseState;
-    
-    ParseState saveState()
-    {
-        return m_index;
-    }
-
-    void restoreState(ParseState state)
-    {
-        m_index = state;
-    }
-
-    bool atEndOfPattern()
-    {
-        ASSERT(m_index <= m_size);
-        return m_index == m_size;
-    }
-
-    int peek()
-    {
-        ASSERT(m_index < m_size);
-        return m_data[m_index];
-    }
-
-    bool peekIsDigit()
-    {
-        return !atEndOfPattern() && WTF::isASCIIDigit(peek());
-    }
-
-    unsigned peekDigit()
-    {
-        ASSERT(peekIsDigit());
-        return peek() - '0';
-    }
-
-    int consume()
-    {
-        ASSERT(m_index < m_size);
-        return m_data[m_index++];
-    }
-
-    unsigned consumeDigit()
-    {
-        ASSERT(peekIsDigit());
-        return consume() - '0';
-    }
-
-    unsigned consumeNumber()
-    {
-        unsigned n = consumeDigit();
-        // check for overflow.
-        for (unsigned newValue; peekIsDigit() && ((newValue = n * 10 + peekDigit()) >= n); ) {
-            n = newValue;
-            consume();
-        }
-        return n;
-    }
-
-    unsigned consumeOctal()
-    {
-        ASSERT(WTF::isASCIIOctalDigit(peek()));
-
-        unsigned n = consumeDigit();
-        while (n < 32 && !atEndOfPattern() && WTF::isASCIIOctalDigit(peek()))
-            n = n * 8 + consumeDigit();
-        return n;
-    }
-
-    bool tryConsume(UChar ch)
-    {
-        if (atEndOfPattern() || (m_data[m_index] != ch))
-            return false;
-        ++m_index;
-        return true;
-    }
-
-    int tryConsumeHex(int count)
-    {
-        ParseState state = saveState();
-
-        int n = 0;
-        while (count--) {
-            if (atEndOfPattern() || !WTF::isASCIIHexDigit(peek())) {
-                restoreState(state);
-                return -1;
-            }
-            n = (n << 4) | WTF::toASCIIHexValue(consume());
-        }
-        return n;
-    }
-
-    Delegate& m_delegate;
-    unsigned m_backReferenceLimit;
-    ErrorCode m_err;
-    const UChar* m_data;
-    unsigned m_size;
-    unsigned m_index;
-    unsigned m_parenthesesNestingDepth;
-
-    // Derived by empirical testing of compile time in PCRE and WREC.
-    static const unsigned MAX_PATTERN_SIZE = 1024 * 1024;
-};
-
-/*
- * Yarr::parse():
- *
- * The parse method is passed a pattern to be parsed and a delegate upon which
- * callbacks will be made to record the parsed tokens forming the regex.
- * Yarr::parse() returns null on success, or a const C string providing an error
- * message where a parse error occurs.
- *
- * The Delegate must implement the following interface:
- *
- *    void assertionBOL();
- *    void assertionEOL();
- *    void assertionWordBoundary(bool invert);
- *
- *    void atomPatternCharacter(UChar ch);
- *    void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert);
- *    void atomCharacterClassBegin(bool invert)
- *    void atomCharacterClassAtom(UChar ch)
- *    void atomCharacterClassRange(UChar begin, UChar end)
- *    void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
- *    void atomCharacterClassEnd()
- *    void atomParenthesesSubpatternBegin(bool capture = true);
- *    void atomParentheticalAssertionBegin(bool invert = false);
- *    void atomParenthesesEnd();
- *    void atomBackReference(unsigned subpatternId);
- *
- *    void quantifyAtom(unsigned min, unsigned max, bool greedy);
- *
- *    void disjunction();
- *
- *    void regexBegin();
- *    void regexEnd();
- *    void regexError();
- *
- * Before any call recording tokens are made, regexBegin() will be called on the
- * delegate once.  Once parsing is complete either regexEnd() or regexError() will
- * be called, as appropriate.
- *
- * The regular expression is described by a sequence of assertion*() and atom*()
- * callbacks to the delegate, describing the terms in the regular expression.
- * Following an atom a quantifyAtom() call may occur to indicate that the previous
- * atom should be quantified.  In the case of atoms described across multiple
- * calls (parentheses and character classes) the call to quantifyAtom() will come
- * after the call to the atom*End() method, never after atom*Begin().
- *
- * Character classes may either be described by a single call to
- * atomBuiltInCharacterClass(), or by a sequence of atomCharacterClass*() calls.
- * In the latter case, ...Begin() will be called, followed by a sequence of
- * calls to ...Atom(), ...Range(), and ...BuiltIn(), followed by a call to ...End().
- *
- * Sequences of atoms and assertions are broken into alternatives via calls to
- * disjunction().  Assertions, atoms, and disjunctions emitted between calls to
- * atomParenthesesBegin() and atomParenthesesEnd() form the body of a subpattern.
- * atomParenthesesBegin() is passed a subpatternId.  In the case of a regular
- * capturing subpattern, this will be the subpatternId associated with these
- * parentheses, and will also by definition be the lowest subpatternId of these
- * parentheses and of any nested paretheses.  The atomParenthesesEnd() method
- * is passed the subpatternId of the last capturing subexpression nested within
- * these paretheses.  In the case of a capturing subpattern with no nested
- * capturing subpatterns, the same subpatternId will be passed to the begin and
- * end functions.  In the case of non-capturing subpatterns the subpatternId
- * passed to the begin method is also the first possible subpatternId that might
- * be nested within these paretheses.  If a set of non-capturing parentheses does
- * not contain any capturing subpatterns, then the subpatternId passed to begin
- * will be greater than the subpatternId passed to end.
- */
-
-template<class Delegate>
-const char* parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = UINT_MAX)
-{
-    return Parser<Delegate>(delegate, pattern, backReferenceLimit).parse();
-}
-
-} } // namespace JSC::Yarr
-
-#endif
-
-#endif // RegexParser_h
diff --git a/yarr/RegexPattern.h b/yarr/RegexPattern.h
deleted file mode 100644 (file)
index 3271cc1..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * Copyright (C) 2009 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 RegexPattern_h
-#define RegexPattern_h
-
-
-#if ENABLE(YARR)
-
-#include <wtf/Vector.h>
-#include <wtf/unicode/Unicode.h>
-
-
-namespace JSC { namespace Yarr {
-
-#define RegexStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers.
-#define RegexStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers.
-#define RegexStackSpaceForBackTrackInfoBackReference 2
-#define RegexStackSpaceForBackTrackInfoAlternative 1 // One per alternative.
-#define RegexStackSpaceForBackTrackInfoParentheticalAssertion 1
-#define RegexStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers.
-#define RegexStackSpaceForBackTrackInfoParentheses 4
-
-struct PatternDisjunction;
-
-struct CharacterRange {
-    UChar begin;
-    UChar end;
-
-    CharacterRange(UChar begin, UChar end)
-        : begin(begin)
-        , end(end)
-    {
-    }
-};
-
-struct CharacterClassTable : RefCounted<CharacterClassTable> {
-    const char* m_table;
-    bool m_inverted;
-    static PassRefPtr<CharacterClassTable> create(const char* table, bool inverted)
-    {
-        return adoptRef(new CharacterClassTable(table, inverted));
-    }
-
-private:
-    CharacterClassTable(const char* table, bool inverted)
-        : m_table(table)
-        , m_inverted(inverted)
-    {
-    }
-};
-
-struct CharacterClass : FastAllocBase {
-    // All CharacterClass instances have to have the full set of matches and ranges,
-    // they may have an optional table for faster lookups (which must match the
-    // specified matches and ranges)
-    CharacterClass(PassRefPtr<CharacterClassTable> table)
-        : m_table(table)
-    {
-    }
-    Vector<UChar> m_matches;
-    Vector<CharacterRange> m_ranges;
-    Vector<UChar> m_matchesUnicode;
-    Vector<CharacterRange> m_rangesUnicode;
-    RefPtr<CharacterClassTable> m_table;
-};
-
-enum QuantifierType {
-    QuantifierFixedCount,
-    QuantifierGreedy,
-    QuantifierNonGreedy,
-};
-
-struct PatternTerm {
-    enum Type {
-        TypeAssertionBOL,
-        TypeAssertionEOL,
-        TypeAssertionWordBoundary,
-        TypePatternCharacter,
-        TypeCharacterClass,
-        TypeBackReference,
-        TypeForwardReference,
-        TypeParenthesesSubpattern,
-        TypeParentheticalAssertion,
-    } type;
-    bool invertOrCapture;
-    union {
-        UChar patternCharacter;
-        CharacterClass* characterClass;
-        unsigned subpatternId;
-        struct {
-            PatternDisjunction* disjunction;
-            unsigned subpatternId;
-            unsigned lastSubpatternId;
-            bool isCopy;
-        } parentheses;
-    };
-    QuantifierType quantityType;
-    unsigned quantityCount;
-    int inputPosition;
-    unsigned frameLocation;
-
-    PatternTerm(UChar ch)
-        : type(PatternTerm::TypePatternCharacter)
-    {
-        patternCharacter = ch;
-        quantityType = QuantifierFixedCount;
-        quantityCount = 1;
-    }
-
-    PatternTerm(CharacterClass* charClass, bool invert)
-        : type(PatternTerm::TypeCharacterClass)
-        , invertOrCapture(invert)
-    {
-        characterClass = charClass;
-        quantityType = QuantifierFixedCount;
-        quantityCount = 1;
-    }
-
-    PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool invertOrCapture)
-        : type(type)
-        , invertOrCapture(invertOrCapture)
-    {
-        parentheses.disjunction = disjunction;
-        parentheses.subpatternId = subpatternId;
-        parentheses.isCopy = false;
-        quantityType = QuantifierFixedCount;
-        quantityCount = 1;
-    }
-    
-    PatternTerm(Type type, bool invert = false)
-        : type(type)
-        , invertOrCapture(invert)
-    {
-        quantityType = QuantifierFixedCount;
-        quantityCount = 1;
-    }
-
-    PatternTerm(unsigned spatternId)
-        : type(TypeBackReference)
-        , invertOrCapture(false)
-    {
-        subpatternId = spatternId;
-        quantityType = QuantifierFixedCount;
-        quantityCount = 1;
-    }
-
-    static PatternTerm ForwardReference()
-    {
-        return PatternTerm(TypeForwardReference);
-    }
-
-    static PatternTerm BOL()
-    {
-        return PatternTerm(TypeAssertionBOL);
-    }
-
-    static PatternTerm EOL()
-    {
-        return PatternTerm(TypeAssertionEOL);
-    }
-
-    static PatternTerm WordBoundary(bool invert)
-    {
-        return PatternTerm(TypeAssertionWordBoundary, invert);
-    }
-    
-    bool invert()
-    {
-        return invertOrCapture;
-    }
-
-    bool capture()
-    {
-        return invertOrCapture;
-    }
-    
-    void quantify(unsigned count, QuantifierType type)
-    {
-        quantityCount = count;
-        quantityType = type;
-    }
-};
-
-struct PatternAlternative : FastAllocBase {
-    PatternAlternative(PatternDisjunction* disjunction)
-        : m_parent(disjunction)
-    {
-    }
-
-    PatternTerm& lastTerm()
-    {
-        ASSERT(m_terms.size());
-        return m_terms[m_terms.size() - 1];
-    }
-    
-    void removeLastTerm()
-    {
-        ASSERT(m_terms.size());
-        m_terms.shrink(m_terms.size() - 1);
-    }
-
-    Vector<PatternTerm> m_terms;
-    PatternDisjunction* m_parent;
-    unsigned m_minimumSize;
-    bool m_hasFixedSize;
-};
-
-struct PatternDisjunction : FastAllocBase {
-    PatternDisjunction(PatternAlternative* parent = 0)
-        : m_parent(parent)
-    {
-    }
-    
-    ~PatternDisjunction()
-    {
-        deleteAllValues(m_alternatives);
-    }
-
-    PatternAlternative* addNewAlternative()
-    {
-        PatternAlternative* alternative = new PatternAlternative(this);
-        m_alternatives.append(alternative);
-        return alternative;
-    }
-
-    Vector<PatternAlternative*> m_alternatives;
-    PatternAlternative* m_parent;
-    unsigned m_minimumSize;
-    unsigned m_callFrameSize;
-    bool m_hasFixedSize;
-};
-
-// You probably don't want to be calling these functions directly
-// (please to be calling newlineCharacterClass() et al on your
-// friendly neighborhood RegexPattern instance to get nicely
-// cached copies).
-CharacterClass* newlineCreate();
-CharacterClass* digitsCreate();
-CharacterClass* spacesCreate();
-CharacterClass* wordcharCreate();
-CharacterClass* nondigitsCreate();
-CharacterClass* nonspacesCreate();
-CharacterClass* nonwordcharCreate();
-
-struct RegexPattern {
-    RegexPattern(bool ignoreCase, bool multiline)
-        : m_ignoreCase(ignoreCase)
-        , m_multiline(multiline)
-        , m_numSubpatterns(0)
-        , m_maxBackReference(0)
-        , m_shouldFallBack(false)
-        , newlineCached(0)
-        , digitsCached(0)
-        , spacesCached(0)
-        , wordcharCached(0)
-        , nondigitsCached(0)
-        , nonspacesCached(0)
-        , nonwordcharCached(0)
-    {
-    }
-
-    ~RegexPattern()
-    {
-        deleteAllValues(m_disjunctions);
-        deleteAllValues(m_userCharacterClasses);
-    }
-
-    void reset()
-    {
-        m_numSubpatterns = 0;
-        m_maxBackReference = 0;
-
-        m_shouldFallBack = false;
-
-        newlineCached = 0;
-        digitsCached = 0;
-        spacesCached = 0;
-        wordcharCached = 0;
-        nondigitsCached = 0;
-        nonspacesCached = 0;
-        nonwordcharCached = 0;
-
-        deleteAllValues(m_disjunctions);
-        m_disjunctions.clear();
-        deleteAllValues(m_userCharacterClasses);
-        m_userCharacterClasses.clear();
-    }
-
-    bool containsIllegalBackReference()
-    {
-        return m_maxBackReference > m_numSubpatterns;
-    }
-
-    CharacterClass* newlineCharacterClass()
-    {
-        if (!newlineCached)
-            m_userCharacterClasses.append(newlineCached = newlineCreate());
-        return newlineCached;
-    }
-    CharacterClass* digitsCharacterClass()
-    {
-        if (!digitsCached)
-            m_userCharacterClasses.append(digitsCached = digitsCreate());
-        return digitsCached;
-    }
-    CharacterClass* spacesCharacterClass()
-    {
-        if (!spacesCached)
-            m_userCharacterClasses.append(spacesCached = spacesCreate());
-        return spacesCached;
-    }
-    CharacterClass* wordcharCharacterClass()
-    {
-        if (!wordcharCached)
-            m_userCharacterClasses.append(wordcharCached = wordcharCreate());
-        return wordcharCached;
-    }
-    CharacterClass* nondigitsCharacterClass()
-    {
-        if (!nondigitsCached)
-            m_userCharacterClasses.append(nondigitsCached = nondigitsCreate());
-        return nondigitsCached;
-    }
-    CharacterClass* nonspacesCharacterClass()
-    {
-        if (!nonspacesCached)
-            m_userCharacterClasses.append(nonspacesCached = nonspacesCreate());
-        return nonspacesCached;
-    }
-    CharacterClass* nonwordcharCharacterClass()
-    {
-        if (!nonwordcharCached)
-            m_userCharacterClasses.append(nonwordcharCached = nonwordcharCreate());
-        return nonwordcharCached;
-    }
-
-    bool m_ignoreCase;
-    bool m_multiline;
-    unsigned m_numSubpatterns;
-    unsigned m_maxBackReference;
-    bool m_shouldFallBack;
-    PatternDisjunction* m_body;
-    Vector<PatternDisjunction*, 4> m_disjunctions;
-    Vector<CharacterClass*> m_userCharacterClasses;
-
-private:
-    CharacterClass* newlineCached;
-    CharacterClass* digitsCached;
-    CharacterClass* spacesCached;
-    CharacterClass* wordcharCached;
-    CharacterClass* nondigitsCached;
-    CharacterClass* nonspacesCached;
-    CharacterClass* nonwordcharCached;
-};
-
-} } // namespace JSC::Yarr
-
-#endif
-
-#endif // RegexPattern_h
diff --git a/yarr/Yarr.h b/yarr/Yarr.h
new file mode 100644 (file)
index 0000000..de64fdd
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 Yarr_h
+#define Yarr_h
+
+#include "YarrInterpreter.h"
+#include "YarrPattern.h"
+
+namespace JSC { namespace Yarr {
+
+#define YarrStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers.
+#define YarrStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers.
+#define YarrStackSpaceForBackTrackInfoBackReference 2
+#define YarrStackSpaceForBackTrackInfoAlternative 1 // One per alternative.
+#define YarrStackSpaceForBackTrackInfoParentheticalAssertion 1
+#define YarrStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers.
+#define YarrStackSpaceForBackTrackInfoParenthesesTerminal 1
+#define YarrStackSpaceForBackTrackInfoParentheses 2
+
+static const unsigned quantifyInfinite = UINT_MAX;
+
+// The below limit restricts the number of "recursive" match calls in order to
+// avoid spending exponential time on complex regular expressions.
+static const unsigned matchLimit = 1000000;
+
+enum JSRegExpResult {
+    JSRegExpMatch = 1,
+    JSRegExpNoMatch = 0,
+    JSRegExpErrorNoMatch = -1,
+    JSRegExpErrorHitLimit = -2,
+    JSRegExpErrorNoMemory = -3,
+    JSRegExpErrorInternal = -4
+};
+
+PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*);
+int interpret(BytecodePattern*, const UChar* input, unsigned start, unsigned length, int* output);
+
+} } // namespace JSC::Yarr
+
+#endif // Yarr_h
+
diff --git a/yarr/YarrInterpreter.cpp b/yarr/YarrInterpreter.cpp
new file mode 100644 (file)
index 0000000..903c692
--- /dev/null
@@ -0,0 +1,1927 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "YarrInterpreter.h"
+
+#include "Yarr.h"
+#include <wtf/BumpPointerAllocator.h>
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+class Interpreter {
+public:
+    struct ParenthesesDisjunctionContext;
+
+    struct BackTrackInfoPatternCharacter {
+        uintptr_t matchAmount;
+    };
+    struct BackTrackInfoCharacterClass {
+        uintptr_t matchAmount;
+    };
+    struct BackTrackInfoBackReference {
+        uintptr_t begin; // Not really needed for greedy quantifiers.
+        uintptr_t matchAmount; // Not really needed for fixed quantifiers.
+    };
+    struct BackTrackInfoAlternative {
+        uintptr_t offset;
+    };
+    struct BackTrackInfoParentheticalAssertion {
+        uintptr_t begin;
+    };
+    struct BackTrackInfoParenthesesOnce {
+        uintptr_t begin;
+    };
+    struct BackTrackInfoParenthesesTerminal {
+        uintptr_t begin;
+    };
+    struct BackTrackInfoParentheses {
+        uintptr_t matchAmount;
+        ParenthesesDisjunctionContext* lastContext;
+    };
+
+    static inline void appendParenthesesDisjunctionContext(BackTrackInfoParentheses* backTrack, ParenthesesDisjunctionContext* context)
+    {
+        context->next = backTrack->lastContext;
+        backTrack->lastContext = context;
+        ++backTrack->matchAmount;
+    }
+
+    static inline void popParenthesesDisjunctionContext(BackTrackInfoParentheses* backTrack)
+    {
+        ASSERT(backTrack->matchAmount);
+        ASSERT(backTrack->lastContext);
+        backTrack->lastContext = backTrack->lastContext->next;
+        --backTrack->matchAmount;
+    }
+
+    struct DisjunctionContext
+    {
+        DisjunctionContext()
+            : term(0)
+        {
+        }
+
+        void* operator new(size_t, void* where)
+        {
+            return where;
+        }
+
+        int term;
+        unsigned matchBegin;
+        unsigned matchEnd;
+        uintptr_t frame[1];
+    };
+
+    DisjunctionContext* allocDisjunctionContext(ByteDisjunction* disjunction)
+    {
+        size_t size = sizeof(DisjunctionContext) - sizeof(uintptr_t) + disjunction->m_frameSize * sizeof(uintptr_t);
+        allocatorPool = allocatorPool->ensureCapacity(size);
+        if (!allocatorPool)
+            CRASH();
+        return new(allocatorPool->alloc(size)) DisjunctionContext();
+    }
+
+    void freeDisjunctionContext(DisjunctionContext* context)
+    {
+        allocatorPool = allocatorPool->dealloc(context);
+    }
+
+    struct ParenthesesDisjunctionContext
+    {
+        ParenthesesDisjunctionContext(int* output, ByteTerm& term)
+            : next(0)
+        {
+            unsigned firstSubpatternId = term.atom.subpatternId;
+            unsigned numNestedSubpatterns = term.atom.parenthesesDisjunction->m_numSubpatterns;
+
+            for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i) {
+                subpatternBackup[i] = output[(firstSubpatternId << 1) + i];
+                output[(firstSubpatternId << 1) + i] = -1;
+            }
+
+            new(getDisjunctionContext(term)) DisjunctionContext();
+        }
+
+        void* operator new(size_t, void* where)
+        {
+            return where;
+        }
+
+        void restoreOutput(int* output, unsigned firstSubpatternId, unsigned numNestedSubpatterns)
+        {
+            for (unsigned i = 0; i < (numNestedSubpatterns << 1); ++i)
+                output[(firstSubpatternId << 1) + i] = subpatternBackup[i];
+        }
+
+        DisjunctionContext* getDisjunctionContext(ByteTerm& term)
+        {
+            return reinterpret_cast<DisjunctionContext*>(&(subpatternBackup[term.atom.parenthesesDisjunction->m_numSubpatterns << 1]));
+        }
+
+        ParenthesesDisjunctionContext* next;
+        int subpatternBackup[1];
+    };
+
+    ParenthesesDisjunctionContext* allocParenthesesDisjunctionContext(ByteDisjunction* disjunction, int* output, ByteTerm& term)
+    {
+        size_t size = sizeof(ParenthesesDisjunctionContext) - sizeof(int) + (term.atom.parenthesesDisjunction->m_numSubpatterns << 1) * sizeof(int) + sizeof(DisjunctionContext) - sizeof(uintptr_t) + disjunction->m_frameSize * sizeof(uintptr_t);
+        allocatorPool = allocatorPool->ensureCapacity(size);
+        if (!allocatorPool)
+            CRASH();
+        return new(allocatorPool->alloc(size)) ParenthesesDisjunctionContext(output, term);
+    }
+
+    void freeParenthesesDisjunctionContext(ParenthesesDisjunctionContext* context)
+    {
+        allocatorPool = allocatorPool->dealloc(context);
+    }
+
+    class InputStream {
+    public:
+        InputStream(const UChar* input, unsigned start, unsigned length)
+            : input(input)
+            , pos(start)
+            , length(length)
+        {
+        }
+
+        void next()
+        {
+            ++pos;
+        }
+
+        void rewind(unsigned amount)
+        {
+            ASSERT(pos >= amount);
+            pos -= amount;
+        }
+
+        int read()
+        {
+            ASSERT(pos < length);
+            if (pos < length)
+                return input[pos];
+            return -1;
+        }
+
+        int readPair()
+        {
+            ASSERT(pos + 1 < length);
+            return input[pos] | input[pos + 1] << 16;
+        }
+
+        int readChecked(int position)
+        {
+            ASSERT(position < 0);
+            ASSERT(static_cast<unsigned>(-position) <= pos);
+            unsigned p = pos + position;
+            ASSERT(p < length);
+            return input[p];
+        }
+
+        int reread(unsigned from)
+        {
+            ASSERT(from < length);
+            return input[from];
+        }
+
+        int prev()
+        {
+            ASSERT(!(pos > length));
+            if (pos && length)
+                return input[pos - 1];
+            return -1;
+        }
+
+        unsigned getPos()
+        {
+            return pos;
+        }
+
+        void setPos(unsigned p)
+        {
+            pos = p;
+        }
+
+        bool atStart()
+        {
+            return pos == 0;
+        }
+
+        bool atEnd()
+        {
+            return pos == length;
+        }
+
+        unsigned end()
+        {
+            return length;
+        }
+
+        bool checkInput(int count)
+        {
+            if ((pos + count) <= length) {
+                pos += count;
+                return true;
+            }
+            return false;
+        }
+
+        void uncheckInput(int count)
+        {
+            pos -= count;
+        }
+
+        bool atStart(int position)
+        {
+            return (pos + position) == 0;
+        }
+
+        bool atEnd(int position)
+        {
+            return (pos + position) == length;
+        }
+
+        bool isNotAvailableInput(int position)
+        {
+            return (pos + position) > length;
+        }
+
+    private:
+        const UChar* input;
+        unsigned pos;
+        unsigned length;
+    };
+
+    bool testCharacterClass(CharacterClass* characterClass, int ch)
+    {
+        if (ch & 0xFF80) {
+            for (unsigned i = 0; i < characterClass->m_matchesUnicode.size(); ++i)
+                if (ch == characterClass->m_matchesUnicode[i])
+                    return true;
+            for (unsigned i = 0; i < characterClass->m_rangesUnicode.size(); ++i)
+                if ((ch >= characterClass->m_rangesUnicode[i].begin) && (ch <= characterClass->m_rangesUnicode[i].end))
+                    return true;
+        } else {
+            for (unsigned i = 0; i < characterClass->m_matches.size(); ++i)
+                if (ch == characterClass->m_matches[i])
+                    return true;
+            for (unsigned i = 0; i < characterClass->m_ranges.size(); ++i)
+                if ((ch >= characterClass->m_ranges[i].begin) && (ch <= characterClass->m_ranges[i].end))
+                    return true;
+        }
+
+        return false;
+    }
+
+    bool checkCharacter(int testChar, int inputPosition)
+    {
+        return testChar == input.readChecked(inputPosition);
+    }
+
+    bool checkCasedCharacter(int loChar, int hiChar, int inputPosition)
+    {
+        int ch = input.readChecked(inputPosition);
+        return (loChar == ch) || (hiChar == ch);
+    }
+
+    bool checkCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition)
+    {
+        bool match = testCharacterClass(characterClass, input.readChecked(inputPosition));
+        return invert ? !match : match;
+    }
+
+    bool tryConsumeBackReference(int matchBegin, int matchEnd, int inputOffset)
+    {
+        int matchSize = matchEnd - matchBegin;
+
+        if (!input.checkInput(matchSize))
+            return false;
+
+        if (pattern->m_ignoreCase) {
+            for (int i = 0; i < matchSize; ++i) {
+                int ch = input.reread(matchBegin + i);
+
+                int lo = Unicode::toLower(ch);
+                int hi = Unicode::toUpper(ch);
+
+                if ((lo != hi) ? (!checkCasedCharacter(lo, hi, inputOffset - matchSize + i)) : (!checkCharacter(ch, inputOffset - matchSize + i))) {
+                    input.uncheckInput(matchSize);
+                    return false;
+                }
+            }
+        } else {
+            for (int i = 0; i < matchSize; ++i) {
+                if (!checkCharacter(input.reread(matchBegin + i), inputOffset - matchSize + i)) {
+                    input.uncheckInput(matchSize);
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool matchAssertionBOL(ByteTerm& term)
+    {
+        return (input.atStart(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition - 1)));
+    }
+
+    bool matchAssertionEOL(ByteTerm& term)
+    {
+        if (term.inputPosition)
+            return (input.atEnd(term.inputPosition)) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.readChecked(term.inputPosition)));
+
+        return (input.atEnd()) || (pattern->m_multiline && testCharacterClass(pattern->newlineCharacterClass, input.read()));
+    }
+
+    bool matchAssertionWordBoundary(ByteTerm& term)
+    {
+        bool prevIsWordchar = !input.atStart(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition - 1));
+        bool readIsWordchar;
+        if (term.inputPosition)
+            readIsWordchar = !input.atEnd(term.inputPosition) && testCharacterClass(pattern->wordcharCharacterClass, input.readChecked(term.inputPosition));
+        else
+            readIsWordchar = !input.atEnd() && testCharacterClass(pattern->wordcharCharacterClass, input.read());
+
+        bool wordBoundary = prevIsWordchar != readIsWordchar;
+        return term.invert() ? !wordBoundary : wordBoundary;
+    }
+
+    bool backtrackPatternCharacter(ByteTerm& term, DisjunctionContext* context)
+    {
+        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount:
+            break;
+
+        case QuantifierGreedy:
+            if (backTrack->matchAmount) {
+                --backTrack->matchAmount;
+                input.uncheckInput(1);
+                return true;
+            }
+            break;
+
+        case QuantifierNonGreedy:
+            if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+                ++backTrack->matchAmount;
+                if (checkCharacter(term.atom.patternCharacter, term.inputPosition - 1))
+                    return true;
+            }
+            input.uncheckInput(backTrack->matchAmount);
+            break;
+        }
+
+        return false;
+    }
+
+    bool backtrackPatternCasedCharacter(ByteTerm& term, DisjunctionContext* context)
+    {
+        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount:
+            break;
+
+        case QuantifierGreedy:
+            if (backTrack->matchAmount) {
+                --backTrack->matchAmount;
+                input.uncheckInput(1);
+                return true;
+            }
+            break;
+
+        case QuantifierNonGreedy:
+            if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+                ++backTrack->matchAmount;
+                if (checkCasedCharacter(term.atom.casedCharacter.lo, term.atom.casedCharacter.hi, term.inputPosition - 1))
+                    return true;
+            }
+            input.uncheckInput(backTrack->matchAmount);
+            break;
+        }
+
+        return false;
+    }
+
+    bool matchCharacterClass(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeCharacterClass);
+        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount: {
+            for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
+                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition + matchAmount))
+                    return false;
+            }
+            return true;
+        }
+
+        case QuantifierGreedy: {
+            unsigned matchAmount = 0;
+            while ((matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+                if (!checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1)) {
+                    input.uncheckInput(1);
+                    break;
+                }
+                ++matchAmount;
+            }
+            backTrack->matchAmount = matchAmount;
+
+            return true;
+        }
+
+        case QuantifierNonGreedy:
+            backTrack->matchAmount = 0;
+            return true;
+        }
+
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    bool backtrackCharacterClass(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeCharacterClass);
+        BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + term.frameLocation);
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount:
+            break;
+
+        case QuantifierGreedy:
+            if (backTrack->matchAmount) {
+                --backTrack->matchAmount;
+                input.uncheckInput(1);
+                return true;
+            }
+            break;
+
+        case QuantifierNonGreedy:
+            if ((backTrack->matchAmount < term.atom.quantityCount) && input.checkInput(1)) {
+                ++backTrack->matchAmount;
+                if (checkCharacterClass(term.atom.characterClass, term.invert(), term.inputPosition - 1))
+                    return true;
+            }
+            input.uncheckInput(backTrack->matchAmount);
+            break;
+        }
+
+        return false;
+    }
+
+    bool matchBackReference(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeBackReference);
+        BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
+
+        int matchBegin = output[(term.atom.subpatternId << 1)];
+        int matchEnd = output[(term.atom.subpatternId << 1) + 1];
+
+        // If the end position of the referenced match hasn't set yet then the backreference in the same parentheses where it references to that.
+        // In this case the result of match is empty string like when it references to a parentheses with zero-width match.
+        // Eg.: /(a\1)/
+        if (matchEnd == -1)
+            return true;
+
+        ASSERT((matchBegin == -1) || (matchBegin <= matchEnd));
+
+        if (matchBegin == matchEnd)
+            return true;
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount: {
+            backTrack->begin = input.getPos();
+            for (unsigned matchAmount = 0; matchAmount < term.atom.quantityCount; ++matchAmount) {
+                if (!tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {
+                    input.setPos(backTrack->begin);
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        case QuantifierGreedy: {
+            unsigned matchAmount = 0;
+            while ((matchAmount < term.atom.quantityCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition))
+                ++matchAmount;
+            backTrack->matchAmount = matchAmount;
+            return true;
+        }
+
+        case QuantifierNonGreedy:
+            backTrack->begin = input.getPos();
+            backTrack->matchAmount = 0;
+            return true;
+        }
+
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    bool backtrackBackReference(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeBackReference);
+        BackTrackInfoBackReference* backTrack = reinterpret_cast<BackTrackInfoBackReference*>(context->frame + term.frameLocation);
+
+        int matchBegin = output[(term.atom.subpatternId << 1)];
+        int matchEnd = output[(term.atom.subpatternId << 1) + 1];
+        ASSERT((matchBegin == -1) || (matchBegin <= matchEnd));
+
+        if (matchBegin == matchEnd)
+            return false;
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount:
+            // for quantityCount == 1, could rewind.
+            input.setPos(backTrack->begin);
+            break;
+
+        case QuantifierGreedy:
+            if (backTrack->matchAmount) {
+                --backTrack->matchAmount;
+                input.rewind(matchEnd - matchBegin);
+                return true;
+            }
+            break;
+
+        case QuantifierNonGreedy:
+            if ((backTrack->matchAmount < term.atom.quantityCount) && tryConsumeBackReference(matchBegin, matchEnd, term.inputPosition)) {
+                ++backTrack->matchAmount;
+                return true;
+            }
+            input.setPos(backTrack->begin);
+            break;
+        }
+
+        return false;
+    }
+
+    void recordParenthesesMatch(ByteTerm& term, ParenthesesDisjunctionContext* context)
+    {
+        if (term.capture()) {
+            unsigned subpatternId = term.atom.subpatternId;
+            output[(subpatternId << 1)] = context->getDisjunctionContext(term)->matchBegin + term.inputPosition;
+            output[(subpatternId << 1) + 1] = context->getDisjunctionContext(term)->matchEnd + term.inputPosition;
+        }
+    }
+    void resetMatches(ByteTerm& term, ParenthesesDisjunctionContext* context)
+    {
+        unsigned firstSubpatternId = term.atom.subpatternId;
+        unsigned count = term.atom.parenthesesDisjunction->m_numSubpatterns;
+        context->restoreOutput(output, firstSubpatternId, count);
+    }
+    JSRegExpResult parenthesesDoBacktrack(ByteTerm& term, BackTrackInfoParentheses* backTrack)
+    {
+        while (backTrack->matchAmount) {
+            ParenthesesDisjunctionContext* context = backTrack->lastContext;
+
+            JSRegExpResult result = matchDisjunction(term.atom.parenthesesDisjunction, context->getDisjunctionContext(term), true);
+            if (result == JSRegExpMatch)
+                return JSRegExpMatch;
+
+            resetMatches(term, context);
+            popParenthesesDisjunctionContext(backTrack);
+            freeParenthesesDisjunctionContext(context);
+
+            if (result != JSRegExpNoMatch)
+                return result;
+        }
+
+        return JSRegExpNoMatch;
+    }
+
+    bool matchParenthesesOnceBegin(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+        ASSERT(term.atom.quantityCount == 1);
+
+        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+
+        switch (term.atom.quantityType) {
+        case QuantifierGreedy: {
+            // set this speculatively; if we get to the parens end this will be true.
+            backTrack->begin = input.getPos();
+            break;
+        }
+        case QuantifierNonGreedy: {
+            backTrack->begin = notFound;
+            context->term += term.atom.parenthesesWidth;
+            return true;
+        }
+        case QuantifierFixedCount:
+            break;
+        }
+
+        if (term.capture()) {
+            unsigned subpatternId = term.atom.subpatternId;
+            output[(subpatternId << 1)] = input.getPos() + term.inputPosition;
+        }
+
+        return true;
+    }
+
+    bool matchParenthesesOnceEnd(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd);
+        ASSERT(term.atom.quantityCount == 1);
+
+        if (term.capture()) {
+            unsigned subpatternId = term.atom.subpatternId;
+            output[(subpatternId << 1) + 1] = input.getPos() + term.inputPosition;
+        }
+
+        if (term.atom.quantityType == QuantifierFixedCount)
+            return true;
+
+        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+        return backTrack->begin != input.getPos();
+    }
+
+    bool backtrackParenthesesOnceBegin(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+        ASSERT(term.atom.quantityCount == 1);
+
+        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+
+        if (term.capture()) {
+            unsigned subpatternId = term.atom.subpatternId;
+            output[(subpatternId << 1)] = -1;
+            output[(subpatternId << 1) + 1] = -1;
+        }
+
+        switch (term.atom.quantityType) {
+        case QuantifierGreedy:
+            // if we backtrack to this point, there is another chance - try matching nothing.
+            ASSERT(backTrack->begin != notFound);
+            backTrack->begin = notFound;
+            context->term += term.atom.parenthesesWidth;
+            return true;
+        case QuantifierNonGreedy:
+            ASSERT(backTrack->begin != notFound);
+        case QuantifierFixedCount:
+            break;
+        }
+
+        return false;
+    }
+
+    bool backtrackParenthesesOnceEnd(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternOnceEnd);
+        ASSERT(term.atom.quantityCount == 1);
+
+        BackTrackInfoParenthesesOnce* backTrack = reinterpret_cast<BackTrackInfoParenthesesOnce*>(context->frame + term.frameLocation);
+
+        switch (term.atom.quantityType) {
+        case QuantifierGreedy:
+            if (backTrack->begin == notFound) {
+                context->term -= term.atom.parenthesesWidth;
+                return false;
+            }
+        case QuantifierNonGreedy:
+            if (backTrack->begin == notFound) {
+                backTrack->begin = input.getPos();
+                if (term.capture()) {
+                    // Technically this access to inputPosition should be accessing the begin term's
+                    // inputPosition, but for repeats other than fixed these values should be
+                    // the same anyway! (We don't pre-check for greedy or non-greedy matches.)
+                    ASSERT((&term - term.atom.parenthesesWidth)->type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+                    ASSERT((&term - term.atom.parenthesesWidth)->inputPosition == term.inputPosition);
+                    unsigned subpatternId = term.atom.subpatternId;
+                    output[subpatternId << 1] = input.getPos() + term.inputPosition;
+                }
+                context->term -= term.atom.parenthesesWidth;
+                return true;
+            }
+        case QuantifierFixedCount:
+            break;
+        }
+
+        return false;
+    }
+
+    bool matchParenthesesTerminalBegin(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternTerminalBegin);
+        ASSERT(term.atom.quantityType == QuantifierGreedy);
+        ASSERT(term.atom.quantityCount == quantifyInfinite);
+        ASSERT(!term.capture());
+
+        BackTrackInfoParenthesesTerminal* backTrack = reinterpret_cast<BackTrackInfoParenthesesTerminal*>(context->frame + term.frameLocation);
+        backTrack->begin = input.getPos();
+        return true;
+    }
+
+    bool matchParenthesesTerminalEnd(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternTerminalEnd);
+
+        BackTrackInfoParenthesesTerminal* backTrack = reinterpret_cast<BackTrackInfoParenthesesTerminal*>(context->frame + term.frameLocation);
+        // Empty match is a failed match.
+        if (backTrack->begin == input.getPos())
+            return false;
+
+        // Successful match! Okay, what's next? - loop around and try to match moar!
+        context->term -= (term.atom.parenthesesWidth + 1);
+        return true;
+    }
+
+    bool backtrackParenthesesTerminalBegin(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpatternTerminalBegin);
+        ASSERT(term.atom.quantityType == QuantifierGreedy);
+        ASSERT(term.atom.quantityCount == quantifyInfinite);
+        ASSERT(!term.capture());
+
+        // If we backtrack to this point, we have failed to match this iteration of the parens.
+        // Since this is greedy / zero minimum a failed is also accepted as a match!
+        context->term += term.atom.parenthesesWidth;
+        return true;
+    }
+
+    bool backtrackParenthesesTerminalEnd(ByteTerm&, DisjunctionContext*)
+    {
+        // 'Terminal' parentheses are at the end of the regex, and as such a match past end
+        // should always be returned as a successful match - we should never backtrack to here.
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
+    bool matchParentheticalAssertionBegin(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin);
+        ASSERT(term.atom.quantityCount == 1);
+
+        BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
+
+        backTrack->begin = input.getPos();
+        return true;
+    }
+
+    bool matchParentheticalAssertionEnd(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd);
+        ASSERT(term.atom.quantityCount == 1);
+
+        BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
+
+        input.setPos(backTrack->begin);
+
+        // We've reached the end of the parens; if they are inverted, this is failure.
+        if (term.invert()) {
+            context->term -= term.atom.parenthesesWidth;
+            return false;
+        }
+
+        return true;
+    }
+
+    bool backtrackParentheticalAssertionBegin(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionBegin);
+        ASSERT(term.atom.quantityCount == 1);
+
+        // We've failed to match parens; if they are inverted, this is win!
+        if (term.invert()) {
+            context->term += term.atom.parenthesesWidth;
+            return true;
+        }
+
+        return false;
+    }
+
+    bool backtrackParentheticalAssertionEnd(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParentheticalAssertionEnd);
+        ASSERT(term.atom.quantityCount == 1);
+
+        BackTrackInfoParentheticalAssertion* backTrack = reinterpret_cast<BackTrackInfoParentheticalAssertion*>(context->frame + term.frameLocation);
+
+        input.setPos(backTrack->begin);
+
+        context->term -= term.atom.parenthesesWidth;
+        return false;
+    }
+
+    JSRegExpResult matchParentheses(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpattern);
+
+        BackTrackInfoParentheses* backTrack = reinterpret_cast<BackTrackInfoParentheses*>(context->frame + term.frameLocation);
+        ByteDisjunction* disjunctionBody = term.atom.parenthesesDisjunction;
+
+        backTrack->matchAmount = 0;
+        backTrack->lastContext = 0;
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount: {
+            // While we haven't yet reached our fixed limit,
+            while (backTrack->matchAmount < term.atom.quantityCount) {
+                // Try to do a match, and it it succeeds, add it to the list.
+                ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+                JSRegExpResult result = matchDisjunction(disjunctionBody, context->getDisjunctionContext(term));
+                if (result == JSRegExpMatch)
+                    appendParenthesesDisjunctionContext(backTrack, context);
+                else {
+                    // The match failed; try to find an alternate point to carry on from.
+                    resetMatches(term, context);
+                    freeParenthesesDisjunctionContext(context);
+
+                    if (result == JSRegExpNoMatch) {
+                        JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack);
+                        if (backtrackResult != JSRegExpMatch)
+                            return backtrackResult;
+                    } else
+                        return result;
+                }
+            }
+
+            ASSERT(backTrack->matchAmount == term.atom.quantityCount);
+            ParenthesesDisjunctionContext* context = backTrack->lastContext;
+            recordParenthesesMatch(term, context);
+            return JSRegExpMatch;
+        }
+
+        case QuantifierGreedy: {
+            while (backTrack->matchAmount < term.atom.quantityCount) {
+                ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+                JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term));
+                if (result == JSRegExpMatch)
+                    appendParenthesesDisjunctionContext(backTrack, context);
+                else {
+                    resetMatches(term, context);
+                    freeParenthesesDisjunctionContext(context);
+
+                    if (result != JSRegExpNoMatch)
+                        return result;
+
+                    break;
+                }
+            }
+
+            if (backTrack->matchAmount) {
+                ParenthesesDisjunctionContext* context = backTrack->lastContext;
+                recordParenthesesMatch(term, context);
+            }
+            return JSRegExpMatch;
+        }
+
+        case QuantifierNonGreedy:
+            return JSRegExpMatch;
+        }
+
+        ASSERT_NOT_REACHED();
+        return JSRegExpErrorNoMatch;
+    }
+
+    // Rules for backtracking differ depending on whether this is greedy or non-greedy.
+    //
+    // Greedy matches never should try just adding more - you should already have done
+    // the 'more' cases.  Always backtrack, at least a leetle bit.  However cases where
+    // you backtrack an item off the list needs checking, since we'll never have matched
+    // the one less case.  Tracking forwards, still add as much as possible.
+    //
+    // Non-greedy, we've already done the one less case, so don't match on popping.
+    // We haven't done the one more case, so always try to add that.
+    //
+    JSRegExpResult backtrackParentheses(ByteTerm& term, DisjunctionContext* context)
+    {
+        ASSERT(term.type == ByteTerm::TypeParenthesesSubpattern);
+
+        BackTrackInfoParentheses* backTrack = reinterpret_cast<BackTrackInfoParentheses*>(context->frame + term.frameLocation);
+        ByteDisjunction* disjunctionBody = term.atom.parenthesesDisjunction;
+
+        switch (term.atom.quantityType) {
+        case QuantifierFixedCount: {
+            ASSERT(backTrack->matchAmount == term.atom.quantityCount);
+
+            ParenthesesDisjunctionContext* context = 0;
+            JSRegExpResult result = parenthesesDoBacktrack(term, backTrack);
+
+            if (result != JSRegExpMatch)
+                return result;
+
+            // While we haven't yet reached our fixed limit,
+            while (backTrack->matchAmount < term.atom.quantityCount) {
+                // Try to do a match, and it it succeeds, add it to the list.
+                context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+                result = matchDisjunction(disjunctionBody, context->getDisjunctionContext(term));
+
+                if (result == JSRegExpMatch)
+                    appendParenthesesDisjunctionContext(backTrack, context);
+                else {
+                    // The match failed; try to find an alternate point to carry on from.
+                    resetMatches(term, context);
+                    freeParenthesesDisjunctionContext(context);
+
+                    if (result == JSRegExpNoMatch) {
+                        JSRegExpResult backtrackResult = parenthesesDoBacktrack(term, backTrack);
+                        if (backtrackResult != JSRegExpMatch)
+                            return backtrackResult;
+                    } else
+                        return result;
+                }
+            }
+
+            ASSERT(backTrack->matchAmount == term.atom.quantityCount);
+            context = backTrack->lastContext;
+            recordParenthesesMatch(term, context);
+            return JSRegExpMatch;
+        }
+
+        case QuantifierGreedy: {
+            if (!backTrack->matchAmount)
+                return JSRegExpNoMatch;
+
+            ParenthesesDisjunctionContext* context = backTrack->lastContext;
+            JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true);
+            if (result == JSRegExpMatch) {
+                while (backTrack->matchAmount < term.atom.quantityCount) {
+                    ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+                    JSRegExpResult parenthesesResult = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term));
+                    if (parenthesesResult == JSRegExpMatch)
+                        appendParenthesesDisjunctionContext(backTrack, context);
+                    else {
+                        resetMatches(term, context);
+                        freeParenthesesDisjunctionContext(context);
+
+                        if (parenthesesResult != JSRegExpNoMatch)
+                            return parenthesesResult;
+
+                        break;
+                    }
+                }
+            } else {
+                resetMatches(term, context);
+                popParenthesesDisjunctionContext(backTrack);
+                freeParenthesesDisjunctionContext(context);
+
+                if (result != JSRegExpNoMatch)
+                    return result;
+            }
+
+            if (backTrack->matchAmount) {
+                ParenthesesDisjunctionContext* context = backTrack->lastContext;
+                recordParenthesesMatch(term, context);
+            }
+            return JSRegExpMatch;
+        }
+
+        case QuantifierNonGreedy: {
+            // If we've not reached the limit, try to add one more match.
+            if (backTrack->matchAmount < term.atom.quantityCount) {
+                ParenthesesDisjunctionContext* context = allocParenthesesDisjunctionContext(disjunctionBody, output, term);
+                JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term));
+                if (result == JSRegExpMatch) {
+                    appendParenthesesDisjunctionContext(backTrack, context);
+                    recordParenthesesMatch(term, context);
+                    return JSRegExpMatch;
+                }
+
+                resetMatches(term, context);
+                freeParenthesesDisjunctionContext(context);
+
+                if (result != JSRegExpNoMatch)
+                    return result;
+            }
+
+            // Nope - okay backtrack looking for an alternative.
+            while (backTrack->matchAmount) {
+                ParenthesesDisjunctionContext* context = backTrack->lastContext;
+                JSRegExpResult result = matchNonZeroDisjunction(disjunctionBody, context->getDisjunctionContext(term), true);
+                if (result == JSRegExpMatch) {
+                    // successful backtrack! we're back in the game!
+                    if (backTrack->matchAmount) {
+                        context = backTrack->lastContext;
+                        recordParenthesesMatch(term, context);
+                    }
+                    return JSRegExpMatch;
+                }
+
+                // pop a match off the stack
+                resetMatches(term, context);
+                popParenthesesDisjunctionContext(backTrack);
+                freeParenthesesDisjunctionContext(context);
+
+                return result;
+            }
+
+            return JSRegExpNoMatch;
+        }
+        }
+
+        ASSERT_NOT_REACHED();
+        return JSRegExpErrorNoMatch;
+    }
+
+    bool matchDotStarEnclosure(ByteTerm& term, DisjunctionContext* context)
+    {
+        UNUSED_PARAM(term);
+        unsigned matchBegin = context->matchBegin;
+
+        if (matchBegin) {
+            for (matchBegin--; true; matchBegin--) {
+                if (testCharacterClass(pattern->newlineCharacterClass, input.reread(matchBegin))) {
+                    ++matchBegin;
+                    break;
+                }
+
+                if (!matchBegin)
+                    break;
+            }
+        }
+
+        unsigned matchEnd = input.getPos();
+
+        for (; (matchEnd != input.end())
+             && (!testCharacterClass(pattern->newlineCharacterClass, input.reread(matchEnd))); matchEnd++) { }
+
+        if (((matchBegin && term.anchors.m_bol)
+             || ((matchEnd != input.end()) && term.anchors.m_eol))
+            && !pattern->m_multiline)
+            return false;
+
+        context->matchBegin = matchBegin;
+        context->matchEnd = matchEnd;
+        return true;
+    }
+
+#define MATCH_NEXT() { ++context->term; goto matchAgain; }
+#define BACKTRACK() { --context->term; goto backtrack; }
+#define currentTerm() (disjunction->terms[context->term])
+    JSRegExpResult matchDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
+    {
+        if (!--remainingMatchCount)
+            return JSRegExpErrorHitLimit;
+
+        if (btrack)
+            BACKTRACK();
+
+        context->matchBegin = input.getPos();
+        context->term = 0;
+
+    matchAgain:
+        ASSERT(context->term < static_cast<int>(disjunction->terms.size()));
+
+        switch (currentTerm().type) {
+        case ByteTerm::TypeSubpatternBegin:
+            MATCH_NEXT();
+        case ByteTerm::TypeSubpatternEnd:
+            context->matchEnd = input.getPos();
+            return JSRegExpMatch;
+
+        case ByteTerm::TypeBodyAlternativeBegin:
+            MATCH_NEXT();
+        case ByteTerm::TypeBodyAlternativeDisjunction:
+        case ByteTerm::TypeBodyAlternativeEnd:
+            context->matchEnd = input.getPos();
+            return JSRegExpMatch;
+
+        case ByteTerm::TypeAlternativeBegin:
+            MATCH_NEXT();
+        case ByteTerm::TypeAlternativeDisjunction:
+        case ByteTerm::TypeAlternativeEnd: {
+            int offset = currentTerm().alternative.end;
+            BackTrackInfoAlternative* backTrack = reinterpret_cast<BackTrackInfoAlternative*>(context->frame + currentTerm().frameLocation);
+            backTrack->offset = offset;
+            context->term += offset;
+            MATCH_NEXT();
+        }
+
+        case ByteTerm::TypeAssertionBOL:
+            if (matchAssertionBOL(currentTerm()))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeAssertionEOL:
+            if (matchAssertionEOL(currentTerm()))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeAssertionWordBoundary:
+            if (matchAssertionWordBoundary(currentTerm()))
+                MATCH_NEXT();
+            BACKTRACK();
+
+        case ByteTerm::TypePatternCharacterOnce:
+        case ByteTerm::TypePatternCharacterFixed: {
+            for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
+                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition + matchAmount))
+                    BACKTRACK();
+            }
+            MATCH_NEXT();
+        }
+        case ByteTerm::TypePatternCharacterGreedy: {
+            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+            unsigned matchAmount = 0;
+            while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
+                if (!checkCharacter(currentTerm().atom.patternCharacter, currentTerm().inputPosition - 1)) {
+                    input.uncheckInput(1);
+                    break;
+                }
+                ++matchAmount;
+            }
+            backTrack->matchAmount = matchAmount;
+
+            MATCH_NEXT();
+        }
+        case ByteTerm::TypePatternCharacterNonGreedy: {
+            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+            backTrack->matchAmount = 0;
+            MATCH_NEXT();
+        }
+
+        case ByteTerm::TypePatternCasedCharacterOnce:
+        case ByteTerm::TypePatternCasedCharacterFixed: {
+            for (unsigned matchAmount = 0; matchAmount < currentTerm().atom.quantityCount; ++matchAmount) {
+                if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition + matchAmount))
+                    BACKTRACK();
+            }
+            MATCH_NEXT();
+        }
+        case ByteTerm::TypePatternCasedCharacterGreedy: {
+            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+            unsigned matchAmount = 0;
+            while ((matchAmount < currentTerm().atom.quantityCount) && input.checkInput(1)) {
+                if (!checkCasedCharacter(currentTerm().atom.casedCharacter.lo, currentTerm().atom.casedCharacter.hi, currentTerm().inputPosition - 1)) {
+                    input.uncheckInput(1);
+                    break;
+                }
+                ++matchAmount;
+            }
+            backTrack->matchAmount = matchAmount;
+
+            MATCH_NEXT();
+        }
+        case ByteTerm::TypePatternCasedCharacterNonGreedy: {
+            BackTrackInfoPatternCharacter* backTrack = reinterpret_cast<BackTrackInfoPatternCharacter*>(context->frame + currentTerm().frameLocation);
+            backTrack->matchAmount = 0;
+            MATCH_NEXT();
+        }
+
+        case ByteTerm::TypeCharacterClass:
+            if (matchCharacterClass(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeBackReference:
+            if (matchBackReference(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpattern: {
+            JSRegExpResult result = matchParentheses(currentTerm(), context);
+
+            if (result == JSRegExpMatch) {
+                MATCH_NEXT();
+            }  else if (result != JSRegExpNoMatch)
+                return result;
+
+            BACKTRACK();
+        }
+        case ByteTerm::TypeParenthesesSubpatternOnceBegin:
+            if (matchParenthesesOnceBegin(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpatternOnceEnd:
+            if (matchParenthesesOnceEnd(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpatternTerminalBegin:
+            if (matchParenthesesTerminalBegin(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpatternTerminalEnd:
+            if (matchParenthesesTerminalEnd(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParentheticalAssertionBegin:
+            if (matchParentheticalAssertionBegin(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParentheticalAssertionEnd:
+            if (matchParentheticalAssertionEnd(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+
+        case ByteTerm::TypeCheckInput:
+            if (input.checkInput(currentTerm().checkInputCount))
+                MATCH_NEXT();
+            BACKTRACK();
+
+        case ByteTerm::TypeUncheckInput:
+            input.uncheckInput(currentTerm().checkInputCount);
+            MATCH_NEXT();
+                
+        case ByteTerm::TypeDotStarEnclosure:
+            if (matchDotStarEnclosure(currentTerm(), context))
+                return JSRegExpMatch;
+            BACKTRACK();
+        }
+
+        // We should never fall-through to here.
+        ASSERT_NOT_REACHED();
+
+    backtrack:
+        ASSERT(context->term < static_cast<int>(disjunction->terms.size()));
+
+        switch (currentTerm().type) {
+        case ByteTerm::TypeSubpatternBegin:
+            return JSRegExpNoMatch;
+        case ByteTerm::TypeSubpatternEnd:
+            ASSERT_NOT_REACHED();
+
+        case ByteTerm::TypeBodyAlternativeBegin:
+        case ByteTerm::TypeBodyAlternativeDisjunction: {
+            int offset = currentTerm().alternative.next;
+            context->term += offset;
+            if (offset > 0)
+                MATCH_NEXT();
+
+            if (input.atEnd())
+                return JSRegExpNoMatch;
+
+            input.next();
+
+            context->matchBegin = input.getPos();
+
+            if (currentTerm().alternative.onceThrough)
+                context->term += currentTerm().alternative.next;
+
+            MATCH_NEXT();
+        }
+        case ByteTerm::TypeBodyAlternativeEnd:
+            ASSERT_NOT_REACHED();
+
+        case ByteTerm::TypeAlternativeBegin:
+        case ByteTerm::TypeAlternativeDisjunction: {
+            int offset = currentTerm().alternative.next;
+            context->term += offset;
+            if (offset > 0)
+                MATCH_NEXT();
+            BACKTRACK();
+        }
+        case ByteTerm::TypeAlternativeEnd: {
+            // We should never backtrack back into an alternative of the main body of the regex.
+            BackTrackInfoAlternative* backTrack = reinterpret_cast<BackTrackInfoAlternative*>(context->frame + currentTerm().frameLocation);
+            unsigned offset = backTrack->offset;
+            context->term -= offset;
+            BACKTRACK();
+        }
+
+        case ByteTerm::TypeAssertionBOL:
+        case ByteTerm::TypeAssertionEOL:
+        case ByteTerm::TypeAssertionWordBoundary:
+            BACKTRACK();
+
+        case ByteTerm::TypePatternCharacterOnce:
+        case ByteTerm::TypePatternCharacterFixed:
+        case ByteTerm::TypePatternCharacterGreedy:
+        case ByteTerm::TypePatternCharacterNonGreedy:
+            if (backtrackPatternCharacter(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypePatternCasedCharacterOnce:
+        case ByteTerm::TypePatternCasedCharacterFixed:
+        case ByteTerm::TypePatternCasedCharacterGreedy:
+        case ByteTerm::TypePatternCasedCharacterNonGreedy:
+            if (backtrackPatternCasedCharacter(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeCharacterClass:
+            if (backtrackCharacterClass(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeBackReference:
+            if (backtrackBackReference(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpattern: {
+            JSRegExpResult result = backtrackParentheses(currentTerm(), context);
+
+            if (result == JSRegExpMatch) {
+                MATCH_NEXT();
+            } else if (result != JSRegExpNoMatch)
+                return result;
+
+            BACKTRACK();
+        }
+        case ByteTerm::TypeParenthesesSubpatternOnceBegin:
+            if (backtrackParenthesesOnceBegin(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpatternOnceEnd:
+            if (backtrackParenthesesOnceEnd(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpatternTerminalBegin:
+            if (backtrackParenthesesTerminalBegin(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParenthesesSubpatternTerminalEnd:
+            if (backtrackParenthesesTerminalEnd(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParentheticalAssertionBegin:
+            if (backtrackParentheticalAssertionBegin(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+        case ByteTerm::TypeParentheticalAssertionEnd:
+            if (backtrackParentheticalAssertionEnd(currentTerm(), context))
+                MATCH_NEXT();
+            BACKTRACK();
+
+        case ByteTerm::TypeCheckInput:
+            input.uncheckInput(currentTerm().checkInputCount);
+            BACKTRACK();
+
+        case ByteTerm::TypeUncheckInput:
+            input.checkInput(currentTerm().checkInputCount);
+            BACKTRACK();
+
+        case ByteTerm::TypeDotStarEnclosure:
+            ASSERT_NOT_REACHED();
+        }
+
+        ASSERT_NOT_REACHED();
+        return JSRegExpErrorNoMatch;
+    }
+
+    JSRegExpResult matchNonZeroDisjunction(ByteDisjunction* disjunction, DisjunctionContext* context, bool btrack = false)
+    {
+        JSRegExpResult result = matchDisjunction(disjunction, context, btrack);
+
+        if (result == JSRegExpMatch) {
+            while (context->matchBegin == context->matchEnd) {
+                result = matchDisjunction(disjunction, context, true);
+                if (result != JSRegExpMatch)
+                    return result;
+            }
+            return JSRegExpMatch;
+        }
+
+        return result;
+    }
+
+    int interpret()
+    {
+        allocatorPool = pattern->m_allocator->startAllocator();
+        if (!allocatorPool)
+            CRASH();
+
+        for (unsigned i = 0; i < ((pattern->m_body->m_numSubpatterns + 1) << 1); ++i)
+            output[i] = -1;
+
+        DisjunctionContext* context = allocDisjunctionContext(pattern->m_body.get());
+
+        JSRegExpResult result = matchDisjunction(pattern->m_body.get(), context, false);
+        if (result == JSRegExpMatch) {
+            output[0] = context->matchBegin;
+            output[1] = context->matchEnd;
+        }
+
+        freeDisjunctionContext(context);
+
+        pattern->m_allocator->stopAllocator();
+
+        // RegExp.cpp currently expects all error to be converted to -1.
+        ASSERT((result == JSRegExpMatch) == (output[0] != -1));
+        return output[0];
+    }
+
+    Interpreter(BytecodePattern* pattern, int* output, const UChar* inputChar, unsigned start, unsigned length)
+        : pattern(pattern)
+        , output(output)
+        , input(inputChar, start, length)
+        , allocatorPool(0)
+        , remainingMatchCount(matchLimit)
+    {
+    }
+
+private:
+    BytecodePattern* pattern;
+    int* output;
+    InputStream input;
+    BumpPointerPool* allocatorPool;
+    unsigned remainingMatchCount;
+};
+
+
+
+class ByteCompiler {
+    struct ParenthesesStackEntry {
+        unsigned beginTerm;
+        unsigned savedAlternativeIndex;
+        ParenthesesStackEntry(unsigned beginTerm, unsigned savedAlternativeIndex/*, unsigned subpatternId, bool capture = false*/)
+            : beginTerm(beginTerm)
+            , savedAlternativeIndex(savedAlternativeIndex)
+        {
+        }
+    };
+
+public:
+    ByteCompiler(YarrPattern& pattern)
+        : m_pattern(pattern)
+    {
+        m_currentAlternativeIndex = 0;
+    }
+
+    PassOwnPtr<BytecodePattern> compile(BumpPointerAllocator* allocator)
+    {
+        regexBegin(m_pattern.m_numSubpatterns, m_pattern.m_body->m_callFrameSize, m_pattern.m_body->m_alternatives[0]->onceThrough());
+        emitDisjunction(m_pattern.m_body);
+        regexEnd();
+
+        return adoptPtr(new BytecodePattern(m_bodyDisjunction.release(), m_allParenthesesInfo, m_pattern, allocator));
+    }
+
+    void checkInput(unsigned count)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm::CheckInput(count));
+    }
+
+    void uncheckInput(unsigned count)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm::UncheckInput(count));
+    }
+    
+    void assertionBOL(int inputPosition)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm::BOL(inputPosition));
+    }
+
+    void assertionEOL(int inputPosition)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm::EOL(inputPosition));
+    }
+
+    void assertionWordBoundary(bool invert, int inputPosition)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm::WordBoundary(invert, inputPosition));
+    }
+
+    void atomPatternCharacter(UChar ch, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+    {
+        if (m_pattern.m_ignoreCase) {
+            UChar lo = Unicode::toLower(ch);
+            UChar hi = Unicode::toUpper(ch);
+
+            if (lo != hi) {
+                m_bodyDisjunction->terms.append(ByteTerm(lo, hi, inputPosition, frameLocation, quantityCount, quantityType));
+                return;
+            }
+        }
+
+        m_bodyDisjunction->terms.append(ByteTerm(ch, inputPosition, frameLocation, quantityCount, quantityType));
+    }
+
+    void atomCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm(characterClass, invert, inputPosition));
+
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+    }
+
+    void atomBackReference(unsigned subpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+    {
+        ASSERT(subpatternId);
+
+        m_bodyDisjunction->terms.append(ByteTerm::BackReference(subpatternId, inputPosition));
+
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+    }
+
+    void atomParenthesesOnceBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+    {
+        int beginTerm = m_bodyDisjunction->terms.size();
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, false, inputPosition));
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+
+        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
+        m_currentAlternativeIndex = beginTerm + 1;
+    }
+
+    void atomParenthesesTerminalBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+    {
+        int beginTerm = m_bodyDisjunction->terms.size();
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalBegin, subpatternId, capture, false, inputPosition));
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+
+        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
+        m_currentAlternativeIndex = beginTerm + 1;
+    }
+
+    void atomParenthesesSubpatternBegin(unsigned subpatternId, bool capture, int inputPosition, unsigned frameLocation, unsigned alternativeFrameLocation)
+    {
+        // Errrk! - this is a little crazy, we initially generate as a TypeParenthesesSubpatternOnceBegin,
+        // then fix this up at the end! - simplifying this should make it much clearer.
+        // https://bugs.webkit.org/show_bug.cgi?id=50136
+
+        int beginTerm = m_bodyDisjunction->terms.size();
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceBegin, subpatternId, capture, false, inputPosition));
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+
+        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
+        m_currentAlternativeIndex = beginTerm + 1;
+    }
+
+    void atomParentheticalAssertionBegin(unsigned subpatternId, bool invert, unsigned frameLocation, unsigned alternativeFrameLocation)
+    {
+        int beginTerm = m_bodyDisjunction->terms.size();
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionBegin, subpatternId, false, invert, 0));
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = frameLocation;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeBegin());
+        m_bodyDisjunction->terms[m_bodyDisjunction->terms.size() - 1].frameLocation = alternativeFrameLocation;
+
+        m_parenthesesStack.append(ParenthesesStackEntry(beginTerm, m_currentAlternativeIndex));
+        m_currentAlternativeIndex = beginTerm + 1;
+    }
+
+    void atomParentheticalAssertionEnd(int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+    {
+        unsigned beginTerm = popParenthesesStack();
+        closeAlternative(beginTerm + 1);
+        unsigned endTerm = m_bodyDisjunction->terms.size();
+
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParentheticalAssertionBegin);
+
+        bool invert = m_bodyDisjunction->terms[beginTerm].invert();
+        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParentheticalAssertionEnd, subpatternId, false, invert, inputPosition));
+        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
+
+        m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
+    }
+
+    void assertionDotStarEnclosure(bool bolAnchored, bool eolAnchored)
+    {
+        m_bodyDisjunction->terms.append(ByteTerm::DotStarEnclosure(bolAnchored, eolAnchored));
+    }
+
+    unsigned popParenthesesStack()
+    {
+        ASSERT(m_parenthesesStack.size());
+        int stackEnd = m_parenthesesStack.size() - 1;
+        unsigned beginTerm = m_parenthesesStack[stackEnd].beginTerm;
+        m_currentAlternativeIndex = m_parenthesesStack[stackEnd].savedAlternativeIndex;
+        m_parenthesesStack.shrink(stackEnd);
+
+        ASSERT(beginTerm < m_bodyDisjunction->terms.size());
+        ASSERT(m_currentAlternativeIndex < m_bodyDisjunction->terms.size());
+
+        return beginTerm;
+    }
+
+#ifndef NDEBUG
+    void dumpDisjunction(ByteDisjunction* disjunction)
+    {
+        printf("ByteDisjunction(%p):\n\t", disjunction);
+        for (unsigned i = 0; i < disjunction->terms.size(); ++i)
+            printf("{ %d } ", disjunction->terms[i].type);
+        printf("\n");
+    }
+#endif
+
+    void closeAlternative(int beginTerm)
+    {
+        int origBeginTerm = beginTerm;
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeBegin);
+        int endIndex = m_bodyDisjunction->terms.size();
+
+        unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
+
+        if (!m_bodyDisjunction->terms[beginTerm].alternative.next)
+            m_bodyDisjunction->terms.remove(beginTerm);
+        else {
+            while (m_bodyDisjunction->terms[beginTerm].alternative.next) {
+                beginTerm += m_bodyDisjunction->terms[beginTerm].alternative.next;
+                ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeAlternativeDisjunction);
+                m_bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
+                m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+            }
+
+            m_bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
+
+            m_bodyDisjunction->terms.append(ByteTerm::AlternativeEnd());
+            m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
+        }
+    }
+
+    void closeBodyAlternative()
+    {
+        int beginTerm = 0;
+        int origBeginTerm = 0;
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeBegin);
+        int endIndex = m_bodyDisjunction->terms.size();
+
+        unsigned frameLocation = m_bodyDisjunction->terms[beginTerm].frameLocation;
+
+        while (m_bodyDisjunction->terms[beginTerm].alternative.next) {
+            beginTerm += m_bodyDisjunction->terms[beginTerm].alternative.next;
+            ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeBodyAlternativeDisjunction);
+            m_bodyDisjunction->terms[beginTerm].alternative.end = endIndex - beginTerm;
+            m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+        }
+
+        m_bodyDisjunction->terms[beginTerm].alternative.next = origBeginTerm - beginTerm;
+
+        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeEnd());
+        m_bodyDisjunction->terms[endIndex].frameLocation = frameLocation;
+    }
+
+    void atomParenthesesSubpatternEnd(unsigned lastSubpatternId, int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType, unsigned callFrameSize = 0)
+    {
+        unsigned beginTerm = popParenthesesStack();
+        closeAlternative(beginTerm + 1);
+        unsigned endTerm = m_bodyDisjunction->terms.size();
+
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+
+        ByteTerm& parenthesesBegin = m_bodyDisjunction->terms[beginTerm];
+
+        bool capture = parenthesesBegin.capture();
+        unsigned subpatternId = parenthesesBegin.atom.subpatternId;
+
+        unsigned numSubpatterns = lastSubpatternId - subpatternId + 1;
+        ByteDisjunction* parenthesesDisjunction = new ByteDisjunction(numSubpatterns, callFrameSize);
+
+        parenthesesDisjunction->terms.append(ByteTerm::SubpatternBegin());
+        for (unsigned termInParentheses = beginTerm + 1; termInParentheses < endTerm; ++termInParentheses)
+            parenthesesDisjunction->terms.append(m_bodyDisjunction->terms[termInParentheses]);
+        parenthesesDisjunction->terms.append(ByteTerm::SubpatternEnd());
+
+        m_bodyDisjunction->terms.shrink(beginTerm);
+
+        m_allParenthesesInfo.append(parenthesesDisjunction);
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, inputPosition));
+
+        m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[beginTerm].frameLocation = frameLocation;
+    }
+
+    void atomParenthesesOnceEnd(int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+    {
+        unsigned beginTerm = popParenthesesStack();
+        closeAlternative(beginTerm + 1);
+        unsigned endTerm = m_bodyDisjunction->terms.size();
+
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParenthesesSubpatternOnceBegin);
+
+        bool capture = m_bodyDisjunction->terms[beginTerm].capture();
+        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternOnceEnd, subpatternId, capture, false, inputPosition));
+        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
+
+        m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
+    }
+
+    void atomParenthesesTerminalEnd(int inputPosition, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+    {
+        unsigned beginTerm = popParenthesesStack();
+        closeAlternative(beginTerm + 1);
+        unsigned endTerm = m_bodyDisjunction->terms.size();
+
+        ASSERT(m_bodyDisjunction->terms[beginTerm].type == ByteTerm::TypeParenthesesSubpatternTerminalBegin);
+
+        bool capture = m_bodyDisjunction->terms[beginTerm].capture();
+        unsigned subpatternId = m_bodyDisjunction->terms[beginTerm].atom.subpatternId;
+
+        m_bodyDisjunction->terms.append(ByteTerm(ByteTerm::TypeParenthesesSubpatternTerminalEnd, subpatternId, capture, false, inputPosition));
+        m_bodyDisjunction->terms[beginTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].atom.parenthesesWidth = endTerm - beginTerm;
+        m_bodyDisjunction->terms[endTerm].frameLocation = frameLocation;
+
+        m_bodyDisjunction->terms[beginTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[beginTerm].atom.quantityType = quantityType;
+        m_bodyDisjunction->terms[endTerm].atom.quantityCount = quantityCount;
+        m_bodyDisjunction->terms[endTerm].atom.quantityType = quantityType;
+    }
+
+    void regexBegin(unsigned numSubpatterns, unsigned callFrameSize, bool onceThrough)
+    {
+        m_bodyDisjunction = adoptPtr(new ByteDisjunction(numSubpatterns, callFrameSize));
+        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeBegin(onceThrough));
+        m_bodyDisjunction->terms[0].frameLocation = 0;
+        m_currentAlternativeIndex = 0;
+    }
+
+    void regexEnd()
+    {
+        closeBodyAlternative();
+    }
+
+    void alternativeBodyDisjunction(bool onceThrough)
+    {
+        int newAlternativeIndex = m_bodyDisjunction->terms.size();
+        m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
+        m_bodyDisjunction->terms.append(ByteTerm::BodyAlternativeDisjunction(onceThrough));
+
+        m_currentAlternativeIndex = newAlternativeIndex;
+    }
+
+    void alternativeDisjunction()
+    {
+        int newAlternativeIndex = m_bodyDisjunction->terms.size();
+        m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex;
+        m_bodyDisjunction->terms.append(ByteTerm::AlternativeDisjunction());
+
+        m_currentAlternativeIndex = newAlternativeIndex;
+    }
+
+    void emitDisjunction(PatternDisjunction* disjunction, unsigned inputCountAlreadyChecked = 0, unsigned parenthesesInputCountAlreadyChecked = 0)
+    {
+        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
+            unsigned currentCountAlreadyChecked = inputCountAlreadyChecked;
+
+            PatternAlternative* alternative = disjunction->m_alternatives[alt];
+
+            if (alt) {
+                if (disjunction == m_pattern.m_body)
+                    alternativeBodyDisjunction(alternative->onceThrough());
+                else
+                    alternativeDisjunction();
+            }
+
+            unsigned minimumSize = alternative->m_minimumSize;
+            ASSERT(minimumSize >= parenthesesInputCountAlreadyChecked);
+            unsigned countToCheck = minimumSize - parenthesesInputCountAlreadyChecked;
+
+            if (countToCheck) {
+                checkInput(countToCheck);
+                currentCountAlreadyChecked += countToCheck;
+            }
+
+            for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
+                PatternTerm& term = alternative->m_terms[i];
+
+                switch (term.type) {
+                case PatternTerm::TypeAssertionBOL:
+                    assertionBOL(term.inputPosition - currentCountAlreadyChecked);
+                    break;
+
+                case PatternTerm::TypeAssertionEOL:
+                    assertionEOL(term.inputPosition - currentCountAlreadyChecked);
+                    break;
+
+                case PatternTerm::TypeAssertionWordBoundary:
+                    assertionWordBoundary(term.invert(), term.inputPosition - currentCountAlreadyChecked);
+                    break;
+
+                case PatternTerm::TypePatternCharacter:
+                    atomPatternCharacter(term.patternCharacter, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+                    break;
+
+                case PatternTerm::TypeCharacterClass:
+                    atomCharacterClass(term.characterClass, term.invert(), term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+                    break;
+
+                case PatternTerm::TypeBackReference:
+                    atomBackReference(term.backReferenceSubpatternId, term.inputPosition - currentCountAlreadyChecked, term.frameLocation, term.quantityCount, term.quantityType);
+                        break;
+
+                case PatternTerm::TypeForwardReference:
+                    break;
+
+                case PatternTerm::TypeParenthesesSubpattern: {
+                    unsigned disjunctionAlreadyCheckedCount = 0;
+                    if (term.quantityCount == 1 && !term.parentheses.isCopy) {
+                        unsigned alternativeFrameLocation = term.frameLocation;
+                        // For QuantifierFixedCount we pre-check the minimum size; for greedy/non-greedy we reserve a slot in the frame.
+                        if (term.quantityType == QuantifierFixedCount)
+                            disjunctionAlreadyCheckedCount = term.parentheses.disjunction->m_minimumSize;
+                        else
+                            alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
+                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
+                        atomParenthesesOnceBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, alternativeFrameLocation);
+                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
+                        atomParenthesesOnceEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType);
+                    } else if (term.parentheses.isTerminal) {
+                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
+                        atomParenthesesTerminalBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, term.frameLocation + YarrStackSpaceForBackTrackInfoParenthesesOnce);
+                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, disjunctionAlreadyCheckedCount);
+                        atomParenthesesTerminalEnd(delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType);
+                    } else {
+                        unsigned delegateEndInputOffset = term.inputPosition - currentCountAlreadyChecked;
+                        atomParenthesesSubpatternBegin(term.parentheses.subpatternId, term.capture(), delegateEndInputOffset - disjunctionAlreadyCheckedCount, term.frameLocation, 0);
+                        emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, 0);
+                        atomParenthesesSubpatternEnd(term.parentheses.lastSubpatternId, delegateEndInputOffset, term.frameLocation, term.quantityCount, term.quantityType, term.parentheses.disjunction->m_callFrameSize);
+                    }
+                    break;
+                }
+
+                case PatternTerm::TypeParentheticalAssertion: {
+                    unsigned alternativeFrameLocation = term.frameLocation + YarrStackSpaceForBackTrackInfoParentheticalAssertion;
+
+                    ASSERT(currentCountAlreadyChecked >= static_cast<unsigned>(term.inputPosition));
+                    unsigned positiveInputOffset = currentCountAlreadyChecked - static_cast<unsigned>(term.inputPosition);
+                    unsigned uncheckAmount = 0;
+                    if (positiveInputOffset > term.parentheses.disjunction->m_minimumSize) {
+                        uncheckAmount = positiveInputOffset - term.parentheses.disjunction->m_minimumSize;
+                        uncheckInput(uncheckAmount);
+                        currentCountAlreadyChecked -= uncheckAmount;
+                    }
+
+                    atomParentheticalAssertionBegin(term.parentheses.subpatternId, term.invert(), term.frameLocation, alternativeFrameLocation);
+                    emitDisjunction(term.parentheses.disjunction, currentCountAlreadyChecked, positiveInputOffset - uncheckAmount);
+                    atomParentheticalAssertionEnd(0, term.frameLocation, term.quantityCount, term.quantityType);
+                    if (uncheckAmount) {
+                        checkInput(uncheckAmount);
+                        currentCountAlreadyChecked += uncheckAmount;
+                    }
+                    break;
+                }
+
+                case PatternTerm::TypeDotStarEnclosure:
+                    assertionDotStarEnclosure(term.anchors.bolAnchor, term.anchors.eolAnchor);
+                    break;
+                }
+            }
+        }
+    }
+
+private:
+    YarrPattern& m_pattern;
+    OwnPtr<ByteDisjunction> m_bodyDisjunction;
+    unsigned m_currentAlternativeIndex;
+    Vector<ParenthesesStackEntry> m_parenthesesStack;
+    Vector<ByteDisjunction*> m_allParenthesesInfo;
+};
+
+PassOwnPtr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocator* allocator)
+{
+    return ByteCompiler(pattern).compile(allocator);
+}
+
+int interpret(BytecodePattern* bytecode, const UChar* input, unsigned start, unsigned length, int* output)
+{
+    return Interpreter(bytecode, output, input, start, length).interpret();
+}
+
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoPatternCharacter) == (YarrStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoPatternCharacter);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoCharacterClass) == (YarrStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoCharacterClass);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoBackReference) == (YarrStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoBackReference);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoAlternative) == (YarrStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoAlternative);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheticalAssertion) == (YarrStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheticalAssertion);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParenthesesOnce) == (YarrStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParenthesesOnce);
+COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheses) == (YarrStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheses);
+
+
+} }
diff --git a/yarr/YarrInterpreter.h b/yarr/YarrInterpreter.h
new file mode 100644 (file)
index 0000000..78a8f34
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2009, 2010 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 YarrInterpreter_h
+#define YarrInterpreter_h
+
+#include "YarrPattern.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WTF {
+class BumpPointerAllocator;
+}
+using WTF::BumpPointerAllocator;
+
+namespace JSC { namespace Yarr {
+
+class ByteDisjunction;
+
+struct ByteTerm {
+    enum Type {
+        TypeBodyAlternativeBegin,
+        TypeBodyAlternativeDisjunction,
+        TypeBodyAlternativeEnd,
+        TypeAlternativeBegin,
+        TypeAlternativeDisjunction,
+        TypeAlternativeEnd,
+        TypeSubpatternBegin,
+        TypeSubpatternEnd,
+        TypeAssertionBOL,
+        TypeAssertionEOL,
+        TypeAssertionWordBoundary,
+        TypePatternCharacterOnce,
+        TypePatternCharacterFixed,
+        TypePatternCharacterGreedy,
+        TypePatternCharacterNonGreedy,
+        TypePatternCasedCharacterOnce,
+        TypePatternCasedCharacterFixed,
+        TypePatternCasedCharacterGreedy,
+        TypePatternCasedCharacterNonGreedy,
+        TypeCharacterClass,
+        TypeBackReference,
+        TypeParenthesesSubpattern,
+        TypeParenthesesSubpatternOnceBegin,
+        TypeParenthesesSubpatternOnceEnd,
+        TypeParenthesesSubpatternTerminalBegin,
+        TypeParenthesesSubpatternTerminalEnd,
+        TypeParentheticalAssertionBegin,
+        TypeParentheticalAssertionEnd,
+        TypeCheckInput,
+        TypeUncheckInput,
+        TypeDotStarEnclosure,
+    } type;
+    union {
+        struct {
+            union {
+                UChar patternCharacter;
+                struct {
+                    UChar lo;
+                    UChar hi;
+                } casedCharacter;
+                CharacterClass* characterClass;
+                unsigned subpatternId;
+            };
+            union {
+                ByteDisjunction* parenthesesDisjunction;
+                unsigned parenthesesWidth;
+            };
+            QuantifierType quantityType;
+            unsigned quantityCount;
+        } atom;
+        struct {
+            int next;
+            int end;
+            bool onceThrough;
+        } alternative;
+        struct {
+            bool m_bol : 1;
+            bool m_eol : 1;
+        } anchors;
+        unsigned checkInputCount;
+    };
+    unsigned frameLocation;
+    bool m_capture : 1;
+    bool m_invert : 1;
+    int inputPosition;
+
+    ByteTerm(UChar ch, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+        : frameLocation(frameLocation)
+        , m_capture(false)
+        , m_invert(false)
+    {
+        switch (quantityType) {
+        case QuantifierFixedCount:
+            type = (quantityCount == 1) ? ByteTerm::TypePatternCharacterOnce : ByteTerm::TypePatternCharacterFixed;
+            break;
+        case QuantifierGreedy:
+            type = ByteTerm::TypePatternCharacterGreedy;
+            break;
+        case QuantifierNonGreedy:
+            type = ByteTerm::TypePatternCharacterNonGreedy;
+            break;
+        }
+
+        atom.patternCharacter = ch;
+        atom.quantityType = quantityType;
+        atom.quantityCount = quantityCount;
+        inputPosition = inputPos;
+    }
+
+    ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, unsigned quantityCount, QuantifierType quantityType)
+        : frameLocation(frameLocation)
+        , m_capture(false)
+        , m_invert(false)
+    {
+        switch (quantityType) {
+        case QuantifierFixedCount:
+            type = (quantityCount == 1) ? ByteTerm::TypePatternCasedCharacterOnce : ByteTerm::TypePatternCasedCharacterFixed;
+            break;
+        case QuantifierGreedy:
+            type = ByteTerm::TypePatternCasedCharacterGreedy;
+            break;
+        case QuantifierNonGreedy:
+            type = ByteTerm::TypePatternCasedCharacterNonGreedy;
+            break;
+        }
+
+        atom.casedCharacter.lo = lo;
+        atom.casedCharacter.hi = hi;
+        atom.quantityType = quantityType;
+        atom.quantityCount = quantityCount;
+        inputPosition = inputPos;
+    }
+
+    ByteTerm(CharacterClass* characterClass, bool invert, int inputPos)
+        : type(ByteTerm::TypeCharacterClass)
+        , m_capture(false)
+        , m_invert(invert)
+    {
+        atom.characterClass = characterClass;
+        atom.quantityType = QuantifierFixedCount;
+        atom.quantityCount = 1;
+        inputPosition = inputPos;
+    }
+
+    ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool capture, int inputPos)
+        : type(type)
+        , m_capture(capture)
+        , m_invert(false)
+    {
+        atom.subpatternId = subpatternId;
+        atom.parenthesesDisjunction = parenthesesInfo;
+        atom.quantityType = QuantifierFixedCount;
+        atom.quantityCount = 1;
+        inputPosition = inputPos;
+    }
+    
+    ByteTerm(Type type, bool invert = false)
+        : type(type)
+        , m_capture(false)
+        , m_invert(invert)
+    {
+        atom.quantityType = QuantifierFixedCount;
+        atom.quantityCount = 1;
+    }
+
+    ByteTerm(Type type, unsigned subpatternId, bool capture, bool invert, int inputPos)
+        : type(type)
+        , m_capture(capture)
+        , m_invert(invert)
+    {
+        atom.subpatternId = subpatternId;
+        atom.quantityType = QuantifierFixedCount;
+        atom.quantityCount = 1;
+        inputPosition = inputPos;
+    }
+
+    static ByteTerm BOL(int inputPos)
+    {
+        ByteTerm term(TypeAssertionBOL);
+        term.inputPosition = inputPos;
+        return term;
+    }
+
+    static ByteTerm CheckInput(unsigned count)
+    {
+        ByteTerm term(TypeCheckInput);
+        term.checkInputCount = count;
+        return term;
+    }
+
+    static ByteTerm UncheckInput(unsigned count)
+    {
+        ByteTerm term(TypeUncheckInput);
+        term.checkInputCount = count;
+        return term;
+    }
+    
+    static ByteTerm EOL(int inputPos)
+    {
+        ByteTerm term(TypeAssertionEOL);
+        term.inputPosition = inputPos;
+        return term;
+    }
+
+    static ByteTerm WordBoundary(bool invert, int inputPos)
+    {
+        ByteTerm term(TypeAssertionWordBoundary, invert);
+        term.inputPosition = inputPos;
+        return term;
+    }
+    
+    static ByteTerm BackReference(unsigned subpatternId, int inputPos)
+    {
+        return ByteTerm(TypeBackReference, subpatternId, false, false, inputPos);
+    }
+
+    static ByteTerm BodyAlternativeBegin(bool onceThrough)
+    {
+        ByteTerm term(TypeBodyAlternativeBegin);
+        term.alternative.next = 0;
+        term.alternative.end = 0;
+        term.alternative.onceThrough = onceThrough;
+        return term;
+    }
+
+    static ByteTerm BodyAlternativeDisjunction(bool onceThrough)
+    {
+        ByteTerm term(TypeBodyAlternativeDisjunction);
+        term.alternative.next = 0;
+        term.alternative.end = 0;
+        term.alternative.onceThrough = onceThrough;
+        return term;
+    }
+
+    static ByteTerm BodyAlternativeEnd()
+    {
+        ByteTerm term(TypeBodyAlternativeEnd);
+        term.alternative.next = 0;
+        term.alternative.end = 0;
+        term.alternative.onceThrough = false;
+        return term;
+    }
+
+    static ByteTerm AlternativeBegin()
+    {
+        ByteTerm term(TypeAlternativeBegin);
+        term.alternative.next = 0;
+        term.alternative.end = 0;
+        term.alternative.onceThrough = false;
+        return term;
+    }
+
+    static ByteTerm AlternativeDisjunction()
+    {
+        ByteTerm term(TypeAlternativeDisjunction);
+        term.alternative.next = 0;
+        term.alternative.end = 0;
+        term.alternative.onceThrough = false;
+        return term;
+    }
+
+    static ByteTerm AlternativeEnd()
+    {
+        ByteTerm term(TypeAlternativeEnd);
+        term.alternative.next = 0;
+        term.alternative.end = 0;
+        term.alternative.onceThrough = false;
+        return term;
+    }
+
+    static ByteTerm SubpatternBegin()
+    {
+        return ByteTerm(TypeSubpatternBegin);
+    }
+
+    static ByteTerm SubpatternEnd()
+    {
+        return ByteTerm(TypeSubpatternEnd);
+    }
+    
+    static ByteTerm DotStarEnclosure(bool bolAnchor, bool eolAnchor)
+    {
+        ByteTerm term(TypeDotStarEnclosure);
+        term.anchors.m_bol = bolAnchor;
+        term.anchors.m_eol = eolAnchor;
+        return term;
+    }
+
+    bool invert()
+    {
+        return m_invert;
+    }
+
+    bool capture()
+    {
+        return m_capture;
+    }
+};
+
+class ByteDisjunction {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ByteDisjunction(unsigned numSubpatterns, unsigned frameSize)
+        : m_numSubpatterns(numSubpatterns)
+        , m_frameSize(frameSize)
+    {
+    }
+
+    Vector<ByteTerm> terms;
+    unsigned m_numSubpatterns;
+    unsigned m_frameSize;
+};
+
+struct BytecodePattern {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    BytecodePattern(PassOwnPtr<ByteDisjunction> body, Vector<ByteDisjunction*> allParenthesesInfo, YarrPattern& pattern, BumpPointerAllocator* allocator)
+        : m_body(body)
+        , m_ignoreCase(pattern.m_ignoreCase)
+        , m_multiline(pattern.m_multiline)
+        , m_allocator(allocator)
+    {
+        newlineCharacterClass = pattern.newlineCharacterClass();
+        wordcharCharacterClass = pattern.wordcharCharacterClass();
+
+        m_allParenthesesInfo.append(allParenthesesInfo);
+        m_userCharacterClasses.append(pattern.m_userCharacterClasses);
+        // 'Steal' the YarrPattern's CharacterClasses!  We clear its
+        // array, so that it won't delete them on destruction.  We'll
+        // take responsibility for that.
+        pattern.m_userCharacterClasses.clear();
+    }
+
+    ~BytecodePattern()
+    {
+        deleteAllValues(m_allParenthesesInfo);
+        deleteAllValues(m_userCharacterClasses);
+    }
+
+    OwnPtr<ByteDisjunction> m_body;
+    bool m_ignoreCase;
+    bool m_multiline;
+    // Each BytecodePattern is associated with a RegExp, each RegExp is associated
+    // with a JSGlobalData.  Cache a pointer to out JSGlobalData's m_regExpAllocator.
+    BumpPointerAllocator* m_allocator;
+
+    CharacterClass* newlineCharacterClass;
+    CharacterClass* wordcharCharacterClass;
+
+private:
+    Vector<ByteDisjunction*> m_allParenthesesInfo;
+    Vector<CharacterClass*> m_userCharacterClasses;
+};
+
+} } // namespace JSC::Yarr
+
+#endif // YarrInterpreter_h
diff --git a/yarr/YarrJIT.cpp b/yarr/YarrJIT.cpp
new file mode 100644 (file)
index 0000000..8d5344f
--- /dev/null
@@ -0,0 +1,2476 @@
+/*
+ * Copyright (C) 2009 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. 
+ */
+
+#include "config.h"
+#include "YarrJIT.h"
+
+#include "ASCIICType.h"
+#include "LinkBuffer.h"
+#include "Yarr.h"
+
+#if ENABLE(YARR_JIT)
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+class YarrGenerator : private MacroAssembler {
+    friend void jitCompile(JSGlobalData*, YarrCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
+
+#if CPU(ARM)
+    static const RegisterID input = ARMRegisters::r0;
+    static const RegisterID index = ARMRegisters::r1;
+    static const RegisterID length = ARMRegisters::r2;
+    static const RegisterID output = ARMRegisters::r4;
+
+    static const RegisterID regT0 = ARMRegisters::r5;
+    static const RegisterID regT1 = ARMRegisters::r6;
+
+    static const RegisterID returnRegister = ARMRegisters::r0;
+#elif CPU(MIPS)
+    static const RegisterID input = MIPSRegisters::a0;
+    static const RegisterID index = MIPSRegisters::a1;
+    static const RegisterID length = MIPSRegisters::a2;
+    static const RegisterID output = MIPSRegisters::a3;
+
+    static const RegisterID regT0 = MIPSRegisters::t4;
+    static const RegisterID regT1 = MIPSRegisters::t5;
+
+    static const RegisterID returnRegister = MIPSRegisters::v0;
+#elif CPU(SH4)
+    static const RegisterID input = SH4Registers::r4;
+    static const RegisterID index = SH4Registers::r5;
+    static const RegisterID length = SH4Registers::r6;
+    static const RegisterID output = SH4Registers::r7;
+
+    static const RegisterID regT0 = SH4Registers::r0;
+    static const RegisterID regT1 = SH4Registers::r1;
+
+    static const RegisterID returnRegister = SH4Registers::r0;
+#elif CPU(X86)
+    static const RegisterID input = X86Registers::eax;
+    static const RegisterID index = X86Registers::edx;
+    static const RegisterID length = X86Registers::ecx;
+    static const RegisterID output = X86Registers::edi;
+
+    static const RegisterID regT0 = X86Registers::ebx;
+    static const RegisterID regT1 = X86Registers::esi;
+
+    static const RegisterID returnRegister = X86Registers::eax;
+#elif CPU(X86_64)
+    static const RegisterID input = X86Registers::edi;
+    static const RegisterID index = X86Registers::esi;
+    static const RegisterID length = X86Registers::edx;
+    static const RegisterID output = X86Registers::ecx;
+
+    static const RegisterID regT0 = X86Registers::eax;
+    static const RegisterID regT1 = X86Registers::ebx;
+
+    static const RegisterID returnRegister = X86Registers::eax;
+#endif
+
+    void optimizeAlternative(PatternAlternative* alternative)
+    {
+        if (!alternative->m_terms.size())
+            return;
+
+        for (unsigned i = 0; i < alternative->m_terms.size() - 1; ++i) {
+            PatternTerm& term = alternative->m_terms[i];
+            PatternTerm& nextTerm = alternative->m_terms[i + 1];
+
+            if ((term.type == PatternTerm::TypeCharacterClass)
+                && (term.quantityType == QuantifierFixedCount)
+                && (nextTerm.type == PatternTerm::TypePatternCharacter)
+                && (nextTerm.quantityType == QuantifierFixedCount)) {
+                PatternTerm termCopy = term;
+                alternative->m_terms[i] = nextTerm;
+                alternative->m_terms[i + 1] = termCopy;
+            }
+        }
+    }
+
+    void matchCharacterClassRange(RegisterID character, JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount)
+    {
+        do {
+            // pick which range we're going to generate
+            int which = count >> 1;
+            char lo = ranges[which].begin;
+            char hi = ranges[which].end;
+
+            // check if there are any ranges or matches below lo.  If not, just jl to failure -
+            // if there is anything else to check, check that first, if it falls through jmp to failure.
+            if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
+                Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
+
+                // generate code for all ranges before this one
+                if (which)
+                    matchCharacterClassRange(character, failures, matchDest, ranges, which, matchIndex, matches, matchCount);
+
+                while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) {
+                    matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex])));
+                    ++*matchIndex;
+                }
+                failures.append(jump());
+
+                loOrAbove.link(this);
+            } else if (which) {
+                Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo));
+
+                matchCharacterClassRange(character, failures, matchDest, ranges, which, matchIndex, matches, matchCount);
+                failures.append(jump());
+
+                loOrAbove.link(this);
+            } else
+                failures.append(branch32(LessThan, character, Imm32((unsigned short)lo)));
+
+            while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi))
+                ++*matchIndex;
+
+            matchDest.append(branch32(LessThanOrEqual, character, Imm32((unsigned short)hi)));
+            // fall through to here, the value is above hi.
+
+            // shuffle along & loop around if there are any more matches to handle.
+            unsigned next = which + 1;
+            ranges += next;
+            count -= next;
+        } while (count);
+    }
+
+    void matchCharacterClass(RegisterID character, JumpList& matchDest, const CharacterClass* charClass)
+    {
+        if (charClass->m_table) {
+            ExtendedAddress tableEntry(character, reinterpret_cast<intptr_t>(charClass->m_table->m_table));
+            matchDest.append(branchTest8(charClass->m_table->m_inverted ? Zero : NonZero, tableEntry));
+            return;
+        }
+        Jump unicodeFail;
+        if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size()) {
+            Jump isAscii = branch32(LessThanOrEqual, character, TrustedImm32(0x7f));
+
+            if (charClass->m_matchesUnicode.size()) {
+                for (unsigned i = 0; i < charClass->m_matchesUnicode.size(); ++i) {
+                    UChar ch = charClass->m_matchesUnicode[i];
+                    matchDest.append(branch32(Equal, character, Imm32(ch)));
+                }
+            }
+
+            if (charClass->m_rangesUnicode.size()) {
+                for (unsigned i = 0; i < charClass->m_rangesUnicode.size(); ++i) {
+                    UChar lo = charClass->m_rangesUnicode[i].begin;
+                    UChar hi = charClass->m_rangesUnicode[i].end;
+
+                    Jump below = branch32(LessThan, character, Imm32(lo));
+                    matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi)));
+                    below.link(this);
+                }
+            }
+
+            unicodeFail = jump();
+            isAscii.link(this);
+        }
+
+        if (charClass->m_ranges.size()) {
+            unsigned matchIndex = 0;
+            JumpList failures;
+            matchCharacterClassRange(character, failures, matchDest, charClass->m_ranges.begin(), charClass->m_ranges.size(), &matchIndex, charClass->m_matches.begin(), charClass->m_matches.size());
+            while (matchIndex < charClass->m_matches.size())
+                matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass->m_matches[matchIndex++])));
+
+            failures.link(this);
+        } else if (charClass->m_matches.size()) {
+            // optimization: gather 'a','A' etc back together, can mask & test once.
+            Vector<char> matchesAZaz;
+
+            for (unsigned i = 0; i < charClass->m_matches.size(); ++i) {
+                char ch = charClass->m_matches[i];
+                if (m_pattern.m_ignoreCase) {
+                    if (isASCIILower(ch)) {
+                        matchesAZaz.append(ch);
+                        continue;
+                    }
+                    if (isASCIIUpper(ch))
+                        continue;
+                }
+                matchDest.append(branch32(Equal, character, Imm32((unsigned short)ch)));
+            }
+
+            if (unsigned countAZaz = matchesAZaz.size()) {
+                or32(TrustedImm32(32), character);
+                for (unsigned i = 0; i < countAZaz; ++i)
+                    matchDest.append(branch32(Equal, character, TrustedImm32(matchesAZaz[i])));
+            }
+        }
+
+        if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size())
+            unicodeFail.link(this);
+    }
+
+    // Jumps if input not available; will have (incorrectly) incremented already!
+    Jump jumpIfNoAvailableInput(unsigned countToCheck = 0)
+    {
+        if (countToCheck)
+            add32(Imm32(countToCheck), index);
+        return branch32(Above, index, length);
+    }
+
+    Jump jumpIfAvailableInput(unsigned countToCheck)
+    {
+        add32(Imm32(countToCheck), index);
+        return branch32(BelowOrEqual, index, length);
+    }
+
+    Jump checkInput()
+    {
+        return branch32(BelowOrEqual, index, length);
+    }
+
+    Jump atEndOfInput()
+    {
+        return branch32(Equal, index, length);
+    }
+
+    Jump notAtEndOfInput()
+    {
+        return branch32(NotEqual, index, length);
+    }
+
+    Jump jumpIfCharEquals(UChar ch, int inputPosition)
+    {
+        return branch16(Equal, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
+    }
+
+    Jump jumpIfCharNotEquals(UChar ch, int inputPosition)
+    {
+        return branch16(NotEqual, BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), Imm32(ch));
+    }
+
+    void readCharacter(int inputPosition, RegisterID reg)
+    {
+        load16(BaseIndex(input, index, TimesTwo, inputPosition * sizeof(UChar)), reg);
+    }
+
+    void storeToFrame(RegisterID reg, unsigned frameLocation)
+    {
+        poke(reg, frameLocation);
+    }
+
+    void storeToFrame(TrustedImm32 imm, unsigned frameLocation)
+    {
+        poke(imm, frameLocation);
+    }
+
+    DataLabelPtr storeToFrameWithPatch(unsigned frameLocation)
+    {
+        return storePtrWithPatch(TrustedImmPtr(0), Address(stackPointerRegister, frameLocation * sizeof(void*)));
+    }
+
+    void loadFromFrame(unsigned frameLocation, RegisterID reg)
+    {
+        peek(reg, frameLocation);
+    }
+
+    void loadFromFrameAndJump(unsigned frameLocation)
+    {
+        jump(Address(stackPointerRegister, frameLocation * sizeof(void*)));
+    }
+
+    enum YarrOpCode {
+        // These nodes wrap body alternatives - those in the main disjunction,
+        // rather than subpatterns or assertions. These are chained together in
+        // a doubly linked list, with a 'begin' node for the first alternative,
+        // a 'next' node for each subsequent alternative, and an 'end' node at
+        // the end. In the case of repeating alternatives, the 'end' node also
+        // has a reference back to 'begin'.
+        OpBodyAlternativeBegin,
+        OpBodyAlternativeNext,
+        OpBodyAlternativeEnd,
+        // Similar to the body alternatives, but used for subpatterns with two
+        // or more alternatives.
+        OpNestedAlternativeBegin,
+        OpNestedAlternativeNext,
+        OpNestedAlternativeEnd,
+        // Used for alternatives in subpatterns where there is only a single
+        // alternative (backtrackingis easier in these cases), or for alternatives
+        // which never need to be backtracked (those in parenthetical assertions,
+        // terminal subpatterns).
+        OpSimpleNestedAlternativeBegin,
+        OpSimpleNestedAlternativeNext,
+        OpSimpleNestedAlternativeEnd,
+        // Used to wrap 'Once' subpattern matches (quantityCount == 1).
+        OpParenthesesSubpatternOnceBegin,
+        OpParenthesesSubpatternOnceEnd,
+        // Used to wrap 'Terminal' subpattern matches (at the end of the regexp).
+        OpParenthesesSubpatternTerminalBegin,
+        OpParenthesesSubpatternTerminalEnd,
+        // Used to wrap parenthetical assertions.
+        OpParentheticalAssertionBegin,
+        OpParentheticalAssertionEnd,
+        // Wraps all simple terms (pattern characters, character classes).
+        OpTerm,
+        // Where an expression contains only 'once through' body alternatives
+        // and no repeating ones, this op is used to return match failure.
+        OpMatchFailed
+    };
+
+    // This structure is used to hold the compiled opcode information,
+    // including reference back to the original PatternTerm/PatternAlternatives,
+    // and JIT compilation data structures.
+    struct YarrOp {
+        explicit YarrOp(PatternTerm* term)
+            : m_op(OpTerm)
+            , m_term(term)
+            , m_isDeadCode(false)
+        {
+        }
+
+        explicit YarrOp(YarrOpCode op)
+            : m_op(op)
+            , m_isDeadCode(false)
+        {
+        }
+
+        // The operation, as a YarrOpCode, and also a reference to the PatternTerm.
+        YarrOpCode m_op;
+        PatternTerm* m_term;
+
+        // For alternatives, this holds the PatternAlternative and doubly linked
+        // references to this alternative's siblings. In the case of the
+        // OpBodyAlternativeEnd node at the end of a section of repeating nodes,
+        // m_nextOp will reference the OpBodyAlternativeBegin node of the first
+        // repeating alternative.
+        PatternAlternative* m_alternative;
+        size_t m_previousOp;
+        size_t m_nextOp;
+
+        // Used to record a set of Jumps out of the generated code, typically
+        // used for jumps out to backtracking code, and a single reentry back
+        // into the code for a node (likely where a backtrack will trigger
+        // rematching).
+        Label m_reentry;
+        JumpList m_jumps;
+
+        // This flag is used to null out the second pattern character, when
+        // two are fused to match a pair together.
+        bool m_isDeadCode;
+
+        // Currently used in the case of some of the more complex management of
+        // 'm_checked', to cache the offset used in this alternative, to avoid
+        // recalculating it.
+        int m_checkAdjust;
+
+        // Used by OpNestedAlternativeNext/End to hold the pointer to the
+        // value that will be pushed into the pattern's frame to return to,
+        // upon backtracking back into the disjunction.
+        DataLabelPtr m_returnAddress;
+    };
+
+    // BacktrackingState
+    // This class encapsulates information about the state of code generation
+    // whilst generating the code for backtracking, when a term fails to match.
+    // Upon entry to code generation of the backtracking code for a given node,
+    // the Backtracking state will hold references to all control flow sources
+    // that are outputs in need of further backtracking from the prior node
+    // generated (which is the subsequent operation in the regular expression,
+    // and in the m_ops Vector, since we generated backtracking backwards).
+    // These references to control flow take the form of:
+    //  - A jump list of jumps, to be linked to code that will backtrack them
+    //    further.
+    //  - A set of DataLabelPtr values, to be populated with values to be
+    //    treated effectively as return addresses backtracking into complex
+    //    subpatterns.
+    //  - A flag indicating that the current sequence of generated code up to
+    //    this point requires backtracking.
+    class BacktrackingState {
+    public:
+        BacktrackingState()
+            : m_pendingFallthrough(false)
+        {
+        }
+
+        // Add a jump or jumps, a return address, or set the flag indicating
+        // that the current 'fallthrough' control flow requires backtracking.
+        void append(const Jump& jump)
+        {
+            m_laterFailures.append(jump);
+        }
+        void append(JumpList& jumpList)
+        {
+            m_laterFailures.append(jumpList);
+        }
+        void append(const DataLabelPtr& returnAddress)
+        {
+            m_pendingReturns.append(returnAddress);
+        }
+        void fallthrough()
+        {
+            ASSERT(!m_pendingFallthrough);
+            m_pendingFallthrough = true;
+        }
+
+        // These methods clear the backtracking state, either linking to the
+        // current location, a provided label, or copying the backtracking out
+        // to a JumpList. All actions may require code generation to take place,
+        // and as such are passed a pointer to the assembler.
+        void link(MacroAssembler* assembler)
+        {
+            if (m_pendingReturns.size()) {
+                Label here(assembler);
+                for (unsigned i = 0; i < m_pendingReturns.size(); ++i)
+                    m_backtrackRecords.append(ReturnAddressRecord(m_pendingReturns[i], here));
+                m_pendingReturns.clear();
+            }
+            m_laterFailures.link(assembler);
+            m_laterFailures.clear();
+            m_pendingFallthrough = false;
+        }
+        void linkTo(Label label, MacroAssembler* assembler)
+        {
+            if (m_pendingReturns.size()) {
+                for (unsigned i = 0; i < m_pendingReturns.size(); ++i)
+                    m_backtrackRecords.append(ReturnAddressRecord(m_pendingReturns[i], label));
+                m_pendingReturns.clear();
+            }
+            if (m_pendingFallthrough)
+                assembler->jump(label);
+            m_laterFailures.linkTo(label, assembler);
+            m_laterFailures.clear();
+            m_pendingFallthrough = false;
+        }
+        void takeBacktracksToJumpList(JumpList& jumpList, MacroAssembler* assembler)
+        {
+            if (m_pendingReturns.size()) {
+                Label here(assembler);
+                for (unsigned i = 0; i < m_pendingReturns.size(); ++i)
+                    m_backtrackRecords.append(ReturnAddressRecord(m_pendingReturns[i], here));
+                m_pendingReturns.clear();
+                m_pendingFallthrough = true;
+            }
+            if (m_pendingFallthrough)
+                jumpList.append(assembler->jump());
+            jumpList.append(m_laterFailures);
+            m_laterFailures.clear();
+            m_pendingFallthrough = false;
+        }
+
+        bool isEmpty()
+        {
+            return m_laterFailures.empty() && m_pendingReturns.isEmpty() && !m_pendingFallthrough;
+        }
+
+        // Called at the end of code generation to link all return addresses.
+        void linkDataLabels(LinkBuffer& linkBuffer)
+        {
+            ASSERT(isEmpty());
+            for (unsigned i = 0; i < m_backtrackRecords.size(); ++i)
+                linkBuffer.patch(m_backtrackRecords[i].m_dataLabel, linkBuffer.locationOf(m_backtrackRecords[i].m_backtrackLocation));
+        }
+
+    private:
+        struct ReturnAddressRecord {
+            ReturnAddressRecord(DataLabelPtr dataLabel, Label backtrackLocation)
+                : m_dataLabel(dataLabel)
+                , m_backtrackLocation(backtrackLocation)
+            {
+            }
+
+            DataLabelPtr m_dataLabel;
+            Label m_backtrackLocation;
+        };
+
+        JumpList m_laterFailures;
+        bool m_pendingFallthrough;
+        Vector<DataLabelPtr, 4> m_pendingReturns;
+        Vector<ReturnAddressRecord, 4> m_backtrackRecords;
+    };
+
+    // Generation methods:
+    // ===================
+
+    // This method provides a default implementation of backtracking common
+    // to many terms; terms commonly jump out of the forwards  matching path
+    // on any failed conditions, and add these jumps to the m_jumps list. If
+    // no special handling is required we can often just backtrack to m_jumps.
+    void backtrackTermDefault(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        m_backtrackingState.append(op.m_jumps);
+    }
+
+    void generateAssertionBOL(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        if (m_pattern.m_multiline) {
+            const RegisterID character = regT0;
+
+            JumpList matchDest;
+            if (!term->inputPosition)
+                matchDest.append(branch32(Equal, index, Imm32(m_checked)));
+
+            readCharacter((term->inputPosition - m_checked) - 1, character);
+            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
+            op.m_jumps.append(jump());
+
+            matchDest.link(this);
+        } else {
+            // Erk, really should poison out these alternatives early. :-/
+            if (term->inputPosition)
+                op.m_jumps.append(jump());
+            else
+                op.m_jumps.append(branch32(NotEqual, index, Imm32(m_checked)));
+        }
+    }
+    void backtrackAssertionBOL(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    void generateAssertionEOL(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        if (m_pattern.m_multiline) {
+            const RegisterID character = regT0;
+
+            JumpList matchDest;
+            if (term->inputPosition == m_checked)
+                matchDest.append(atEndOfInput());
+
+            readCharacter((term->inputPosition - m_checked), character);
+            matchCharacterClass(character, matchDest, m_pattern.newlineCharacterClass());
+            op.m_jumps.append(jump());
+
+            matchDest.link(this);
+        } else {
+            if (term->inputPosition == m_checked)
+                op.m_jumps.append(notAtEndOfInput());
+            // Erk, really should poison out these alternatives early. :-/
+            else
+                op.m_jumps.append(jump());
+        }
+    }
+    void backtrackAssertionEOL(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    // Also falls though on nextIsNotWordChar.
+    void matchAssertionWordchar(size_t opIndex, JumpList& nextIsWordChar, JumpList& nextIsNotWordChar)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+
+        if (term->inputPosition == m_checked)
+            nextIsNotWordChar.append(atEndOfInput());
+
+        readCharacter((term->inputPosition - m_checked), character);
+        matchCharacterClass(character, nextIsWordChar, m_pattern.wordcharCharacterClass());
+    }
+
+    void generateAssertionWordBoundary(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+
+        Jump atBegin;
+        JumpList matchDest;
+        if (!term->inputPosition)
+            atBegin = branch32(Equal, index, Imm32(m_checked));
+        readCharacter((term->inputPosition - m_checked) - 1, character);
+        matchCharacterClass(character, matchDest, m_pattern.wordcharCharacterClass());
+        if (!term->inputPosition)
+            atBegin.link(this);
+
+        // We fall through to here if the last character was not a wordchar.
+        JumpList nonWordCharThenWordChar;
+        JumpList nonWordCharThenNonWordChar;
+        if (term->invert()) {
+            matchAssertionWordchar(opIndex, nonWordCharThenNonWordChar, nonWordCharThenWordChar);
+            nonWordCharThenWordChar.append(jump());
+        } else {
+            matchAssertionWordchar(opIndex, nonWordCharThenWordChar, nonWordCharThenNonWordChar);
+            nonWordCharThenNonWordChar.append(jump());
+        }
+        op.m_jumps.append(nonWordCharThenNonWordChar);
+
+        // We jump here if the last character was a wordchar.
+        matchDest.link(this);
+        JumpList wordCharThenWordChar;
+        JumpList wordCharThenNonWordChar;
+        if (term->invert()) {
+            matchAssertionWordchar(opIndex, wordCharThenNonWordChar, wordCharThenWordChar);
+            wordCharThenWordChar.append(jump());
+        } else {
+            matchAssertionWordchar(opIndex, wordCharThenWordChar, wordCharThenNonWordChar);
+            // This can fall-though!
+        }
+
+        op.m_jumps.append(wordCharThenWordChar);
+
+        nonWordCharThenWordChar.link(this);
+        wordCharThenNonWordChar.link(this);
+    }
+    void backtrackAssertionWordBoundary(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    void generatePatternCharacterOnce(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+
+        // m_ops always ends with a OpBodyAlternativeEnd or OpMatchFailed
+        // node, so there must always be at least one more node.
+        ASSERT(opIndex + 1 < m_ops.size());
+        YarrOp& nextOp = m_ops[opIndex + 1];
+
+        if (op.m_isDeadCode)
+            return;
+
+        PatternTerm* term = op.m_term;
+        UChar ch = term->patternCharacter;
+
+        const RegisterID character = regT0;
+
+        if (nextOp.m_op == OpTerm) {
+            PatternTerm* nextTerm = nextOp.m_term;
+            if (nextTerm->type == PatternTerm::TypePatternCharacter
+                && nextTerm->quantityType == QuantifierFixedCount
+                && nextTerm->quantityCount == 1
+                && nextTerm->inputPosition == (term->inputPosition + 1)) {
+
+                UChar ch2 = nextTerm->patternCharacter;
+
+                int mask = 0;
+                int chPair = ch | (ch2 << 16);
+
+                if (m_pattern.m_ignoreCase) {
+                    if (isASCIIAlpha(ch))
+                        mask |= 32;
+                    if (isASCIIAlpha(ch2))
+                        mask |= 32 << 16;
+                }
+
+                BaseIndex address(input, index, TimesTwo, (term->inputPosition - m_checked) * sizeof(UChar));
+                if (mask) {
+                    load32WithUnalignedHalfWords(address, character);
+                    or32(Imm32(mask), character);
+                    op.m_jumps.append(branch32(NotEqual, character, Imm32(chPair | mask)));
+                } else
+                    op.m_jumps.append(branch32WithUnalignedHalfWords(NotEqual, address, Imm32(chPair)));
+
+                nextOp.m_isDeadCode = true;
+                return;
+            }
+        }
+
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+            readCharacter(term->inputPosition - m_checked, character);
+            or32(TrustedImm32(32), character);
+            op.m_jumps.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
+        } else {
+            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+            op.m_jumps.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked));
+        }
+    }
+    void backtrackPatternCharacterOnce(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    void generatePatternCharacterFixed(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+        UChar ch = term->patternCharacter;
+
+        const RegisterID character = regT0;
+        const RegisterID countRegister = regT1;
+
+        move(index, countRegister);
+        sub32(Imm32(term->quantityCount), countRegister);
+
+        Label loop(this);
+        BaseIndex address(input, countRegister, TimesTwo, (term->inputPosition - m_checked + term->quantityCount) * sizeof(UChar));
+
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+            load16(address, character);
+            or32(TrustedImm32(32), character);
+            op.m_jumps.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
+        } else {
+            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+            op.m_jumps.append(branch16(NotEqual, address, Imm32(ch)));
+        }
+        add32(TrustedImm32(1), countRegister);
+        branch32(NotEqual, countRegister, index).linkTo(loop, this);
+    }
+    void backtrackPatternCharacterFixed(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    void generatePatternCharacterGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+        UChar ch = term->patternCharacter;
+
+        const RegisterID character = regT0;
+        const RegisterID countRegister = regT1;
+
+        move(TrustedImm32(0), countRegister);
+
+        JumpList failures;
+        Label loop(this);
+        failures.append(atEndOfInput());
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+            readCharacter(term->inputPosition - m_checked, character);
+            or32(TrustedImm32(32), character);
+            failures.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
+        } else {
+            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+            failures.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked));
+        }
+
+        add32(TrustedImm32(1), countRegister);
+        add32(TrustedImm32(1), index);
+        if (term->quantityCount == quantifyInfinite)
+            jump(loop);
+        else
+            branch32(NotEqual, countRegister, Imm32(term->quantityCount)).linkTo(loop, this);
+
+        failures.link(this);
+        op.m_reentry = label();
+
+        storeToFrame(countRegister, term->frameLocation);
+
+    }
+    void backtrackPatternCharacterGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID countRegister = regT1;
+
+        m_backtrackingState.link(this);
+
+        loadFromFrame(term->frameLocation, countRegister);
+        m_backtrackingState.append(branchTest32(Zero, countRegister));
+        sub32(TrustedImm32(1), countRegister);
+        sub32(TrustedImm32(1), index);
+        jump(op.m_reentry);
+    }
+
+    void generatePatternCharacterNonGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID countRegister = regT1;
+
+        move(TrustedImm32(0), countRegister);
+        op.m_reentry = label();
+        storeToFrame(countRegister, term->frameLocation);
+    }
+    void backtrackPatternCharacterNonGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+        UChar ch = term->patternCharacter;
+
+        const RegisterID character = regT0;
+        const RegisterID countRegister = regT1;
+
+        JumpList nonGreedyFailures;
+
+        m_backtrackingState.link(this);
+
+        loadFromFrame(term->frameLocation, countRegister);
+
+        nonGreedyFailures.append(atEndOfInput());
+        if (term->quantityCount != quantifyInfinite)
+            nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount)));
+        if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) {
+            readCharacter(term->inputPosition - m_checked, character);
+            or32(TrustedImm32(32), character);
+            nonGreedyFailures.append(branch32(NotEqual, character, Imm32(Unicode::toLower(ch))));
+        } else {
+            ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch)));
+            nonGreedyFailures.append(jumpIfCharNotEquals(ch, term->inputPosition - m_checked));
+        }
+
+        add32(TrustedImm32(1), countRegister);
+        add32(TrustedImm32(1), index);
+
+        jump(op.m_reentry);
+
+        nonGreedyFailures.link(this);
+        sub32(countRegister, index);
+        m_backtrackingState.fallthrough();
+    }
+
+    void generateCharacterClassOnce(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+
+        JumpList matchDest;
+        readCharacter((term->inputPosition - m_checked), character);
+        matchCharacterClass(character, matchDest, term->characterClass);
+
+        if (term->invert())
+            op.m_jumps.append(matchDest);
+        else {
+            op.m_jumps.append(jump());
+            matchDest.link(this);
+        }
+    }
+    void backtrackCharacterClassOnce(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    void generateCharacterClassFixed(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+        const RegisterID countRegister = regT1;
+
+        move(index, countRegister);
+        sub32(Imm32(term->quantityCount), countRegister);
+
+        Label loop(this);
+        JumpList matchDest;
+        load16(BaseIndex(input, countRegister, TimesTwo, (term->inputPosition - m_checked + term->quantityCount) * sizeof(UChar)), character);
+        matchCharacterClass(character, matchDest, term->characterClass);
+
+        if (term->invert())
+            op.m_jumps.append(matchDest);
+        else {
+            op.m_jumps.append(jump());
+            matchDest.link(this);
+        }
+
+        add32(TrustedImm32(1), countRegister);
+        branch32(NotEqual, countRegister, index).linkTo(loop, this);
+    }
+    void backtrackCharacterClassFixed(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+
+    void generateCharacterClassGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+        const RegisterID countRegister = regT1;
+
+        move(TrustedImm32(0), countRegister);
+
+        JumpList failures;
+        Label loop(this);
+        failures.append(atEndOfInput());
+
+        if (term->invert()) {
+            readCharacter(term->inputPosition - m_checked, character);
+            matchCharacterClass(character, failures, term->characterClass);
+        } else {
+            JumpList matchDest;
+            readCharacter(term->inputPosition - m_checked, character);
+            matchCharacterClass(character, matchDest, term->characterClass);
+            failures.append(jump());
+            matchDest.link(this);
+        }
+
+        add32(TrustedImm32(1), countRegister);
+        add32(TrustedImm32(1), index);
+        if (term->quantityCount != quantifyInfinite) {
+            branch32(NotEqual, countRegister, Imm32(term->quantityCount)).linkTo(loop, this);
+            failures.append(jump());
+        } else
+            jump(loop);
+
+        failures.link(this);
+        op.m_reentry = label();
+
+        storeToFrame(countRegister, term->frameLocation);
+    }
+    void backtrackCharacterClassGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID countRegister = regT1;
+
+        m_backtrackingState.link(this);
+
+        loadFromFrame(term->frameLocation, countRegister);
+        m_backtrackingState.append(branchTest32(Zero, countRegister));
+        sub32(TrustedImm32(1), countRegister);
+        sub32(TrustedImm32(1), index);
+        jump(op.m_reentry);
+    }
+
+    void generateCharacterClassNonGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID countRegister = regT1;
+
+        move(TrustedImm32(0), countRegister);
+        op.m_reentry = label();
+        storeToFrame(countRegister, term->frameLocation);
+    }
+    void backtrackCharacterClassNonGreedy(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+        const RegisterID countRegister = regT1;
+
+        JumpList nonGreedyFailures;
+
+        m_backtrackingState.link(this);
+
+        Label backtrackBegin(this);
+        loadFromFrame(term->frameLocation, countRegister);
+
+        nonGreedyFailures.append(atEndOfInput());
+        nonGreedyFailures.append(branch32(Equal, countRegister, Imm32(term->quantityCount)));
+
+        JumpList matchDest;
+        readCharacter(term->inputPosition - m_checked, character);
+        matchCharacterClass(character, matchDest, term->characterClass);
+
+        if (term->invert())
+            nonGreedyFailures.append(matchDest);
+        else {
+            nonGreedyFailures.append(jump());
+            matchDest.link(this);
+        }
+
+        add32(TrustedImm32(1), countRegister);
+        add32(TrustedImm32(1), index);
+
+        jump(op.m_reentry);
+
+        nonGreedyFailures.link(this);
+        sub32(countRegister, index);
+        m_backtrackingState.fallthrough();
+    }
+
+    void generateDotStarEnclosure(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        const RegisterID character = regT0;
+        const RegisterID matchPos = regT1;
+
+        JumpList foundBeginningNewLine;
+        JumpList saveStartIndex;
+        JumpList foundEndingNewLine;
+
+        if (m_pattern.m_body->m_hasFixedSize) {
+            move(index, matchPos);
+            sub32(Imm32(m_checked), matchPos);
+        } else
+            load32(Address(output), matchPos);
+
+        saveStartIndex.append(branchTest32(Zero, matchPos));
+        Label findBOLLoop(this);
+        sub32(TrustedImm32(1), matchPos);
+        load16(BaseIndex(input, matchPos, TimesTwo, 0), character);
+        matchCharacterClass(character, foundBeginningNewLine, m_pattern.newlineCharacterClass());
+        branchTest32(NonZero, matchPos).linkTo(findBOLLoop, this);
+        saveStartIndex.append(jump());
+
+        foundBeginningNewLine.link(this);
+        add32(TrustedImm32(1), matchPos); // Advance past newline
+        saveStartIndex.link(this);
+
+        if (!m_pattern.m_multiline && term->anchors.bolAnchor)
+            op.m_jumps.append(branchTest32(NonZero, matchPos));
+
+        store32(matchPos, Address(output));
+
+        move(index, matchPos);
+
+        Label findEOLLoop(this);        
+        foundEndingNewLine.append(branch32(Equal, matchPos, length));
+        load16(BaseIndex(input, matchPos, TimesTwo, 0), character);
+        matchCharacterClass(character, foundEndingNewLine, m_pattern.newlineCharacterClass());
+        add32(TrustedImm32(1), matchPos);
+        jump(findEOLLoop);
+
+        foundEndingNewLine.link(this);
+
+        if (!m_pattern.m_multiline && term->anchors.eolAnchor)
+            op.m_jumps.append(branch32(NotEqual, matchPos, length));
+
+        move(matchPos, index);
+    }
+
+    void backtrackDotStarEnclosure(size_t opIndex)
+    {
+        backtrackTermDefault(opIndex);
+    }
+    
+    // Code generation/backtracking for simple terms
+    // (pattern characters, character classes, and assertions).
+    // These methods farm out work to the set of functions above.
+    void generateTerm(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        switch (term->type) {
+        case PatternTerm::TypePatternCharacter:
+            switch (term->quantityType) {
+            case QuantifierFixedCount:
+                if (term->quantityCount == 1)
+                    generatePatternCharacterOnce(opIndex);
+                else
+                    generatePatternCharacterFixed(opIndex);
+                break;
+            case QuantifierGreedy:
+                generatePatternCharacterGreedy(opIndex);
+                break;
+            case QuantifierNonGreedy:
+                generatePatternCharacterNonGreedy(opIndex);
+                break;
+            }
+            break;
+
+        case PatternTerm::TypeCharacterClass:
+            switch (term->quantityType) {
+            case QuantifierFixedCount:
+                if (term->quantityCount == 1)
+                    generateCharacterClassOnce(opIndex);
+                else
+                    generateCharacterClassFixed(opIndex);
+                break;
+            case QuantifierGreedy:
+                generateCharacterClassGreedy(opIndex);
+                break;
+            case QuantifierNonGreedy:
+                generateCharacterClassNonGreedy(opIndex);
+                break;
+            }
+            break;
+
+        case PatternTerm::TypeAssertionBOL:
+            generateAssertionBOL(opIndex);
+            break;
+
+        case PatternTerm::TypeAssertionEOL:
+            generateAssertionEOL(opIndex);
+            break;
+
+        case PatternTerm::TypeAssertionWordBoundary:
+            generateAssertionWordBoundary(opIndex);
+            break;
+
+        case PatternTerm::TypeForwardReference:
+            break;
+
+        case PatternTerm::TypeParenthesesSubpattern:
+        case PatternTerm::TypeParentheticalAssertion:
+            ASSERT_NOT_REACHED();
+        case PatternTerm::TypeBackReference:
+            m_shouldFallBack = true;
+            break;
+        case PatternTerm::TypeDotStarEnclosure:
+            generateDotStarEnclosure(opIndex);
+            break;
+        }
+    }
+    void backtrackTerm(size_t opIndex)
+    {
+        YarrOp& op = m_ops[opIndex];
+        PatternTerm* term = op.m_term;
+
+        switch (term->type) {
+        case PatternTerm::TypePatternCharacter:
+            switch (term->quantityType) {
+            case QuantifierFixedCount:
+                if (term->quantityCount == 1)
+                    backtrackPatternCharacterOnce(opIndex);
+                else
+                    backtrackPatternCharacterFixed(opIndex);
+                break;
+            case QuantifierGreedy:
+                backtrackPatternCharacterGreedy(opIndex);
+                break;
+            case QuantifierNonGreedy:
+                backtrackPatternCharacterNonGreedy(opIndex);
+                break;
+            }
+            break;
+
+        case PatternTerm::TypeCharacterClass:
+            switch (term->quantityType) {
+            case QuantifierFixedCount:
+                if (term->quantityCount == 1)
+                    backtrackCharacterClassOnce(opIndex);
+                else
+                    backtrackCharacterClassFixed(opIndex);
+                break;
+            case QuantifierGreedy:
+                backtrackCharacterClassGreedy(opIndex);
+                break;
+            case QuantifierNonGreedy:
+                backtrackCharacterClassNonGreedy(opIndex);
+                break;
+            }
+            break;
+
+        case PatternTerm::TypeAssertionBOL:
+            backtrackAssertionBOL(opIndex);
+            break;
+
+        case PatternTerm::TypeAssertionEOL:
+            backtrackAssertionEOL(opIndex);
+            break;
+
+        case PatternTerm::TypeAssertionWordBoundary:
+            backtrackAssertionWordBoundary(opIndex);
+            break;
+
+        case PatternTerm::TypeForwardReference:
+            break;
+
+        case PatternTerm::TypeParenthesesSubpattern:
+        case PatternTerm::TypeParentheticalAssertion:
+            ASSERT_NOT_REACHED();
+
+        case PatternTerm::TypeDotStarEnclosure:
+            backtrackDotStarEnclosure(opIndex);
+            break;
+
+        case PatternTerm::TypeBackReference:
+            m_shouldFallBack = true;
+            break;
+        }
+    }
+
+    void generate()
+    {
+        // Forwards generate the matching code.
+        ASSERT(m_ops.size());
+        size_t opIndex = 0;
+
+        do {
+            YarrOp& op = m_ops[opIndex];
+            switch (op.m_op) {
+
+            case OpTerm:
+                generateTerm(opIndex);
+                break;
+
+            // OpBodyAlternativeBegin/Next/End
+            //
+            // These nodes wrap the set of alternatives in the body of the regular expression.
+            // There may be either one or two chains of OpBodyAlternative nodes, one representing
+            // the 'once through' sequence of alternatives (if any exist), and one representing
+            // the repeating alternatives (again, if any exist).
+            //
+            // Upon normal entry to the Begin alternative, we will check that input is available.
+            // Reentry to the Begin alternative will take place after the check has taken place,
+            // and will assume that the input position has already been progressed as appropriate.
+            //
+            // Entry to subsequent Next/End alternatives occurs when the prior alternative has
+            // successfully completed a match - return a success state from JIT code.
+            //
+            // Next alternatives allow for reentry optimized to suit backtracking from its
+            // preceding alternative. It expects the input position to still be set to a position
+            // appropriate to its predecessor, and it will only perform an input check if the
+            // predecessor had a minimum size less than its own.
+            //
+            // In the case 'once through' expressions, the End node will also have a reentry
+            // point to jump to when the last alternative fails. Again, this expects the input
+            // position to still reflect that expected by the prior alternative.
+            case OpBodyAlternativeBegin: {
+                PatternAlternative* alternative = op.m_alternative;
+
+                // Upon entry at the head of the set of alternatives, check if input is available
+                // to run the first alternative. (This progresses the input position).
+                op.m_jumps.append(jumpIfNoAvailableInput(alternative->m_minimumSize));
+                // We will reenter after the check, and assume the input position to have been
+                // set as appropriate to this alternative.
+                op.m_reentry = label();
+
+                m_checked += alternative->m_minimumSize;
+                break;
+            }
+            case OpBodyAlternativeNext:
+            case OpBodyAlternativeEnd: {
+                PatternAlternative* priorAlternative = m_ops[op.m_previousOp].m_alternative;
+                PatternAlternative* alternative = op.m_alternative;
+
+                // If we get here, the prior alternative matched - return success.
+                
+                // Adjust the stack pointer to remove the pattern's frame.
+                if (m_pattern.m_body->m_callFrameSize)
+                    addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+
+                // Load appropriate values into the return register and the first output
+                // slot, and return. In the case of pattern with a fixed size, we will
+                // not have yet set the value in the first 
+                ASSERT(index != returnRegister);
+                if (m_pattern.m_body->m_hasFixedSize) {
+                    move(index, returnRegister);
+                    if (priorAlternative->m_minimumSize)
+                        sub32(Imm32(priorAlternative->m_minimumSize), returnRegister);
+                    store32(returnRegister, output);
+                } else
+                    load32(Address(output), returnRegister);
+                store32(index, Address(output, 4));
+                generateReturn();
+
+                // This is the divide between the tail of the prior alternative, above, and
+                // the head of the subsequent alternative, below.
+
+                if (op.m_op == OpBodyAlternativeNext) {
+                    // This is the reentry point for the Next alternative. We expect any code
+                    // that jumps here to do so with the input position matching that of the
+                    // PRIOR alteranative, and we will only check input availability if we
+                    // need to progress it forwards.
+                    op.m_reentry = label();
+                    if (alternative->m_minimumSize > priorAlternative->m_minimumSize) {
+                        add32(Imm32(alternative->m_minimumSize - priorAlternative->m_minimumSize), index);
+                        op.m_jumps.append(jumpIfNoAvailableInput());
+                    } else if (priorAlternative->m_minimumSize > alternative->m_minimumSize)
+                        sub32(Imm32(priorAlternative->m_minimumSize - alternative->m_minimumSize), index);
+                } else if (op.m_nextOp == notFound) {
+                    // This is the reentry point for the End of 'once through' alternatives,
+                    // jumped to when the las alternative fails to match.
+                    op.m_reentry = label();
+                    sub32(Imm32(priorAlternative->m_minimumSize), index);
+                }
+
+                if (op.m_op == OpBodyAlternativeNext)
+                    m_checked += alternative->m_minimumSize;
+                m_checked -= priorAlternative->m_minimumSize;
+                break;
+            }
+
+            // OpSimpleNestedAlternativeBegin/Next/End
+            // OpNestedAlternativeBegin/Next/End
+            //
+            // These nodes are used to handle sets of alternatives that are nested within
+            // subpatterns and parenthetical assertions. The 'simple' forms are used where
+            // we do not need to be able to backtrack back into any alternative other than
+            // the last, the normal forms allow backtracking into any alternative.
+            //
+            // Each Begin/Next node is responsible for planting an input check to ensure
+            // sufficient input is available on entry. Next nodes additionally need to
+            // jump to the end - Next nodes use the End node's m_jumps list to hold this
+            // set of jumps.
+            //
+            // In the non-simple forms, successful alternative matches must store a
+            // 'return address' using a DataLabelPtr, used to store the address to jump
+            // to when backtracking, to get to the code for the appropriate alternative.
+            case OpSimpleNestedAlternativeBegin:
+            case OpNestedAlternativeBegin: {
+                PatternTerm* term = op.m_term;
+                PatternAlternative* alternative = op.m_alternative;
+                PatternDisjunction* disjunction = term->parentheses.disjunction;
+
+                // Calculate how much input we need to check for, and if non-zero check.
+                op.m_checkAdjust = alternative->m_minimumSize;
+                if ((term->quantityType == QuantifierFixedCount) && (term->type != PatternTerm::TypeParentheticalAssertion))
+                    op.m_checkAdjust -= disjunction->m_minimumSize;
+                if (op.m_checkAdjust)
+                    op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust));
+                m_checked += op.m_checkAdjust;
+                break;
+            }
+            case OpSimpleNestedAlternativeNext:
+            case OpNestedAlternativeNext: {
+                PatternTerm* term = op.m_term;
+                PatternAlternative* alternative = op.m_alternative;
+                PatternDisjunction* disjunction = term->parentheses.disjunction;
+
+                // In the non-simple case, store a 'return address' so we can backtrack correctly.
+                if (op.m_op == OpNestedAlternativeNext) {
+                    unsigned parenthesesFrameLocation = term->frameLocation;
+                    unsigned alternativeFrameLocation = parenthesesFrameLocation;
+                    if (term->quantityType != QuantifierFixedCount)
+                        alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
+                    op.m_returnAddress = storeToFrameWithPatch(alternativeFrameLocation);
+                }
+
+                // If we reach here then the last alternative has matched - jump to the
+                // End node, to skip over any further alternatives.
+                //
+                // FIXME: this is logically O(N^2) (though N can be expected to be very
+                // small). We could avoid this either by adding an extra jump to the JIT
+                // data structures, or by making backtracking code that jumps to Next
+                // alternatives are responsible for checking that input is available (if
+                // we didn't need to plant the input checks, then m_jumps would be free).
+                YarrOp* endOp = &m_ops[op.m_nextOp];
+                while (endOp->m_nextOp != notFound) {
+                    ASSERT(endOp->m_op == OpSimpleNestedAlternativeNext || endOp->m_op == OpNestedAlternativeNext);
+                    endOp = &m_ops[endOp->m_nextOp];
+                }
+                ASSERT(endOp->m_op == OpSimpleNestedAlternativeEnd || endOp->m_op == OpNestedAlternativeEnd);
+                endOp->m_jumps.append(jump());
+
+                // This is the entry point for the next alternative.
+                op.m_reentry = label();
+
+                // Calculate how much input we need to check for, and if non-zero check.
+                op.m_checkAdjust = alternative->m_minimumSize;
+                if ((term->quantityType == QuantifierFixedCount) && (term->type != PatternTerm::TypeParentheticalAssertion))
+                    op.m_checkAdjust -= disjunction->m_minimumSize;
+                if (op.m_checkAdjust)
+                    op.m_jumps.append(jumpIfNoAvailableInput(op.m_checkAdjust));
+
+                YarrOp& lastOp = m_ops[op.m_previousOp];
+                m_checked -= lastOp.m_checkAdjust;
+                m_checked += op.m_checkAdjust;
+                break;
+            }
+            case OpSimpleNestedAlternativeEnd:
+            case OpNestedAlternativeEnd: {
+                PatternTerm* term = op.m_term;
+
+                // In the non-simple case, store a 'return address' so we can backtrack correctly.
+                if (op.m_op == OpNestedAlternativeEnd) {
+                    unsigned parenthesesFrameLocation = term->frameLocation;
+                    unsigned alternativeFrameLocation = parenthesesFrameLocation;
+                    if (term->quantityType != QuantifierFixedCount)
+                        alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
+                    op.m_returnAddress = storeToFrameWithPatch(alternativeFrameLocation);
+                }
+
+                // If this set of alternatives contains more than one alternative,
+                // then the Next nodes will have planted jumps to the End, and added
+                // them to this node's m_jumps list.
+                op.m_jumps.link(this);
+                op.m_jumps.clear();
+
+                YarrOp& lastOp = m_ops[op.m_previousOp];
+                m_checked -= lastOp.m_checkAdjust;
+                break;
+            }
+
+            // OpParenthesesSubpatternOnceBegin/End
+            //
+            // These nodes support (optionally) capturing subpatterns, that have a
+            // quantity count of 1 (this covers fixed once, and ?/?? quantifiers). 
+            case OpParenthesesSubpatternOnceBegin: {
+                PatternTerm* term = op.m_term;
+                unsigned parenthesesFrameLocation = term->frameLocation;
+                const RegisterID indexTemporary = regT0;
+                ASSERT(term->quantityCount == 1);
+
+                // Upon entry to a Greedy quantified set of parenthese store the index.
+                // We'll use this for two purposes:
+                //  - To indicate which iteration we are on of mathing the remainder of
+                //    the expression after the parentheses - the first, including the
+                //    match within the parentheses, or the second having skipped over them.
+                //  - To check for empty matches, which must be rejected.
+                //
+                // At the head of a NonGreedy set of parentheses we'll immediately set the
+                // value on the stack to -1 (indicating a match skipping the subpattern),
+                // and plant a jump to the end. We'll also plant a label to backtrack to
+                // to reenter the subpattern later, with a store to set up index on the
+                // second iteration.
+                //
+                // FIXME: for capturing parens, could use the index in the capture array?
+                if (term->quantityType == QuantifierGreedy)
+                    storeToFrame(index, parenthesesFrameLocation);
+                else if (term->quantityType == QuantifierNonGreedy) {
+                    storeToFrame(TrustedImm32(-1), parenthesesFrameLocation);
+                    op.m_jumps.append(jump());
+                    op.m_reentry = label();
+                    storeToFrame(index, parenthesesFrameLocation);
+                }
+
+                // If the parenthese are capturing, store the starting index value to the
+                // captures array, offsetting as necessary.
+                //
+                // FIXME: could avoid offsetting this value in JIT code, apply
+                // offsets only afterwards, at the point the results array is
+                // being accessed.
+                if (term->capture()) {
+                    int offsetId = term->parentheses.subpatternId << 1;
+                    int inputOffset = term->inputPosition - m_checked;
+                    if (term->quantityType == QuantifierFixedCount)
+                        inputOffset -= term->parentheses.disjunction->m_minimumSize;
+                    if (inputOffset) {
+                        move(index, indexTemporary);
+                        add32(Imm32(inputOffset), indexTemporary);
+                        store32(indexTemporary, Address(output, offsetId * sizeof(int)));
+                    } else
+                        store32(index, Address(output, offsetId * sizeof(int)));
+                }
+                break;
+            }
+            case OpParenthesesSubpatternOnceEnd: {
+                PatternTerm* term = op.m_term;
+                unsigned parenthesesFrameLocation = term->frameLocation;
+                const RegisterID indexTemporary = regT0;
+                ASSERT(term->quantityCount == 1);
+
+                // For Greedy/NonGreedy quantified parentheses, we must reject zero length
+                // matches. If the minimum size is know to be non-zero we need not check.
+                if (term->quantityType != QuantifierFixedCount && !term->parentheses.disjunction->m_minimumSize)
+                    op.m_jumps.append(branch32(Equal, index, Address(stackPointerRegister, parenthesesFrameLocation * sizeof(void*))));
+
+                // If the parenthese are capturing, store the ending index value to the
+                // captures array, offsetting as necessary.
+                //
+                // FIXME: could avoid offsetting this value in JIT code, apply
+                // offsets only afterwards, at the point the results array is
+                // being accessed.
+                if (term->capture()) {
+                    int offsetId = (term->parentheses.subpatternId << 1) + 1;
+                    int inputOffset = term->inputPosition - m_checked;
+                    if (inputOffset) {
+                        move(index, indexTemporary);
+                        add32(Imm32(inputOffset), indexTemporary);
+                        store32(indexTemporary, Address(output, offsetId * sizeof(int)));
+                    } else
+                        store32(index, Address(output, offsetId * sizeof(int)));
+                }
+
+                // If the parentheses are quantified Greedy then add a label to jump back
+                // to if get a failed match from after the parentheses. For NonGreedy
+                // parentheses, link the jump from before the subpattern to here.
+                if (term->quantityType == QuantifierGreedy)
+                    op.m_reentry = label();
+                else if (term->quantityType == QuantifierNonGreedy) {
+                    YarrOp& beginOp = m_ops[op.m_previousOp];
+                    beginOp.m_jumps.link(this);
+                }
+                break;
+            }
+
+            // OpParenthesesSubpatternTerminalBegin/End
+            case OpParenthesesSubpatternTerminalBegin: {
+                PatternTerm* term = op.m_term;
+                ASSERT(term->quantityType == QuantifierGreedy);
+                ASSERT(term->quantityCount == quantifyInfinite);
+                ASSERT(!term->capture());
+
+                // Upon entry set a label to loop back to.
+                op.m_reentry = label();
+
+                // Store the start index of the current match; we need to reject zero
+                // length matches.
+                storeToFrame(index, term->frameLocation);
+                break;
+            }
+            case OpParenthesesSubpatternTerminalEnd: {
+                PatternTerm* term = op.m_term;
+
+                // Check for zero length matches - if the match is non-zero, then we
+                // can accept it & loop back up to the head of the subpattern.
+                YarrOp& beginOp = m_ops[op.m_previousOp];
+                branch32(NotEqual, index, Address(stackPointerRegister, term->frameLocation * sizeof(void*)), beginOp.m_reentry);
+
+                // Reject the match - backtrack back into the subpattern.
+                op.m_jumps.append(jump());
+
+                // This is the entry point to jump to when we stop matching - we will
+                // do so once the subpattern cannot match any more.
+                op.m_reentry = label();
+                break;
+            }
+
+            // OpParentheticalAssertionBegin/End
+            case OpParentheticalAssertionBegin: {
+                PatternTerm* term = op.m_term;
+
+                // Store the current index - assertions should not update index, so
+                // we will need to restore it upon a successful match.
+                unsigned parenthesesFrameLocation = term->frameLocation;
+                storeToFrame(index, parenthesesFrameLocation);
+
+                // Check 
+                op.m_checkAdjust = m_checked - term->inputPosition;
+                if (op.m_checkAdjust)
+                    sub32(Imm32(op.m_checkAdjust), index);
+
+                m_checked -= op.m_checkAdjust;
+                break;
+            }
+            case OpParentheticalAssertionEnd: {
+                PatternTerm* term = op.m_term;
+
+                // Restore the input index value.
+                unsigned parenthesesFrameLocation = term->frameLocation;
+                loadFromFrame(parenthesesFrameLocation, index);
+
+                // If inverted, a successful match of the assertion must be treated
+                // as a failure, so jump to backtracking.
+                if (term->invert()) {
+                    op.m_jumps.append(jump());
+                    op.m_reentry = label();
+                }
+
+                YarrOp& lastOp = m_ops[op.m_previousOp];
+                m_checked += lastOp.m_checkAdjust;
+                break;
+            }
+
+            case OpMatchFailed:
+                if (m_pattern.m_body->m_callFrameSize)
+                    addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+                move(TrustedImm32(-1), returnRegister);
+                generateReturn();
+                break;
+            }
+
+            ++opIndex;
+        } while (opIndex < m_ops.size());
+    }
+
+    void backtrack()
+    {
+        // Backwards generate the backtracking code.
+        size_t opIndex = m_ops.size();
+        ASSERT(opIndex);
+
+        do {
+            --opIndex;
+            YarrOp& op = m_ops[opIndex];
+            switch (op.m_op) {
+
+            case OpTerm:
+                backtrackTerm(opIndex);
+                break;
+
+            // OpBodyAlternativeBegin/Next/End
+            //
+            // For each Begin/Next node representing an alternative, we need to decide what to do
+            // in two circumstances:
+            //  - If we backtrack back into this node, from within the alternative.
+            //  - If the input check at the head of the alternative fails (if this exists).
+            //
+            // We treat these two cases differently since in the former case we have slightly
+            // more information - since we are backtracking out of a prior alternative we know
+            // that at least enough input was available to run it. For example, given the regular
+            // expression /a|b/, if we backtrack out of the first alternative (a failed pattern
+            // character match of 'a'), then we need not perform an additional input availability
+            // check before running the second alternative.
+            //
+            // Backtracking required differs for the last alternative, which in the case of the
+            // repeating set of alternatives must loop. The code generated for the last alternative
+            // will also be used to handle all input check failures from any prior alternatives -
+            // these require similar functionality, in seeking the next available alternative for
+            // which there is sufficient input.
+            //
+            // Since backtracking of all other alternatives simply requires us to link backtracks
+            // to the reentry point for the subsequent alternative, we will only be generating any
+            // code when backtracking the last alternative.
+            case OpBodyAlternativeBegin:
+            case OpBodyAlternativeNext: {
+                PatternAlternative* alternative = op.m_alternative;
+
+                if (op.m_op == OpBodyAlternativeNext) {
+                    PatternAlternative* priorAlternative = m_ops[op.m_previousOp].m_alternative;
+                    m_checked += priorAlternative->m_minimumSize;
+                }
+                m_checked -= alternative->m_minimumSize;
+
+                // Is this the last alternative? If not, then if we backtrack to this point we just
+                // need to jump to try to match the next alternative.
+                if (m_ops[op.m_nextOp].m_op != OpBodyAlternativeEnd) {
+                    m_backtrackingState.linkTo(m_ops[op.m_nextOp].m_reentry, this);
+                    break;
+                }
+                YarrOp& endOp = m_ops[op.m_nextOp];
+
+                YarrOp* beginOp = &op;
+                while (beginOp->m_op != OpBodyAlternativeBegin) {
+                    ASSERT(beginOp->m_op == OpBodyAlternativeNext);
+                    beginOp = &m_ops[beginOp->m_previousOp];
+                }
+
+                bool onceThrough = endOp.m_nextOp == notFound;
+
+                // First, generate code to handle cases where we backtrack out of an attempted match
+                // of the last alternative. If this is a 'once through' set of alternatives then we
+                // have nothing to do - link this straight through to the End.
+                if (onceThrough)
+                    m_backtrackingState.linkTo(endOp.m_reentry, this);
+                else {
+                    // If we don't need to move the input poistion, and the pattern has a fixed size
+                    // (in which case we omit the store of the start index until the pattern has matched)
+                    // then we can just link the backtrack out of the last alternative straight to the
+                    // head of the first alternative.
+                    if (m_pattern.m_body->m_hasFixedSize
+                        && (alternative->m_minimumSize > beginOp->m_alternative->m_minimumSize)
+                        && (alternative->m_minimumSize - beginOp->m_alternative->m_minimumSize == 1))
+                        m_backtrackingState.linkTo(beginOp->m_reentry, this);
+                    else {
+                        // We need to generate a trampoline of code to execute before looping back
+                        // around to the first alternative.
+                        m_backtrackingState.link(this);
+
+                        // If the pattern size is not fixed, then store the start index, for use if we match.
+                        if (!m_pattern.m_body->m_hasFixedSize) {
+                            if (alternative->m_minimumSize == 1)
+                                store32(index, Address(output));
+                            else {
+                                move(index, regT0);
+                                if (alternative->m_minimumSize)
+                                    sub32(Imm32(alternative->m_minimumSize - 1), regT0);
+                                else
+                                    add32(Imm32(1), regT0);
+                                store32(regT0, Address(output));
+                            }
+                        }
+
+                        // Generate code to loop. Check whether the last alternative is longer than the
+                        // first (e.g. /a|xy/ or /a|xyz/).
+                        if (alternative->m_minimumSize > beginOp->m_alternative->m_minimumSize) {
+                            // We want to loop, and increment input position. If the delta is 1, it is
+                            // already correctly incremented, if more than one then decrement as appropriate.
+                            unsigned delta = alternative->m_minimumSize - beginOp->m_alternative->m_minimumSize;
+                            ASSERT(delta);
+                            if (delta != 1)
+                                sub32(Imm32(delta - 1), index);
+                            jump(beginOp->m_reentry);
+                        } else {
+                            // If the first alternative has minimum size 0xFFFFFFFFu, then there cannot
+                            // be sufficent input available to handle this, so just fall through.
+                            unsigned delta = beginOp->m_alternative->m_minimumSize - alternative->m_minimumSize;
+                            if (delta != 0xFFFFFFFFu) {
+                                // We need to check input because we are incrementing the input.
+                                add32(Imm32(delta + 1), index);
+                                checkInput().linkTo(beginOp->m_reentry, this);
+                            }
+                        }
+                    }
+                }
+
+                // We can reach this point in the code in two ways:
+                //  - Fallthrough from the code above (a repeating alternative backtracked out of its
+                //    last alternative, and did not have sufficent input to run the first).
+                //  - We will loop back up to the following label when a releating alternative loops,
+                //    following a failed input check.
+                //
+                // Either way, we have just failed the input check for the first alternative.
+                Label firstInputCheckFailed(this);
+
+                // Generate code to handle input check failures from alternatives except the last.
+                // prevOp is the alternative we're handling a bail out from (initially Begin), and
+                // nextOp is the alternative we will be attempting to reenter into.
+                // 
+                // We will link input check failures from the forwards matching path back to the code
+                // that can handle them.
+                YarrOp* prevOp = beginOp;
+                YarrOp* nextOp = &m_ops[beginOp->m_nextOp];
+                while (nextOp->m_op != OpBodyAlternativeEnd) {
+                    prevOp->m_jumps.link(this);
+
+                    // We only get here if an input check fails, it is only worth checking again
+                    // if the next alternative has a minimum size less than the last.
+                    if (prevOp->m_alternative->m_minimumSize > nextOp->m_alternative->m_minimumSize) {
+                        // FIXME: if we added an extra label to YarrOp, we could avoid needing to
+                        // subtract delta back out, and reduce this code. Should performance test
+                        // the benefit of this.
+                        unsigned delta = prevOp->m_alternative->m_minimumSize - nextOp->m_alternative->m_minimumSize;
+                        sub32(Imm32(delta), index);
+                        Jump fail = jumpIfNoAvailableInput();
+                        add32(Imm32(delta), index);
+                        jump(nextOp->m_reentry);
+                        fail.link(this);
+                    } else if (prevOp->m_alternative->m_minimumSize < nextOp->m_alternative->m_minimumSize)
+                        add32(Imm32(nextOp->m_alternative->m_minimumSize - prevOp->m_alternative->m_minimumSize), index);
+                    prevOp = nextOp;
+                    nextOp = &m_ops[nextOp->m_nextOp];
+                }
+
+                // We fall through to here if there is insufficient input to run the last alternative.
+
+                // If there is insufficient input to run the last alternative, then for 'once through'
+                // alternatives we are done - just jump back up into the forwards matching path at the End.
+                if (onceThrough) {
+                    op.m_jumps.linkTo(endOp.m_reentry, this);
+                    jump(endOp.m_reentry);
+                    break;
+                }
+
+                // For repeating alternatives, link any input check failure from the last alternative to
+                // this point.
+                op.m_jumps.link(this);
+
+                bool needsToUpdateMatchStart = !m_pattern.m_body->m_hasFixedSize;
+
+                // Check for cases where input position is already incremented by 1 for the last
+                // alternative (this is particularly useful where the minimum size of the body
+                // disjunction is 0, e.g. /a*|b/).
+                if (needsToUpdateMatchStart && alternative->m_minimumSize == 1) {
+                    // index is already incremented by 1, so just store it now!
+                    store32(index, Address(output));
+                    needsToUpdateMatchStart = false;
+                }
+
+                // Check whether there is sufficient input to loop. Increment the input position by
+                // one, and check. Also add in the minimum disjunction size before checking - there
+                // is no point in looping if we're just going to fail all the input checks around
+                // the next iteration.
+                ASSERT(alternative->m_minimumSize >= m_pattern.m_body->m_minimumSize);
+                if (alternative->m_minimumSize == m_pattern.m_body->m_minimumSize) {
+                    // If the last alternative had the same minimum size as the disjunction,
+                    // just simply increment input pos by 1, no adjustment based on minimum size.
+                    add32(Imm32(1), index);
+                } else {
+                    // If the minumum for the last alternative was one greater than than that
+                    // for the disjunction, we're already progressed by 1, nothing to do!
+                    unsigned delta = (alternative->m_minimumSize - m_pattern.m_body->m_minimumSize) - 1;
+                    if (delta)
+                        sub32(Imm32(delta), index);
+                }
+                Jump matchFailed = jumpIfNoAvailableInput();
+
+                if (needsToUpdateMatchStart) {
+                    if (!m_pattern.m_body->m_minimumSize)
+                        store32(index, Address(output));
+                    else {
+                        move(index, regT0);
+                        sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0);
+                        store32(regT0, Address(output));
+                    }
+                }
+
+                // Calculate how much more input the first alternative requires than the minimum
+                // for the body as a whole. If no more is needed then we dont need an additional
+                // input check here - jump straight back up to the start of the first alternative.
+                if (beginOp->m_alternative->m_minimumSize == m_pattern.m_body->m_minimumSize)
+                    jump(beginOp->m_reentry);
+                else {
+                    if (beginOp->m_alternative->m_minimumSize > m_pattern.m_body->m_minimumSize)
+                        add32(Imm32(beginOp->m_alternative->m_minimumSize - m_pattern.m_body->m_minimumSize), index);
+                    else
+                        sub32(Imm32(m_pattern.m_body->m_minimumSize - beginOp->m_alternative->m_minimumSize), index);
+                    checkInput().linkTo(beginOp->m_reentry, this);
+                    jump(firstInputCheckFailed);
+                }
+
+                // We jump to here if we iterate to the point that there is insufficient input to
+                // run any matches, and need to return a failure state from JIT code.
+                matchFailed.link(this);
+
+                if (m_pattern.m_body->m_callFrameSize)
+                    addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+                move(TrustedImm32(-1), returnRegister);
+                generateReturn();
+                break;
+            }
+            case OpBodyAlternativeEnd: {
+                // We should never backtrack back into a body disjunction.
+                ASSERT(m_backtrackingState.isEmpty());
+
+                PatternAlternative* priorAlternative = m_ops[op.m_previousOp].m_alternative;
+                m_checked += priorAlternative->m_minimumSize;
+                break;
+            }
+
+            // OpSimpleNestedAlternativeBegin/Next/End
+            // OpNestedAlternativeBegin/Next/End
+            //
+            // Generate code for when we backtrack back out of an alternative into
+            // a Begin or Next node, or when the entry input count check fails. If
+            // there are more alternatives we need to jump to the next alternative,
+            // if not we backtrack back out of the current set of parentheses.
+            //
+            // In the case of non-simple nested assertions we need to also link the
+            // 'return address' appropriately to backtrack back out into the correct
+            // alternative.
+            case OpSimpleNestedAlternativeBegin:
+            case OpSimpleNestedAlternativeNext:
+            case OpNestedAlternativeBegin:
+            case OpNestedAlternativeNext: {
+                YarrOp& nextOp = m_ops[op.m_nextOp];
+                bool isBegin = op.m_previousOp == notFound;
+                bool isLastAlternative = nextOp.m_nextOp == notFound;
+                ASSERT(isBegin == (op.m_op == OpSimpleNestedAlternativeBegin || op.m_op == OpNestedAlternativeBegin));
+                ASSERT(isLastAlternative == (nextOp.m_op == OpSimpleNestedAlternativeEnd || nextOp.m_op == OpNestedAlternativeEnd));
+
+                // Treat an input check failure the same as a failed match.
+                m_backtrackingState.append(op.m_jumps);
+
+                // Set the backtracks to jump to the appropriate place. We may need
+                // to link the backtracks in one of three different way depending on
+                // the type of alternative we are dealing with:
+                //  - A single alternative, with no simplings.
+                //  - The last alternative of a set of two or more.
+                //  - An alternative other than the last of a set of two or more.
+                //
+                // In the case of a single alternative on its own, we don't need to
+                // jump anywhere - if the alternative fails to match we can just
+                // continue to backtrack out of the parentheses without jumping.
+                //
+                // In the case of the last alternative in a set of more than one, we
+                // need to jump to return back out to the beginning. We'll do so by
+                // adding a jump to the End node's m_jumps list, and linking this
+                // when we come to generate the Begin node. For alternatives other
+                // than the last, we need to jump to the next alternative.
+                //
+                // If the alternative had adjusted the input position we must link
+                // backtracking to here, correct, and then jump on. If not we can
+                // link the backtracks directly to their destination.
+                if (op.m_checkAdjust) {
+                    // Handle the cases where we need to link the backtracks here.
+                    m_backtrackingState.link(this);
+                    sub32(Imm32(op.m_checkAdjust), index);
+                    if (!isLastAlternative) {
+                        // An alternative that is not the last should jump to its successor.
+                        jump(nextOp.m_reentry);
+                    } else if (!isBegin) {
+                        // The last of more than one alternatives must jump back to the begnning.
+                        nextOp.m_jumps.append(jump());
+                    } else {
+                        // A single alternative on its own can fall through.
+                        m_backtrackingState.fallthrough();
+                    }
+                } else {
+                    // Handle the cases where we can link the backtracks directly to their destinations.
+                    if (!isLastAlternative) {
+                        // An alternative that is not the last should jump to its successor.
+                        m_backtrackingState.linkTo(nextOp.m_reentry, this);
+                    } else if (!isBegin) {
+                        // The last of more than one alternatives must jump back to the begnning.
+                        m_backtrackingState.takeBacktracksToJumpList(nextOp.m_jumps, this);
+                    }
+                    // In the case of a single alternative on its own do nothing - it can fall through.
+                }
+
+                // At this point we've handled the backtracking back into this node.
+                // Now link any backtracks that need to jump to here.
+
+                // For non-simple alternatives, link the alternative's 'return address'
+                // so that we backtrack back out into the previous alternative.
+                if (op.m_op == OpNestedAlternativeNext)
+                    m_backtrackingState.append(op.m_returnAddress);
+
+                // If there is more than one alternative, then the last alternative will
+                // have planted a jump to be linked to the end. This jump was added to the
+                // End node's m_jumps list. If we are back at the beginning, link it here.
+                if (isBegin) {
+                    YarrOp* endOp = &m_ops[op.m_nextOp];
+                    while (endOp->m_nextOp != notFound) {
+                        ASSERT(endOp->m_op == OpSimpleNestedAlternativeNext || endOp->m_op == OpNestedAlternativeNext);
+                        endOp = &m_ops[endOp->m_nextOp];
+                    }
+                    ASSERT(endOp->m_op == OpSimpleNestedAlternativeEnd || endOp->m_op == OpNestedAlternativeEnd);
+                    m_backtrackingState.append(endOp->m_jumps);
+                }
+
+                if (!isBegin) {
+                    YarrOp& lastOp = m_ops[op.m_previousOp];
+                    m_checked += lastOp.m_checkAdjust;
+                }
+                m_checked -= op.m_checkAdjust;
+                break;
+            }
+            case OpSimpleNestedAlternativeEnd:
+            case OpNestedAlternativeEnd: {
+                PatternTerm* term = op.m_term;
+
+                // If we backtrack into the end of a simple subpattern do nothing;
+                // just continue through into the last alternative. If we backtrack
+                // into the end of a non-simple set of alterntives we need to jump
+                // to the backtracking return address set up during generation.
+                if (op.m_op == OpNestedAlternativeEnd) {
+                    m_backtrackingState.link(this);
+
+                    // Plant a jump to the return address.
+                    unsigned parenthesesFrameLocation = term->frameLocation;
+                    unsigned alternativeFrameLocation = parenthesesFrameLocation;
+                    if (term->quantityType != QuantifierFixedCount)
+                        alternativeFrameLocation += YarrStackSpaceForBackTrackInfoParenthesesOnce;
+                    loadFromFrameAndJump(alternativeFrameLocation);
+
+                    // Link the DataLabelPtr associated with the end of the last
+                    // alternative to this point.
+                    m_backtrackingState.append(op.m_returnAddress);
+                }
+
+                YarrOp& lastOp = m_ops[op.m_previousOp];
+                m_checked += lastOp.m_checkAdjust;
+                break;
+            }
+
+            // OpParenthesesSubpatternOnceBegin/End
+            //
+            // When we are backtracking back out of a capturing subpattern we need
+            // to clear the start index in the matches output array, to record that
+            // this subpattern has not been captured.
+            //
+            // When backtracking back out of a Greedy quantified subpattern we need
+            // to catch this, and try running the remainder of the alternative after
+            // the subpattern again, skipping the parentheses.
+            //
+            // Upon backtracking back into a quantified set of parentheses we need to
+            // check whether we were currently skipping the subpattern. If not, we
+            // can backtrack into them, if we were we need to either backtrack back
+            // out of the start of the parentheses, or jump back to the forwards
+            // matching start, depending of whether the match is Greedy or NonGreedy.
+            case OpParenthesesSubpatternOnceBegin: {
+                PatternTerm* term = op.m_term;
+                ASSERT(term->quantityCount == 1);
+
+                // We only need to backtrack to thispoint if capturing or greedy.
+                if (term->capture() || term->quantityType == QuantifierGreedy) {
+                    m_backtrackingState.link(this);
+
+                    // If capturing, clear the capture (we only need to reset start).
+                    if (term->capture())
+                        store32(TrustedImm32(-1), Address(output, (term->parentheses.subpatternId << 1) * sizeof(int)));
+
+                    // If Greedy, jump to the end.
+                    if (term->quantityType == QuantifierGreedy) {
+                        // Clear the flag in the stackframe indicating we ran through the subpattern.
+                        unsigned parenthesesFrameLocation = term->frameLocation;
+                        storeToFrame(TrustedImm32(-1), parenthesesFrameLocation);
+                        // Jump to after the parentheses, skipping the subpattern.
+                        jump(m_ops[op.m_nextOp].m_reentry);
+                        // A backtrack from after the parentheses, when skipping the subpattern,
+                        // will jump back to here.
+                        op.m_jumps.link(this);
+                    }
+
+                    m_backtrackingState.fallthrough();
+                }
+                break;
+            }
+            case OpParenthesesSubpatternOnceEnd: {
+                PatternTerm* term = op.m_term;
+
+                if (term->quantityType != QuantifierFixedCount) {
+                    m_backtrackingState.link(this);
+
+                    // Check whether we should backtrack back into the parentheses, or if we
+                    // are currently in a state where we had skipped over the subpattern
+                    // (in which case the flag value on the stack will be -1).
+                    unsigned parenthesesFrameLocation = term->frameLocation;
+                    Jump hadSkipped = branch32(Equal, Address(stackPointerRegister, parenthesesFrameLocation * sizeof(void*)), TrustedImm32(-1));
+
+                    if (term->quantityType == QuantifierGreedy) {
+                        // For Greedy parentheses, we skip after having already tried going
+                        // through the subpattern, so if we get here we're done.
+                        YarrOp& beginOp = m_ops[op.m_previousOp];
+                        beginOp.m_jumps.append(hadSkipped);
+                    } else {
+                        // For NonGreedy parentheses, we try skipping the subpattern first,
+                        // so if we get here we need to try running through the subpattern
+                        // next. Jump back to the start of the parentheses in the forwards
+                        // matching path.
+                        ASSERT(term->quantityType == QuantifierNonGreedy);
+                        YarrOp& beginOp = m_ops[op.m_previousOp];
+                        hadSkipped.linkTo(beginOp.m_reentry, this);
+                    }
+
+                    m_backtrackingState.fallthrough();
+                }
+
+                m_backtrackingState.append(op.m_jumps);
+                break;
+            }
+
+            // OpParenthesesSubpatternTerminalBegin/End
+            //
+            // Terminal subpatterns will always match - there is nothing after them to
+            // force a backtrack, and they have a minimum count of 0, and as such will
+            // always produce an acceptable result.
+            case OpParenthesesSubpatternTerminalBegin: {
+                // We will backtrack to this point once the subpattern cannot match any
+                // more. Since no match is accepted as a successful match (we are Greedy
+                // quantified with a minimum of zero) jump back to the forwards matching
+                // path at the end.
+                YarrOp& endOp = m_ops[op.m_nextOp];
+                m_backtrackingState.linkTo(endOp.m_reentry, this);
+                break;
+            }
+            case OpParenthesesSubpatternTerminalEnd:
+                // We should never be backtracking to here (hence the 'terminal' in the name).
+                ASSERT(m_backtrackingState.isEmpty());
+                m_backtrackingState.append(op.m_jumps);
+                break;
+
+            // OpParentheticalAssertionBegin/End
+            case OpParentheticalAssertionBegin: {
+                PatternTerm* term = op.m_term;
+                YarrOp& endOp = m_ops[op.m_nextOp];
+
+                // We need to handle the backtracks upon backtracking back out
+                // of a parenthetical assertion if either we need to correct
+                // the input index, or the assertion was inverted.
+                if (op.m_checkAdjust || term->invert()) {
+                     m_backtrackingState.link(this);
+
+                    if (op.m_checkAdjust)
+                        add32(Imm32(op.m_checkAdjust), index);
+
+                    // In an inverted assertion failure to match the subpattern
+                    // is treated as a successful match - jump to the end of the
+                    // subpattern. We already have adjusted the input position
+                    // back to that before the assertion, which is correct.
+                    if (term->invert())
+                        jump(endOp.m_reentry);
+
+                    m_backtrackingState.fallthrough();
+                }
+
+                // The End node's jump list will contain any backtracks into
+                // the end of the assertion. Also, if inverted, we will have
+                // added the failure caused by a successful match to this.
+                m_backtrackingState.append(endOp.m_jumps);
+
+                m_checked += op.m_checkAdjust;
+                break;
+            }
+            case OpParentheticalAssertionEnd: {
+                // FIXME: We should really be clearing any nested subpattern
+                // matches on bailing out from after the pattern. Firefox has
+                // this bug too (presumably because they use YARR!)
+
+                // Never backtrack into an assertion; later failures bail to before the begin.
+                m_backtrackingState.takeBacktracksToJumpList(op.m_jumps, this);
+
+                YarrOp& lastOp = m_ops[op.m_previousOp];
+                m_checked -= lastOp.m_checkAdjust;
+                break;
+            }
+
+            case OpMatchFailed:
+                break;
+            }
+
+        } while (opIndex);
+    }
+
+    // Compilation methods:
+    // ====================
+
+    // opCompileParenthesesSubpattern
+    // Emits ops for a subpattern (set of parentheses). These consist
+    // of a set of alternatives wrapped in an outer set of nodes for
+    // the parentheses.
+    // Supported types of parentheses are 'Once' (quantityCount == 1)
+    // and 'Terminal' (non-capturing parentheses quantified as greedy
+    // and infinite).
+    // Alternatives will use the 'Simple' set of ops if either the
+    // subpattern is terminal (in which case we will never need to
+    // backtrack), or if the subpattern only contains one alternative.
+    void opCompileParenthesesSubpattern(PatternTerm* term)
+    {
+        YarrOpCode parenthesesBeginOpCode;
+        YarrOpCode parenthesesEndOpCode;
+        YarrOpCode alternativeBeginOpCode = OpSimpleNestedAlternativeBegin;
+        YarrOpCode alternativeNextOpCode = OpSimpleNestedAlternativeNext;
+        YarrOpCode alternativeEndOpCode = OpSimpleNestedAlternativeEnd;
+
+        // We can currently only compile quantity 1 subpatterns that are
+        // not copies. We generate a copy in the case of a range quantifier,
+        // e.g. /(?:x){3,9}/, or /(?:x)+/ (These are effectively expanded to
+        // /(?:x){3,3}(?:x){0,6}/ and /(?:x)(?:x)*/ repectively). The problem
+        // comes where the subpattern is capturing, in which case we would
+        // need to restore the capture from the first subpattern upon a
+        // failure in the second.
+        if (term->quantityCount == 1 && !term->parentheses.isCopy) {
+            // Select the 'Once' nodes.
+            parenthesesBeginOpCode = OpParenthesesSubpatternOnceBegin;
+            parenthesesEndOpCode = OpParenthesesSubpatternOnceEnd;
+
+            // If there is more than one alternative we cannot use the 'simple' nodes.
+            if (term->parentheses.disjunction->m_alternatives.size() != 1) {
+                alternativeBeginOpCode = OpNestedAlternativeBegin;
+                alternativeNextOpCode = OpNestedAlternativeNext;
+                alternativeEndOpCode = OpNestedAlternativeEnd;
+            }
+        } else if (term->parentheses.isTerminal) {
+            // Select the 'Terminal' nodes.
+            parenthesesBeginOpCode = OpParenthesesSubpatternTerminalBegin;
+            parenthesesEndOpCode = OpParenthesesSubpatternTerminalEnd;
+        } else {
+            // This subpattern is not supported by the JIT.
+            m_shouldFallBack = true;
+            return;
+        }
+
+        size_t parenBegin = m_ops.size();
+        m_ops.append(parenthesesBeginOpCode);
+
+        m_ops.append(alternativeBeginOpCode);
+        m_ops.last().m_previousOp = notFound;
+        m_ops.last().m_term = term;
+        Vector<PatternAlternative*>& alternatives =  term->parentheses.disjunction->m_alternatives;
+        for (unsigned i = 0; i < alternatives.size(); ++i) {
+            size_t lastOpIndex = m_ops.size() - 1;
+
+            PatternAlternative* nestedAlternative = alternatives[i];
+            opCompileAlternative(nestedAlternative);
+
+            size_t thisOpIndex = m_ops.size();
+            m_ops.append(YarrOp(alternativeNextOpCode));
+
+            YarrOp& lastOp = m_ops[lastOpIndex];
+            YarrOp& thisOp = m_ops[thisOpIndex];
+
+            lastOp.m_alternative = nestedAlternative;
+            lastOp.m_nextOp = thisOpIndex;
+            thisOp.m_previousOp = lastOpIndex;
+            thisOp.m_term = term;
+        }
+        YarrOp& lastOp = m_ops.last();
+        ASSERT(lastOp.m_op == alternativeNextOpCode);
+        lastOp.m_op = alternativeEndOpCode;
+        lastOp.m_alternative = 0;
+        lastOp.m_nextOp = notFound;
+
+        size_t parenEnd = m_ops.size();
+        m_ops.append(parenthesesEndOpCode);
+
+        m_ops[parenBegin].m_term = term;
+        m_ops[parenBegin].m_previousOp = notFound;
+        m_ops[parenBegin].m_nextOp = parenEnd;
+        m_ops[parenEnd].m_term = term;
+        m_ops[parenEnd].m_previousOp = parenBegin;
+        m_ops[parenEnd].m_nextOp = notFound;
+    }
+
+    // opCompileParentheticalAssertion
+    // Emits ops for a parenthetical assertion. These consist of an
+    // OpSimpleNestedAlternativeBegin/Next/End set of nodes wrapping
+    // the alternatives, with these wrapped by an outer pair of
+    // OpParentheticalAssertionBegin/End nodes.
+    // We can always use the OpSimpleNestedAlternative nodes in the
+    // case of parenthetical assertions since these only ever match
+    // once, and will never backtrack back into the assertion.
+    void opCompileParentheticalAssertion(PatternTerm* term)
+    {
+        size_t parenBegin = m_ops.size();
+        m_ops.append(OpParentheticalAssertionBegin);
+
+        m_ops.append(OpSimpleNestedAlternativeBegin);
+        m_ops.last().m_previousOp = notFound;
+        m_ops.last().m_term = term;
+        Vector<PatternAlternative*>& alternatives =  term->parentheses.disjunction->m_alternatives;
+        for (unsigned i = 0; i < alternatives.size(); ++i) {
+            size_t lastOpIndex = m_ops.size() - 1;
+
+            PatternAlternative* nestedAlternative = alternatives[i];
+            opCompileAlternative(nestedAlternative);
+
+            size_t thisOpIndex = m_ops.size();
+            m_ops.append(YarrOp(OpSimpleNestedAlternativeNext));
+
+            YarrOp& lastOp = m_ops[lastOpIndex];
+            YarrOp& thisOp = m_ops[thisOpIndex];
+
+            lastOp.m_alternative = nestedAlternative;
+            lastOp.m_nextOp = thisOpIndex;
+            thisOp.m_previousOp = lastOpIndex;
+            thisOp.m_term = term;
+        }
+        YarrOp& lastOp = m_ops.last();
+        ASSERT(lastOp.m_op == OpSimpleNestedAlternativeNext);
+        lastOp.m_op = OpSimpleNestedAlternativeEnd;
+        lastOp.m_alternative = 0;
+        lastOp.m_nextOp = notFound;
+
+        size_t parenEnd = m_ops.size();
+        m_ops.append(OpParentheticalAssertionEnd);
+
+        m_ops[parenBegin].m_term = term;
+        m_ops[parenBegin].m_previousOp = notFound;
+        m_ops[parenBegin].m_nextOp = parenEnd;
+        m_ops[parenEnd].m_term = term;
+        m_ops[parenEnd].m_previousOp = parenBegin;
+        m_ops[parenEnd].m_nextOp = notFound;
+    }
+
+    // opCompileAlternative
+    // Called to emit nodes for all terms in an alternative.
+    void opCompileAlternative(PatternAlternative* alternative)
+    {
+        optimizeAlternative(alternative);
+
+        for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
+            PatternTerm* term = &alternative->m_terms[i];
+
+            switch (term->type) {
+            case PatternTerm::TypeParenthesesSubpattern:
+                opCompileParenthesesSubpattern(term);
+                break;
+
+            case PatternTerm::TypeParentheticalAssertion:
+                opCompileParentheticalAssertion(term);
+                break;
+
+            default:
+                m_ops.append(term);
+            }
+        }
+    }
+
+    // opCompileBody
+    // This method compiles the body disjunction of the regular expression.
+    // The body consists of two sets of alternatives - zero or more 'once
+    // through' (BOL anchored) alternatives, followed by zero or more
+    // repeated alternatives.
+    // For each of these two sets of alteratives, if not empty they will be
+    // wrapped in a set of OpBodyAlternativeBegin/Next/End nodes (with the
+    // 'begin' node referencing the first alternative, and 'next' nodes
+    // referencing any further alternatives. The begin/next/end nodes are
+    // linked together in a doubly linked list. In the case of repeating
+    // alternatives, the end node is also linked back to the beginning.
+    // If no repeating alternatives exist, then a OpMatchFailed node exists
+    // to return the failing result.
+    void opCompileBody(PatternDisjunction* disjunction)
+    {
+        Vector<PatternAlternative*>& alternatives =  disjunction->m_alternatives;
+        size_t currentAlternativeIndex = 0;
+
+        // Emit the 'once through' alternatives.
+        if (alternatives.size() && alternatives[0]->onceThrough()) {
+            m_ops.append(YarrOp(OpBodyAlternativeBegin));
+            m_ops.last().m_previousOp = notFound;
+
+            do {
+                size_t lastOpIndex = m_ops.size() - 1;
+                PatternAlternative* alternative = alternatives[currentAlternativeIndex];
+                opCompileAlternative(alternative);
+
+                size_t thisOpIndex = m_ops.size();
+                m_ops.append(YarrOp(OpBodyAlternativeNext));
+
+                YarrOp& lastOp = m_ops[lastOpIndex];
+                YarrOp& thisOp = m_ops[thisOpIndex];
+
+                lastOp.m_alternative = alternative;
+                lastOp.m_nextOp = thisOpIndex;
+                thisOp.m_previousOp = lastOpIndex;
+                
+                ++currentAlternativeIndex;
+            } while (currentAlternativeIndex < alternatives.size() && alternatives[currentAlternativeIndex]->onceThrough());
+
+            YarrOp& lastOp = m_ops.last();
+
+            ASSERT(lastOp.m_op == OpBodyAlternativeNext);
+            lastOp.m_op = OpBodyAlternativeEnd;
+            lastOp.m_alternative = 0;
+            lastOp.m_nextOp = notFound;
+        }
+
+        if (currentAlternativeIndex == alternatives.size()) {
+            m_ops.append(YarrOp(OpMatchFailed));
+            return;
+        }
+
+        // Emit the repeated alternatives.
+        size_t repeatLoop = m_ops.size();
+        m_ops.append(YarrOp(OpBodyAlternativeBegin));
+        m_ops.last().m_previousOp = notFound;
+        do {
+            size_t lastOpIndex = m_ops.size() - 1;
+            PatternAlternative* alternative = alternatives[currentAlternativeIndex];
+            ASSERT(!alternative->onceThrough());
+            opCompileAlternative(alternative);
+
+            size_t thisOpIndex = m_ops.size();
+            m_ops.append(YarrOp(OpBodyAlternativeNext));
+
+            YarrOp& lastOp = m_ops[lastOpIndex];
+            YarrOp& thisOp = m_ops[thisOpIndex];
+
+            lastOp.m_alternative = alternative;
+            lastOp.m_nextOp = thisOpIndex;
+            thisOp.m_previousOp = lastOpIndex;
+            
+            ++currentAlternativeIndex;
+        } while (currentAlternativeIndex < alternatives.size());
+        YarrOp& lastOp = m_ops.last();
+        ASSERT(lastOp.m_op == OpBodyAlternativeNext);
+        lastOp.m_op = OpBodyAlternativeEnd;
+        lastOp.m_alternative = 0;
+        lastOp.m_nextOp = repeatLoop;
+    }
+
+    void generateEnter()
+    {
+#if CPU(X86_64)
+        push(X86Registers::ebp);
+        move(stackPointerRegister, X86Registers::ebp);
+        push(X86Registers::ebx);
+#elif CPU(X86)
+        push(X86Registers::ebp);
+        move(stackPointerRegister, X86Registers::ebp);
+        // TODO: do we need spill registers to fill the output pointer if there are no sub captures?
+        push(X86Registers::ebx);
+        push(X86Registers::edi);
+        push(X86Registers::esi);
+        // load output into edi (2 = saved ebp + return address).
+    #if COMPILER(MSVC)
+        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), input);
+        loadPtr(Address(X86Registers::ebp, 3 * sizeof(void*)), index);
+        loadPtr(Address(X86Registers::ebp, 4 * sizeof(void*)), length);
+        loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output);
+    #else
+        loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output);
+    #endif
+#elif CPU(ARM)
+        push(ARMRegisters::r4);
+        push(ARMRegisters::r5);
+        push(ARMRegisters::r6);
+#if CPU(ARM_TRADITIONAL)
+        push(ARMRegisters::r8); // scratch register
+#endif
+        move(ARMRegisters::r3, output);
+#elif CPU(SH4)
+        push(SH4Registers::r11);
+        push(SH4Registers::r13);
+#elif CPU(MIPS)
+        // Do nothing.
+#endif
+    }
+
+    void generateReturn()
+    {
+#if CPU(X86_64)
+        pop(X86Registers::ebx);
+        pop(X86Registers::ebp);
+#elif CPU(X86)
+        pop(X86Registers::esi);
+        pop(X86Registers::edi);
+        pop(X86Registers::ebx);
+        pop(X86Registers::ebp);
+#elif CPU(ARM)
+#if CPU(ARM_TRADITIONAL)
+        pop(ARMRegisters::r8); // scratch register
+#endif
+        pop(ARMRegisters::r6);
+        pop(ARMRegisters::r5);
+        pop(ARMRegisters::r4);
+#elif CPU(SH4)
+        pop(SH4Registers::r13);
+        pop(SH4Registers::r11);
+#elif CPU(MIPS)
+        // Do nothing
+#endif
+        ret();
+    }
+
+public:
+    YarrGenerator(YarrPattern& pattern)
+        : m_pattern(pattern)
+        , m_shouldFallBack(false)
+        , m_checked(0)
+    {
+    }
+
+    void compile(JSGlobalData* globalData, YarrCodeBlock& jitObject)
+    {
+        generateEnter();
+
+        if (!m_pattern.m_body->m_hasFixedSize)
+            store32(index, Address(output));
+
+        if (m_pattern.m_body->m_callFrameSize)
+            subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister);
+
+        // Compile the pattern to the internal 'YarrOp' representation.
+        opCompileBody(m_pattern.m_body);
+
+        // If we encountered anything we can't handle in the JIT code
+        // (e.g. backreferences) then return early.
+        if (m_shouldFallBack) {
+            jitObject.setFallBack(true);
+            return;
+        }
+
+        generate();
+        backtrack();
+
+        // Link & finalize the code.
+        LinkBuffer linkBuffer(*globalData, this, globalData->regexAllocator);
+        m_backtrackingState.linkDataLabels(linkBuffer);
+        jitObject.set(linkBuffer.finalizeCode());
+        jitObject.setFallBack(m_shouldFallBack);
+    }
+
+private:
+    YarrPattern& m_pattern;
+
+    // Used to detect regular expression constructs that are not currently
+    // supported in the JIT; fall back to the interpreter when this is detected.
+    bool m_shouldFallBack;
+
+    // The regular expression expressed as a linear sequence of operations.
+    Vector<YarrOp, 128> m_ops;
+
+    // This records the current input offset being applied due to the current
+    // set of alternatives we are nested within. E.g. when matching the
+    // character 'b' within the regular expression /abc/, we will know that
+    // the minimum size for the alternative is 3, checked upon entry to the
+    // alternative, and that 'b' is at offset 1 from the start, and as such
+    // when matching 'b' we need to apply an offset of -2 to the load.
+    //
+    // FIXME: This should go away. Rather than tracking this value throughout
+    // code generation, we should gather this information up front & store it
+    // on the YarrOp structure.
+    int m_checked;
+
+    // This class records state whilst generating the backtracking path of code.
+    BacktrackingState m_backtrackingState;
+};
+
+void jitCompile(YarrPattern& pattern, JSGlobalData* globalData, YarrCodeBlock& jitObject)
+{
+    YarrGenerator(pattern).compile(globalData, jitObject);
+}
+
+int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output)
+{
+    return jitObject.execute(input, start, length, output);
+}
+
+}}
+
+#endif
diff --git a/yarr/YarrJIT.h b/yarr/YarrJIT.h
new file mode 100644 (file)
index 0000000..91c5b85
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2009 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 YarrJIT_h
+#define YarrJIT_h
+
+#if ENABLE(YARR_JIT)
+
+#include "JSGlobalData.h"
+#include "MacroAssembler.h"
+#include "UString.h"
+#include "YarrPattern.h"
+
+#if CPU(X86) && !COMPILER(MSVC)
+#define YARR_CALL __attribute__ ((regparm (3)))
+#else
+#define YARR_CALL
+#endif
+
+namespace JSC {
+
+class JSGlobalData;
+class ExecutablePool;
+
+namespace Yarr {
+
+class YarrCodeBlock {
+    typedef int (*YarrJITCode)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL;
+
+public:
+    YarrCodeBlock()
+        : m_needFallBack(false)
+    {
+    }
+
+    ~YarrCodeBlock()
+    {
+    }
+
+    void setFallBack(bool fallback) { m_needFallBack = fallback; }
+    bool isFallBack() { return m_needFallBack; }
+    void set(MacroAssembler::CodeRef ref) { m_ref = ref; }
+
+    int execute(const UChar* input, unsigned start, unsigned length, int* output)
+    {
+        return reinterpret_cast<YarrJITCode>(m_ref.m_code.executableAddress())(input, start, length, output);
+    }
+
+#if ENABLE(REGEXP_TRACING)
+    void *getAddr() { return m_ref.m_code.executableAddress(); }
+#endif
+
+private:
+    MacroAssembler::CodeRef m_ref;
+    bool m_needFallBack;
+};
+
+void jitCompile(YarrPattern&, JSGlobalData*, YarrCodeBlock& jitObject);
+int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output);
+
+} } // namespace JSC::Yarr
+
+#endif
+
+#endif // YarrJIT_h
diff --git a/yarr/YarrParser.h b/yarr/YarrParser.h
new file mode 100644 (file)
index 0000000..65fb41d
--- /dev/null
@@ -0,0 +1,872 @@
+/*
+ * Copyright (C) 2009 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 YarrParser_h
+#define YarrParser_h
+
+#include <runtime/UString.h>
+#include "Yarr.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC { namespace Yarr {
+
+#define REGEXP_ERROR_PREFIX "Invalid regular expression: "
+
+enum BuiltInCharacterClassID {
+    DigitClassID,
+    SpaceClassID,
+    WordClassID,
+    NewlineClassID,
+};
+
+// The Parser class should not be used directly - only via the Yarr::parse() method.
+template<class Delegate>
+class Parser {
+private:
+    template<class FriendDelegate>
+    friend const char* parse(FriendDelegate& delegate, const UString& pattern, unsigned backReferenceLimit);
+
+    enum ErrorCode {
+        NoError,
+        PatternTooLarge,
+        QuantifierOutOfOrder,
+        QuantifierWithoutAtom,
+        MissingParentheses,
+        ParenthesesUnmatched,
+        ParenthesesTypeInvalid,
+        CharacterClassUnmatched,
+        CharacterClassOutOfOrder,
+        EscapeUnterminated,
+        NumberOfErrorCodes
+    };
+
+    /*
+     * CharacterClassParserDelegate:
+     *
+     * The class CharacterClassParserDelegate is used in the parsing of character
+     * classes.  This class handles detection of character ranges.  This class
+     * implements enough of the delegate interface such that it can be passed to
+     * parseEscape() as an EscapeDelegate.  This allows parseEscape() to be reused
+     * to perform the parsing of escape characters in character sets.
+     */
+    class CharacterClassParserDelegate {
+    public:
+        CharacterClassParserDelegate(Delegate& delegate, ErrorCode& err)
+            : m_delegate(delegate)
+            , m_err(err)
+            , m_state(Empty)
+            , m_character(0)
+        {
+        }
+
+        /*
+         * begin():
+         *
+         * Called at beginning of construction.
+         */
+        void begin(bool invert)
+        {
+            m_delegate.atomCharacterClassBegin(invert);
+        }
+
+        /*
+         * atomPatternCharacter():
+         *
+         * This method is called either from parseCharacterClass() (for an unescaped
+         * character in a character class), or from parseEscape(). In the former case
+         * the value true will be passed for the argument 'hyphenIsRange', and in this
+         * mode we will allow a hypen to be treated as indicating a range (i.e. /[a-z]/
+         * is different to /[a\-z]/).
+         */
+        void atomPatternCharacter(UChar ch, bool hyphenIsRange = false)
+        {
+            switch (m_state) {
+            case AfterCharacterClass:
+                // Following a builtin character class we need look out for a hyphen.
+                // We're looking for invalid ranges, such as /[\d-x]/ or /[\d-\d]/.
+                // If we see a hyphen following a charater class then unlike usual
+                // we'll report it to the delegate immediately, and put ourself into
+                // a poisoned state. Any following calls to add another character or
+                // character class will result in an error. (A hypen following a
+                // character-class is itself valid, but only  at the end of a regex).
+                if (hyphenIsRange && ch == '-') {
+                    m_delegate.atomCharacterClassAtom('-');
+                    m_state = AfterCharacterClassHyphen;
+                    return;
+                }
+                // Otherwise just fall through - cached character so treat this as Empty.
+
+            case Empty:
+                m_character = ch;
+                m_state = CachedCharacter;
+                return;
+
+            case CachedCharacter:
+                if (hyphenIsRange && ch == '-')
+                    m_state = CachedCharacterHyphen;
+                else {
+                    m_delegate.atomCharacterClassAtom(m_character);
+                    m_character = ch;
+                }
+                return;
+
+            case CachedCharacterHyphen:
+                if (ch < m_character) {
+                    m_err = CharacterClassOutOfOrder;
+                    return;
+                }
+                m_delegate.atomCharacterClassRange(m_character, ch);
+                m_state = Empty;
+                return;
+
+                // See coment in atomBuiltInCharacterClass below.
+                // This too is technically an error, per ECMA-262, and again we
+                // we chose to allow this.  Note a subtlely here that while we
+                // diverge from the spec's definition of CharacterRange we do
+                // remain in compliance with the grammar.  For example, consider
+                // the expression /[\d-a-z]/.  We comply with the grammar in
+                // this case by not allowing a-z to be matched as a range.
+            case AfterCharacterClassHyphen:
+                m_delegate.atomCharacterClassAtom(ch);
+                m_state = Empty;
+                return;
+            }
+        }
+
+        /*
+         * atomBuiltInCharacterClass():
+         *
+         * Adds a built-in character class, called by parseEscape().
+         */
+        void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
+        {
+            switch (m_state) {
+            case CachedCharacter:
+                // Flush the currently cached character, then fall through.
+                m_delegate.atomCharacterClassAtom(m_character);
+
+            case Empty:
+            case AfterCharacterClass:
+                m_state = AfterCharacterClass;
+                m_delegate.atomCharacterClassBuiltIn(classID, invert);
+                return;
+
+                // If we hit either of these cases, we have an invalid range that
+                // looks something like /[x-\d]/ or /[\d-\d]/.
+                // According to ECMA-262 this should be a syntax error, but
+                // empirical testing shows this to break teh webz.  Instead we
+                // comply with to the ECMA-262 grammar, and assume the grammar to
+                // have matched the range correctly, but tweak our interpretation
+                // of CharacterRange.  Effectively we implicitly handle the hyphen
+                // as if it were escaped, e.g. /[\w-_]/ is treated as /[\w\-_]/.
+            case CachedCharacterHyphen:
+                m_delegate.atomCharacterClassAtom(m_character);
+                m_delegate.atomCharacterClassAtom('-');
+                // fall through
+            case AfterCharacterClassHyphen:
+                m_delegate.atomCharacterClassBuiltIn(classID, invert);
+                m_state = Empty;
+                return;
+            }
+        }
+
+        /*
+         * end():
+         *
+         * Called at end of construction.
+         */
+        void end()
+        {
+            if (m_state == CachedCharacter)
+                m_delegate.atomCharacterClassAtom(m_character);
+            else if (m_state == CachedCharacterHyphen) {
+                m_delegate.atomCharacterClassAtom(m_character);
+                m_delegate.atomCharacterClassAtom('-');
+            }
+            m_delegate.atomCharacterClassEnd();
+        }
+
+        // parseEscape() should never call these delegate methods when
+        // invoked with inCharacterClass set.
+        void assertionWordBoundary(bool) { ASSERT_NOT_REACHED(); }
+        void atomBackReference(unsigned) { ASSERT_NOT_REACHED(); }
+
+    private:
+        Delegate& m_delegate;
+        ErrorCode& m_err;
+        enum CharacterClassConstructionState {
+            Empty,
+            CachedCharacter,
+            CachedCharacterHyphen,
+            AfterCharacterClass,
+            AfterCharacterClassHyphen,
+        } m_state;
+        UChar m_character;
+    };
+
+    Parser(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit)
+        : m_delegate(delegate)
+        , m_backReferenceLimit(backReferenceLimit)
+        , m_err(NoError)
+        , m_data(pattern.characters())
+        , m_size(pattern.length())
+        , m_index(0)
+        , m_parenthesesNestingDepth(0)
+    {
+    }
+    
+    /*
+     * parseEscape():
+     *
+     * Helper for parseTokens() AND parseCharacterClass().
+     * Unlike the other parser methods, this function does not report tokens
+     * directly to the member delegate (m_delegate), instead tokens are
+     * emitted to the delegate provided as an argument.  In the case of atom
+     * escapes, parseTokens() will call parseEscape() passing m_delegate as
+     * an argument, and as such the escape will be reported to the delegate.
+     *
+     * However this method may also be used by parseCharacterClass(), in which
+     * case a CharacterClassParserDelegate will be passed as the delegate that
+     * tokens should be added to.  A boolean flag is also provided to indicate
+     * whether that an escape in a CharacterClass is being parsed (some parsing
+     * rules change in this context).
+     *
+     * The boolean value returned by this method indicates whether the token
+     * parsed was an atom (outside of a characted class \b and \B will be
+     * interpreted as assertions).
+     */
+    template<bool inCharacterClass, class EscapeDelegate>
+    bool parseEscape(EscapeDelegate& delegate)
+    {
+        ASSERT(!m_err);
+        ASSERT(peek() == '\\');
+        consume();
+
+        if (atEndOfPattern()) {
+            m_err = EscapeUnterminated;
+            return false;
+        }
+
+        switch (peek()) {
+        // Assertions
+        case 'b':
+            consume();
+            if (inCharacterClass)
+                delegate.atomPatternCharacter('\b');
+            else {
+                delegate.assertionWordBoundary(false);
+                return false;
+            }
+            break;
+        case 'B':
+            consume();
+            if (inCharacterClass)
+                delegate.atomPatternCharacter('B');
+            else {
+                delegate.assertionWordBoundary(true);
+                return false;
+            }
+            break;
+
+        // CharacterClassEscape
+        case 'd':
+            consume();
+            delegate.atomBuiltInCharacterClass(DigitClassID, false);
+            break;
+        case 's':
+            consume();
+            delegate.atomBuiltInCharacterClass(SpaceClassID, false);
+            break;
+        case 'w':
+            consume();
+            delegate.atomBuiltInCharacterClass(WordClassID, false);
+            break;
+        case 'D':
+            consume();
+            delegate.atomBuiltInCharacterClass(DigitClassID, true);
+            break;
+        case 'S':
+            consume();
+            delegate.atomBuiltInCharacterClass(SpaceClassID, true);
+            break;
+        case 'W':
+            consume();
+            delegate.atomBuiltInCharacterClass(WordClassID, true);
+            break;
+
+        // DecimalEscape
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9': {
+            // To match Firefox, we parse an invalid backreference in the range [1-7] as an octal escape.
+            // First, try to parse this as backreference.
+            if (!inCharacterClass) {
+                ParseState state = saveState();
+
+                unsigned backReference = consumeNumber();
+                if (backReference <= m_backReferenceLimit) {
+                    delegate.atomBackReference(backReference);
+                    break;
+                }
+
+                restoreState(state);
+            }
+            
+            // Not a backreference, and not octal.
+            if (peek() >= '8') {
+                delegate.atomPatternCharacter('\\');
+                break;
+            }
+
+            // Fall-through to handle this as an octal escape.
+        }
+
+        // Octal escape
+        case '0':
+            delegate.atomPatternCharacter(consumeOctal());
+            break;
+
+        // ControlEscape
+        case 'f':
+            consume();
+            delegate.atomPatternCharacter('\f');
+            break;
+        case 'n':
+            consume();
+            delegate.atomPatternCharacter('\n');
+            break;
+        case 'r':
+            consume();
+            delegate.atomPatternCharacter('\r');
+            break;
+        case 't':
+            consume();
+            delegate.atomPatternCharacter('\t');
+            break;
+        case 'v':
+            consume();
+            delegate.atomPatternCharacter('\v');
+            break;
+
+        // ControlLetter
+        case 'c': {
+            ParseState state = saveState();
+            consume();
+            if (!atEndOfPattern()) {
+                int control = consume();
+
+                // To match Firefox, inside a character class, we also accept numbers and '_' as control characters.
+                if (inCharacterClass ? WTF::isASCIIAlphanumeric(control) || (control == '_') : WTF::isASCIIAlpha(control)) {
+                    delegate.atomPatternCharacter(control & 0x1f);
+                    break;
+                }
+            }
+            restoreState(state);
+            delegate.atomPatternCharacter('\\');
+            break;
+        }
+
+        // HexEscape
+        case 'x': {
+            consume();
+            int x = tryConsumeHex(2);
+            if (x == -1)
+                delegate.atomPatternCharacter('x');
+            else
+                delegate.atomPatternCharacter(x);
+            break;
+        }
+
+        // UnicodeEscape
+        case 'u': {
+            consume();
+            int u = tryConsumeHex(4);
+            if (u == -1)
+                delegate.atomPatternCharacter('u');
+            else
+                delegate.atomPatternCharacter(u);
+            break;
+        }
+
+        // IdentityEscape
+        default:
+            delegate.atomPatternCharacter(consume());
+        }
+        
+        return true;
+    }
+
+    /*
+     * parseAtomEscape(), parseCharacterClassEscape():
+     *
+     * These methods alias to parseEscape().
+     */
+    bool parseAtomEscape()
+    {
+        return parseEscape<false>(m_delegate);
+    }
+    void parseCharacterClassEscape(CharacterClassParserDelegate& delegate)
+    {
+        parseEscape<true>(delegate);
+    }
+
+    /*
+     * parseCharacterClass():
+     *
+     * Helper for parseTokens(); calls dirctly and indirectly (via parseCharacterClassEscape)
+     * to an instance of CharacterClassParserDelegate, to describe the character class to the
+     * delegate.
+     */
+    void parseCharacterClass()
+    {
+        ASSERT(!m_err);
+        ASSERT(peek() == '[');
+        consume();
+
+        CharacterClassParserDelegate characterClassConstructor(m_delegate, m_err);
+
+        characterClassConstructor.begin(tryConsume('^'));
+
+        while (!atEndOfPattern()) {
+            switch (peek()) {
+            case ']':
+                consume();
+                characterClassConstructor.end();
+                return;
+
+            case '\\':
+                parseCharacterClassEscape(characterClassConstructor);
+                break;
+
+            default:
+                characterClassConstructor.atomPatternCharacter(consume(), true);
+            }
+
+            if (m_err)
+                return;
+        }
+
+        m_err = CharacterClassUnmatched;
+    }
+
+    /*
+     * parseParenthesesBegin():
+     *
+     * Helper for parseTokens(); checks for parentheses types other than regular capturing subpatterns.
+     */
+    void parseParenthesesBegin()
+    {
+        ASSERT(!m_err);
+        ASSERT(peek() == '(');
+        consume();
+
+        if (tryConsume('?')) {
+            if (atEndOfPattern()) {
+                m_err = ParenthesesTypeInvalid;
+                return;
+            }
+
+            switch (consume()) {
+            case ':':
+                m_delegate.atomParenthesesSubpatternBegin(false);
+                break;
+            
+            case '=':
+                m_delegate.atomParentheticalAssertionBegin();
+                break;
+
+            case '!':
+                m_delegate.atomParentheticalAssertionBegin(true);
+                break;
+            
+            default:
+                m_err = ParenthesesTypeInvalid;
+            }
+        } else
+            m_delegate.atomParenthesesSubpatternBegin();
+
+        ++m_parenthesesNestingDepth;
+    }
+
+    /*
+     * parseParenthesesEnd():
+     *
+     * Helper for parseTokens(); checks for parse errors (due to unmatched parentheses).
+     */
+    void parseParenthesesEnd()
+    {
+        ASSERT(!m_err);
+        ASSERT(peek() == ')');
+        consume();
+
+        if (m_parenthesesNestingDepth > 0)
+            m_delegate.atomParenthesesEnd();
+        else
+            m_err = ParenthesesUnmatched;
+
+        --m_parenthesesNestingDepth;
+    }
+
+    /*
+     * parseQuantifier():
+     *
+     * Helper for parseTokens(); checks for parse errors and non-greedy quantifiers.
+     */
+    void parseQuantifier(bool lastTokenWasAnAtom, unsigned min, unsigned max)
+    {
+        ASSERT(!m_err);
+        ASSERT(min <= max);
+
+        if (lastTokenWasAnAtom)
+            m_delegate.quantifyAtom(min, max, !tryConsume('?'));
+        else
+            m_err = QuantifierWithoutAtom;
+    }
+
+    /*
+     * parseTokens():
+     *
+     * This method loops over the input pattern reporting tokens to the delegate.
+     * The method returns when a parse error is detected, or the end of the pattern
+     * is reached.  One piece of state is tracked around the loop, which is whether
+     * the last token passed to the delegate was an atom (this is necessary to detect
+     * a parse error when a quantifier provided without an atom to quantify).
+     */
+    void parseTokens()
+    {
+        bool lastTokenWasAnAtom = false;
+
+        while (!atEndOfPattern()) {
+            switch (peek()) {
+            case '|':
+                consume();
+                m_delegate.disjunction();
+                lastTokenWasAnAtom = false;
+                break;
+
+            case '(':
+                parseParenthesesBegin();
+                lastTokenWasAnAtom = false;
+                break;
+
+            case ')':
+                parseParenthesesEnd();
+                lastTokenWasAnAtom = true;
+                break;
+
+            case '^':
+                consume();
+                m_delegate.assertionBOL();
+                lastTokenWasAnAtom = false;
+                break;
+
+            case '$':
+                consume();
+                m_delegate.assertionEOL();
+                lastTokenWasAnAtom = false;
+                break;
+
+            case '.':
+                consume();
+                m_delegate.atomBuiltInCharacterClass(NewlineClassID, true);
+                lastTokenWasAnAtom = true;
+                break;
+
+            case '[':
+                parseCharacterClass();
+                lastTokenWasAnAtom = true;
+                break;
+
+            case '\\':
+                lastTokenWasAnAtom = parseAtomEscape();
+                break;
+
+            case '*':
+                consume();
+                parseQuantifier(lastTokenWasAnAtom, 0, quantifyInfinite);
+                lastTokenWasAnAtom = false;
+                break;
+
+            case '+':
+                consume();
+                parseQuantifier(lastTokenWasAnAtom, 1, quantifyInfinite);
+                lastTokenWasAnAtom = false;
+                break;
+
+            case '?':
+                consume();
+                parseQuantifier(lastTokenWasAnAtom, 0, 1);
+                lastTokenWasAnAtom = false;
+                break;
+
+            case '{': {
+                ParseState state = saveState();
+
+                consume();
+                if (peekIsDigit()) {
+                    unsigned min = consumeNumber();
+                    unsigned max = min;
+                    
+                    if (tryConsume(','))
+                        max = peekIsDigit() ? consumeNumber() : quantifyInfinite;
+
+                    if (tryConsume('}')) {
+                        if (min <= max)
+                            parseQuantifier(lastTokenWasAnAtom, min, max);
+                        else
+                            m_err = QuantifierOutOfOrder;
+                        lastTokenWasAnAtom = false;
+                        break;
+                    }
+                }
+
+                restoreState(state);
+            } // if we did not find a complete quantifer, fall through to the default case.
+
+            default:
+                m_delegate.atomPatternCharacter(consume());
+                lastTokenWasAnAtom = true;
+            }
+
+            if (m_err)
+                return;
+        }
+
+        if (m_parenthesesNestingDepth > 0)
+            m_err = MissingParentheses;
+    }
+
+    /*
+     * parse():
+     *
+     * This method calls parseTokens() to parse over the input and converts any
+     * error code to a const char* for a result.
+     */
+    const char* parse()
+    {
+        if (m_size > MAX_PATTERN_SIZE)
+            m_err = PatternTooLarge;
+        else
+            parseTokens();
+        ASSERT(atEndOfPattern() || m_err);
+
+        // The order of this array must match the ErrorCode enum.
+        static const char* errorMessages[NumberOfErrorCodes] = {
+            0, // NoError
+            REGEXP_ERROR_PREFIX "regular expression too large",
+            REGEXP_ERROR_PREFIX "numbers out of order in {} quantifier",
+            REGEXP_ERROR_PREFIX "nothing to repeat",
+            REGEXP_ERROR_PREFIX "missing )",
+            REGEXP_ERROR_PREFIX "unmatched parentheses",
+            REGEXP_ERROR_PREFIX "unrecognized character after (?",
+            REGEXP_ERROR_PREFIX "missing terminating ] for character class",
+            REGEXP_ERROR_PREFIX "range out of order in character class",
+            REGEXP_ERROR_PREFIX "\\ at end of pattern"
+        };
+
+        return errorMessages[m_err];
+    }
+
+
+    // Misc helper functions:
+
+    typedef unsigned ParseState;
+    
+    ParseState saveState()
+    {
+        return m_index;
+    }
+
+    void restoreState(ParseState state)
+    {
+        m_index = state;
+    }
+
+    bool atEndOfPattern()
+    {
+        ASSERT(m_index <= m_size);
+        return m_index == m_size;
+    }
+
+    int peek()
+    {
+        ASSERT(m_index < m_size);
+        return m_data[m_index];
+    }
+
+    bool peekIsDigit()
+    {
+        return !atEndOfPattern() && WTF::isASCIIDigit(peek());
+    }
+
+    unsigned peekDigit()
+    {
+        ASSERT(peekIsDigit());
+        return peek() - '0';
+    }
+
+    int consume()
+    {
+        ASSERT(m_index < m_size);
+        return m_data[m_index++];
+    }
+
+    unsigned consumeDigit()
+    {
+        ASSERT(peekIsDigit());
+        return consume() - '0';
+    }
+
+    unsigned consumeNumber()
+    {
+        unsigned n = consumeDigit();
+        // check for overflow.
+        for (unsigned newValue; peekIsDigit() && ((newValue = n * 10 + peekDigit()) >= n); ) {
+            n = newValue;
+            consume();
+        }
+        return n;
+    }
+
+    unsigned consumeOctal()
+    {
+        ASSERT(WTF::isASCIIOctalDigit(peek()));
+
+        unsigned n = consumeDigit();
+        while (n < 32 && !atEndOfPattern() && WTF::isASCIIOctalDigit(peek()))
+            n = n * 8 + consumeDigit();
+        return n;
+    }
+
+    bool tryConsume(UChar ch)
+    {
+        if (atEndOfPattern() || (m_data[m_index] != ch))
+            return false;
+        ++m_index;
+        return true;
+    }
+
+    int tryConsumeHex(int count)
+    {
+        ParseState state = saveState();
+
+        int n = 0;
+        while (count--) {
+            if (atEndOfPattern() || !WTF::isASCIIHexDigit(peek())) {
+                restoreState(state);
+                return -1;
+            }
+            n = (n << 4) | WTF::toASCIIHexValue(consume());
+        }
+        return n;
+    }
+
+    Delegate& m_delegate;
+    unsigned m_backReferenceLimit;
+    ErrorCode m_err;
+    const UChar* m_data;
+    unsigned m_size;
+    unsigned m_index;
+    unsigned m_parenthesesNestingDepth;
+
+    // Derived by empirical testing of compile time in PCRE and WREC.
+    static const unsigned MAX_PATTERN_SIZE = 1024 * 1024;
+};
+
+/*
+ * Yarr::parse():
+ *
+ * The parse method is passed a pattern to be parsed and a delegate upon which
+ * callbacks will be made to record the parsed tokens forming the regex.
+ * Yarr::parse() returns null on success, or a const C string providing an error
+ * message where a parse error occurs.
+ *
+ * The Delegate must implement the following interface:
+ *
+ *    void assertionBOL();
+ *    void assertionEOL();
+ *    void assertionWordBoundary(bool invert);
+ *
+ *    void atomPatternCharacter(UChar ch);
+ *    void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert);
+ *    void atomCharacterClassBegin(bool invert)
+ *    void atomCharacterClassAtom(UChar ch)
+ *    void atomCharacterClassRange(UChar begin, UChar end)
+ *    void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
+ *    void atomCharacterClassEnd()
+ *    void atomParenthesesSubpatternBegin(bool capture = true);
+ *    void atomParentheticalAssertionBegin(bool invert = false);
+ *    void atomParenthesesEnd();
+ *    void atomBackReference(unsigned subpatternId);
+ *
+ *    void quantifyAtom(unsigned min, unsigned max, bool greedy);
+ *
+ *    void disjunction();
+ *
+ * The regular expression is described by a sequence of assertion*() and atom*()
+ * callbacks to the delegate, describing the terms in the regular expression.
+ * Following an atom a quantifyAtom() call may occur to indicate that the previous
+ * atom should be quantified.  In the case of atoms described across multiple
+ * calls (parentheses and character classes) the call to quantifyAtom() will come
+ * after the call to the atom*End() method, never after atom*Begin().
+ *
+ * Character classes may either be described by a single call to
+ * atomBuiltInCharacterClass(), or by a sequence of atomCharacterClass*() calls.
+ * In the latter case, ...Begin() will be called, followed by a sequence of
+ * calls to ...Atom(), ...Range(), and ...BuiltIn(), followed by a call to ...End().
+ *
+ * Sequences of atoms and assertions are broken into alternatives via calls to
+ * disjunction().  Assertions, atoms, and disjunctions emitted between calls to
+ * atomParenthesesBegin() and atomParenthesesEnd() form the body of a subpattern.
+ * atomParenthesesBegin() is passed a subpatternId.  In the case of a regular
+ * capturing subpattern, this will be the subpatternId associated with these
+ * parentheses, and will also by definition be the lowest subpatternId of these
+ * parentheses and of any nested paretheses.  The atomParenthesesEnd() method
+ * is passed the subpatternId of the last capturing subexpression nested within
+ * these paretheses.  In the case of a capturing subpattern with no nested
+ * capturing subpatterns, the same subpatternId will be passed to the begin and
+ * end functions.  In the case of non-capturing subpatterns the subpatternId
+ * passed to the begin method is also the first possible subpatternId that might
+ * be nested within these paretheses.  If a set of non-capturing parentheses does
+ * not contain any capturing subpatterns, then the subpatternId passed to begin
+ * will be greater than the subpatternId passed to end.
+ */
+
+template<class Delegate>
+const char* parse(Delegate& delegate, const UString& pattern, unsigned backReferenceLimit = quantifyInfinite)
+{
+    return Parser<Delegate>(delegate, pattern, backReferenceLimit).parse();
+}
+
+} } // namespace JSC::Yarr
+
+#endif // YarrParser_h
diff --git a/yarr/YarrPattern.cpp b/yarr/YarrPattern.cpp
new file mode 100644 (file)
index 0000000..fc8e8ee
--- /dev/null
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
+ *
+ * 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. 
+ */
+
+#include "config.h"
+#include "YarrPattern.h"
+
+#include "Yarr.h"
+#include "YarrParser.h"
+#include <wtf/Vector.h>
+
+using namespace WTF;
+
+namespace JSC { namespace Yarr {
+
+#include "RegExpJitTables.h"
+
+class CharacterClassConstructor {
+public:
+    CharacterClassConstructor(bool isCaseInsensitive = false)
+        : m_isCaseInsensitive(isCaseInsensitive)
+    {
+    }
+    
+    void reset()
+    {
+        m_matches.clear();
+        m_ranges.clear();
+        m_matchesUnicode.clear();
+        m_rangesUnicode.clear();
+    }
+
+    void append(const CharacterClass* other)
+    {
+        for (size_t i = 0; i < other->m_matches.size(); ++i)
+            addSorted(m_matches, other->m_matches[i]);
+        for (size_t i = 0; i < other->m_ranges.size(); ++i)
+            addSortedRange(m_ranges, other->m_ranges[i].begin, other->m_ranges[i].end);
+        for (size_t i = 0; i < other->m_matchesUnicode.size(); ++i)
+            addSorted(m_matchesUnicode, other->m_matchesUnicode[i]);
+        for (size_t i = 0; i < other->m_rangesUnicode.size(); ++i)
+            addSortedRange(m_rangesUnicode, other->m_rangesUnicode[i].begin, other->m_rangesUnicode[i].end);
+    }
+
+    void putChar(UChar ch)
+    {
+        if (ch <= 0x7f) {
+            if (m_isCaseInsensitive && isASCIIAlpha(ch)) {
+                addSorted(m_matches, toASCIIUpper(ch));
+                addSorted(m_matches, toASCIILower(ch));
+            } else
+                addSorted(m_matches, ch);
+        } else {
+            UChar upper, lower;
+            if (m_isCaseInsensitive && ((upper = Unicode::toUpper(ch)) != (lower = Unicode::toLower(ch)))) {
+                addSorted(m_matchesUnicode, upper);
+                addSorted(m_matchesUnicode, lower);
+            } else
+                addSorted(m_matchesUnicode, ch);
+        }
+    }
+
+    // returns true if this character has another case, and 'ch' is the upper case form.
+    static inline bool isUnicodeUpper(UChar ch)
+    {
+        return ch != Unicode::toLower(ch);
+    }
+
+    // returns true if this character has another case, and 'ch' is the lower case form.
+    static inline bool isUnicodeLower(UChar ch)
+    {
+        return ch != Unicode::toUpper(ch);
+    }
+
+    void putRange(UChar lo, UChar hi)
+    {
+        if (lo <= 0x7f) {
+            char asciiLo = lo;
+            char asciiHi = std::min(hi, (UChar)0x7f);
+            addSortedRange(m_ranges, lo, asciiHi);
+            
+            if (m_isCaseInsensitive) {
+                if ((asciiLo <= 'Z') && (asciiHi >= 'A'))
+                    addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A'));
+                if ((asciiLo <= 'z') && (asciiHi >= 'a'))
+                    addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a'));
+            }
+        }
+        if (hi >= 0x80) {
+            uint32_t unicodeCurr = std::max(lo, (UChar)0x80);
+            addSortedRange(m_rangesUnicode, unicodeCurr, hi);
+            
+            if (m_isCaseInsensitive) {
+                while (unicodeCurr <= hi) {
+                    // If the upper bound of the range (hi) is 0xffff, the increments to
+                    // unicodeCurr in this loop may take it to 0x10000.  This is fine
+                    // (if so we won't re-enter the loop, since the loop condition above
+                    // will definitely fail) - but this does mean we cannot use a UChar
+                    // to represent unicodeCurr, we must use a 32-bit value instead.
+                    ASSERT(unicodeCurr <= 0xffff);
+
+                    if (isUnicodeUpper(unicodeCurr)) {
+                        UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr);
+                        UChar lowerCaseRangeEnd = lowerCaseRangeBegin;
+                        while ((++unicodeCurr <= hi) && isUnicodeUpper(unicodeCurr) && (Unicode::toLower(unicodeCurr) == (lowerCaseRangeEnd + 1)))
+                            lowerCaseRangeEnd++;
+                        addSortedRange(m_rangesUnicode, lowerCaseRangeBegin, lowerCaseRangeEnd);
+                    } else if (isUnicodeLower(unicodeCurr)) {
+                        UChar upperCaseRangeBegin = Unicode::toUpper(unicodeCurr);
+                        UChar upperCaseRangeEnd = upperCaseRangeBegin;
+                        while ((++unicodeCurr <= hi) && isUnicodeLower(unicodeCurr) && (Unicode::toUpper(unicodeCurr) == (upperCaseRangeEnd + 1)))
+                            upperCaseRangeEnd++;
+                        addSortedRange(m_rangesUnicode, upperCaseRangeBegin, upperCaseRangeEnd);
+                    } else
+                        ++unicodeCurr;
+                }
+            }
+        }
+    }
+
+    CharacterClass* charClass()
+    {
+        CharacterClass* characterClass = new CharacterClass(0);
+
+        characterClass->m_matches.append(m_matches);
+        characterClass->m_ranges.append(m_ranges);
+        characterClass->m_matchesUnicode.append(m_matchesUnicode);
+        characterClass->m_rangesUnicode.append(m_rangesUnicode);
+
+        reset();
+
+        return characterClass;
+    }
+
+private:
+    void addSorted(Vector<UChar>& matches, UChar ch)
+    {
+        unsigned pos = 0;
+        unsigned range = matches.size();
+
+        // binary chop, find position to insert char.
+        while (range) {
+            unsigned index = range >> 1;
+
+            int val = matches[pos+index] - ch;
+            if (!val)
+                return;
+            else if (val > 0)
+                range = index;
+            else {
+                pos += (index+1);
+                range -= (index+1);
+            }
+        }
+        
+        if (pos == matches.size())
+            matches.append(ch);
+        else
+            matches.insert(pos, ch);
+    }
+
+    void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi)
+    {
+        unsigned end = ranges.size();
+        
+        // Simple linear scan - I doubt there are that many ranges anyway...
+        // feel free to fix this with something faster (eg binary chop).
+        for (unsigned i = 0; i < end; ++i) {
+            // does the new range fall before the current position in the array
+            if (hi < ranges[i].begin) {
+                // optional optimization: concatenate appending ranges? - may not be worthwhile.
+                if (hi == (ranges[i].begin - 1)) {
+                    ranges[i].begin = lo;
+                    return;
+                }
+                ranges.insert(i, CharacterRange(lo, hi));
+                return;
+            }
+            // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the begining
+            // If the new range start at or before the end of the last range, then the overlap (if it starts one after the
+            // end of the last range they concatenate, which is just as good.
+            if (lo <= (ranges[i].end + 1)) {
+                // found an intersect! we'll replace this entry in the array.
+                ranges[i].begin = std::min(ranges[i].begin, lo);
+                ranges[i].end = std::max(ranges[i].end, hi);
+
+                // now check if the new range can subsume any subsequent ranges.
+                unsigned next = i+1;
+                // each iteration of the loop we will either remove something from the list, or break the loop.
+                while (next < ranges.size()) {
+                    if (ranges[next].begin <= (ranges[i].end + 1)) {
+                        // the next entry now overlaps / concatenates this one.
+                        ranges[i].end = std::max(ranges[i].end, ranges[next].end);
+                        ranges.remove(next);
+                    } else
+                        break;
+                }
+                
+                return;
+            }
+        }
+
+        // CharacterRange comes after all existing ranges.
+        ranges.append(CharacterRange(lo, hi));
+    }
+
+    bool m_isCaseInsensitive;
+
+    Vector<UChar> m_matches;
+    Vector<CharacterRange> m_ranges;
+    Vector<UChar> m_matchesUnicode;
+    Vector<CharacterRange> m_rangesUnicode;
+};
+
+class YarrPatternConstructor {
+public:
+    YarrPatternConstructor(YarrPattern& pattern)
+        : m_pattern(pattern)
+        , m_characterClassConstructor(pattern.m_ignoreCase)
+        , m_invertParentheticalAssertion(false)
+    {
+        m_pattern.m_body = new PatternDisjunction();
+        m_alternative = m_pattern.m_body->addNewAlternative();
+        m_pattern.m_disjunctions.append(m_pattern.m_body);
+    }
+
+    ~YarrPatternConstructor()
+    {
+    }
+
+    void reset()
+    {
+        m_pattern.reset();
+        m_characterClassConstructor.reset();
+
+        m_pattern.m_body = new PatternDisjunction();
+        m_alternative = m_pattern.m_body->addNewAlternative();
+        m_pattern.m_disjunctions.append(m_pattern.m_body);
+    }
+    
+    void assertionBOL()
+    {
+        if (!m_alternative->m_terms.size() & !m_invertParentheticalAssertion) {
+            m_alternative->m_startsWithBOL = true;
+            m_alternative->m_containsBOL = true;
+            m_pattern.m_containsBOL = true;
+        }
+        m_alternative->m_terms.append(PatternTerm::BOL());
+    }
+    void assertionEOL()
+    {
+        m_alternative->m_terms.append(PatternTerm::EOL());
+    }
+    void assertionWordBoundary(bool invert)
+    {
+        m_alternative->m_terms.append(PatternTerm::WordBoundary(invert));
+    }
+
+    void atomPatternCharacter(UChar ch)
+    {
+        // We handle case-insensitive checking of unicode characters which do have both
+        // cases by handling them as if they were defined using a CharacterClass.
+        if (m_pattern.m_ignoreCase && !isASCII(ch) && (Unicode::toUpper(ch) != Unicode::toLower(ch))) {
+            atomCharacterClassBegin();
+            atomCharacterClassAtom(ch);
+            atomCharacterClassEnd();
+        } else
+            m_alternative->m_terms.append(PatternTerm(ch));
+    }
+
+    void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert)
+    {
+        switch (classID) {
+        case DigitClassID:
+            m_alternative->m_terms.append(PatternTerm(m_pattern.digitsCharacterClass(), invert));
+            break;
+        case SpaceClassID:
+            m_alternative->m_terms.append(PatternTerm(m_pattern.spacesCharacterClass(), invert));
+            break;
+        case WordClassID:
+            m_alternative->m_terms.append(PatternTerm(m_pattern.wordcharCharacterClass(), invert));
+            break;
+        case NewlineClassID:
+            m_alternative->m_terms.append(PatternTerm(m_pattern.newlineCharacterClass(), invert));
+            break;
+        }
+    }
+
+    void atomCharacterClassBegin(bool invert = false)
+    {
+        m_invertCharacterClass = invert;
+    }
+
+    void atomCharacterClassAtom(UChar ch)
+    {
+        m_characterClassConstructor.putChar(ch);
+    }
+
+    void atomCharacterClassRange(UChar begin, UChar end)
+    {
+        m_characterClassConstructor.putRange(begin, end);
+    }
+
+    void atomCharacterClassBuiltIn(BuiltInCharacterClassID classID, bool invert)
+    {
+        ASSERT(classID != NewlineClassID);
+
+        switch (classID) {
+        case DigitClassID:
+            m_characterClassConstructor.append(invert ? m_pattern.nondigitsCharacterClass() : m_pattern.digitsCharacterClass());
+            break;
+        
+        case SpaceClassID:
+            m_characterClassConstructor.append(invert ? m_pattern.nonspacesCharacterClass() : m_pattern.spacesCharacterClass());
+            break;
+        
+        case WordClassID:
+            m_characterClassConstructor.append(invert ? m_pattern.nonwordcharCharacterClass() : m_pattern.wordcharCharacterClass());
+            break;
+        
+        default:
+            ASSERT_NOT_REACHED();
+        }
+    }
+
+    void atomCharacterClassEnd()
+    {
+        CharacterClass* newCharacterClass = m_characterClassConstructor.charClass();
+        m_pattern.m_userCharacterClasses.append(newCharacterClass);
+        m_alternative->m_terms.append(PatternTerm(newCharacterClass, m_invertCharacterClass));
+    }
+
+    void atomParenthesesSubpatternBegin(bool capture = true)
+    {
+        unsigned subpatternId = m_pattern.m_numSubpatterns + 1;
+        if (capture)
+            m_pattern.m_numSubpatterns++;
+
+        PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
+        m_pattern.m_disjunctions.append(parenthesesDisjunction);
+        m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture, false));
+        m_alternative = parenthesesDisjunction->addNewAlternative();
+    }
+
+    void atomParentheticalAssertionBegin(bool invert = false)
+    {
+        PatternDisjunction* parenthesesDisjunction = new PatternDisjunction(m_alternative);
+        m_pattern.m_disjunctions.append(parenthesesDisjunction);
+        m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, false, invert));
+        m_alternative = parenthesesDisjunction->addNewAlternative();
+        m_invertParentheticalAssertion = invert;
+    }
+
+    void atomParenthesesEnd()
+    {
+        ASSERT(m_alternative->m_parent);
+        ASSERT(m_alternative->m_parent->m_parent);
+
+        PatternDisjunction* parenthesesDisjunction = m_alternative->m_parent;
+        m_alternative = m_alternative->m_parent->m_parent;
+
+        PatternTerm& lastTerm = m_alternative->lastTerm();
+
+        unsigned numParenAlternatives = parenthesesDisjunction->m_alternatives.size();
+        unsigned numBOLAnchoredAlts = 0;
+
+        for (unsigned i = 0; i < numParenAlternatives; i++) {
+            // Bubble up BOL flags
+            if (parenthesesDisjunction->m_alternatives[i]->m_startsWithBOL)
+                numBOLAnchoredAlts++;
+        }
+
+        if (numBOLAnchoredAlts) {
+            m_alternative->m_containsBOL = true;
+            // If all the alternatives in parens start with BOL, then so does this one
+            if (numBOLAnchoredAlts == numParenAlternatives)
+                m_alternative->m_startsWithBOL = true;
+        }
+
+        lastTerm.parentheses.lastSubpatternId = m_pattern.m_numSubpatterns;
+        m_invertParentheticalAssertion = false;
+    }
+
+    void atomBackReference(unsigned subpatternId)
+    {
+        ASSERT(subpatternId);
+        m_pattern.m_containsBackreferences = true;
+        m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, subpatternId);
+
+        if (subpatternId > m_pattern.m_numSubpatterns) {
+            m_alternative->m_terms.append(PatternTerm::ForwardReference());
+            return;
+        }
+
+        PatternAlternative* currentAlternative = m_alternative;
+        ASSERT(currentAlternative);
+
+        // Note to self: if we waited until the AST was baked, we could also remove forwards refs 
+        while ((currentAlternative = currentAlternative->m_parent->m_parent)) {
+            PatternTerm& term = currentAlternative->lastTerm();
+            ASSERT((term.type == PatternTerm::TypeParenthesesSubpattern) || (term.type == PatternTerm::TypeParentheticalAssertion));
+
+            if ((term.type == PatternTerm::TypeParenthesesSubpattern) && term.capture() && (subpatternId == term.parentheses.subpatternId)) {
+                m_alternative->m_terms.append(PatternTerm::ForwardReference());
+                return;
+            }
+        }
+
+        m_alternative->m_terms.append(PatternTerm(subpatternId));
+    }
+
+    // deep copy the argument disjunction.  If filterStartsWithBOL is true, 
+    // skip alternatives with m_startsWithBOL set true.
+    PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction, bool filterStartsWithBOL = false)
+    {
+        PatternDisjunction* newDisjunction = 0;
+        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
+            PatternAlternative* alternative = disjunction->m_alternatives[alt];
+            if (!filterStartsWithBOL || !alternative->m_startsWithBOL) {
+                if (!newDisjunction) {
+                    newDisjunction = new PatternDisjunction();
+                    newDisjunction->m_parent = disjunction->m_parent;
+                }
+                PatternAlternative* newAlternative = newDisjunction->addNewAlternative();
+                for (unsigned i = 0; i < alternative->m_terms.size(); ++i)
+                    newAlternative->m_terms.append(copyTerm(alternative->m_terms[i], filterStartsWithBOL));
+            }
+        }
+        
+        if (newDisjunction)
+            m_pattern.m_disjunctions.append(newDisjunction);
+        return newDisjunction;
+    }
+    
+    PatternTerm copyTerm(PatternTerm& term, bool filterStartsWithBOL = false)
+    {
+        if ((term.type != PatternTerm::TypeParenthesesSubpattern) && (term.type != PatternTerm::TypeParentheticalAssertion))
+            return PatternTerm(term);
+        
+        PatternTerm termCopy = term;
+        termCopy.parentheses.disjunction = copyDisjunction(termCopy.parentheses.disjunction, filterStartsWithBOL);
+        return termCopy;
+    }
+    
+    void quantifyAtom(unsigned min, unsigned max, bool greedy)
+    {
+        ASSERT(min <= max);
+        ASSERT(m_alternative->m_terms.size());
+
+        if (!max) {
+            m_alternative->removeLastTerm();
+            return;
+        }
+
+        PatternTerm& term = m_alternative->lastTerm();
+        ASSERT(term.type > PatternTerm::TypeAssertionWordBoundary);
+        ASSERT((term.quantityCount == 1) && (term.quantityType == QuantifierFixedCount));
+
+        // For any assertion with a zero minimum, not matching is valid and has no effect,
+        // remove it.  Otherwise, we need to match as least once, but there is no point
+        // matching more than once, so remove the quantifier.  It is not entirely clear
+        // from the spec whether or not this behavior is correct, but I believe this
+        // matches Firefox. :-/
+        if (term.type == PatternTerm::TypeParentheticalAssertion) {
+            if (!min)
+                m_alternative->removeLastTerm();
+            return;
+        }
+
+        if (min == 0)
+            term.quantify(max, greedy   ? QuantifierGreedy : QuantifierNonGreedy);
+        else if (min == max)
+            term.quantify(min, QuantifierFixedCount);
+        else {
+            term.quantify(min, QuantifierFixedCount);
+            m_alternative->m_terms.append(copyTerm(term));
+            // NOTE: this term is interesting from an analysis perspective, in that it can be ignored.....
+            m_alternative->lastTerm().quantify((max == quantifyInfinite) ? max : max - min, greedy ? QuantifierGreedy : QuantifierNonGreedy);
+            if (m_alternative->lastTerm().type == PatternTerm::TypeParenthesesSubpattern)
+                m_alternative->lastTerm().parentheses.isCopy = true;
+        }
+    }
+
+    void disjunction()
+    {
+        m_alternative = m_alternative->m_parent->addNewAlternative();
+    }
+
+    unsigned setupAlternativeOffsets(PatternAlternative* alternative, unsigned currentCallFrameSize, unsigned initialInputPosition)
+    {
+        alternative->m_hasFixedSize = true;
+        unsigned currentInputPosition = initialInputPosition;
+
+        for (unsigned i = 0; i < alternative->m_terms.size(); ++i) {
+            PatternTerm& term = alternative->m_terms[i];
+
+            switch (term.type) {
+            case PatternTerm::TypeAssertionBOL:
+            case PatternTerm::TypeAssertionEOL:
+            case PatternTerm::TypeAssertionWordBoundary:
+                term.inputPosition = currentInputPosition;
+                break;
+
+            case PatternTerm::TypeBackReference:
+                term.inputPosition = currentInputPosition;
+                term.frameLocation = currentCallFrameSize;
+                currentCallFrameSize += YarrStackSpaceForBackTrackInfoBackReference;
+                alternative->m_hasFixedSize = false;
+                break;
+
+            case PatternTerm::TypeForwardReference:
+                break;
+
+            case PatternTerm::TypePatternCharacter:
+                term.inputPosition = currentInputPosition;
+                if (term.quantityType != QuantifierFixedCount) {
+                    term.frameLocation = currentCallFrameSize;
+                    currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter;
+                    alternative->m_hasFixedSize = false;
+                } else
+                    currentInputPosition += term.quantityCount;
+                break;
+
+            case PatternTerm::TypeCharacterClass:
+                term.inputPosition = currentInputPosition;
+                if (term.quantityType != QuantifierFixedCount) {
+                    term.frameLocation = currentCallFrameSize;
+                    currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass;
+                    alternative->m_hasFixedSize = false;
+                } else
+                    currentInputPosition += term.quantityCount;
+                break;
+
+            case PatternTerm::TypeParenthesesSubpattern:
+                // Note: for fixed once parentheses we will ensure at least the minimum is available; others are on their own.
+                term.frameLocation = currentCallFrameSize;
+                if (term.quantityCount == 1 && !term.parentheses.isCopy) {
+                    if (term.quantityType != QuantifierFixedCount)
+                        currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesOnce;
+                    currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
+                    // If quantity is fixed, then pre-check its minimum size.
+                    if (term.quantityType == QuantifierFixedCount)
+                        currentInputPosition += term.parentheses.disjunction->m_minimumSize;
+                    term.inputPosition = currentInputPosition;
+                } else if (term.parentheses.isTerminal) {
+                    currentCallFrameSize += YarrStackSpaceForBackTrackInfoParenthesesTerminal;
+                    currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize, currentInputPosition);
+                    term.inputPosition = currentInputPosition;
+                } else {
+                    term.inputPosition = currentInputPosition;
+                    setupDisjunctionOffsets(term.parentheses.disjunction, 0, currentInputPosition);
+                    currentCallFrameSize += YarrStackSpaceForBackTrackInfoParentheses;
+                }
+                // Fixed count of 1 could be accepted, if they have a fixed size *AND* if all alternatives are of the same length.
+                alternative->m_hasFixedSize = false;
+                break;
+
+            case PatternTerm::TypeParentheticalAssertion:
+                term.inputPosition = currentInputPosition;
+                term.frameLocation = currentCallFrameSize;
+                currentCallFrameSize = setupDisjunctionOffsets(term.parentheses.disjunction, currentCallFrameSize + YarrStackSpaceForBackTrackInfoParentheticalAssertion, currentInputPosition);
+                break;
+
+            case PatternTerm::TypeDotStarEnclosure:
+                alternative->m_hasFixedSize = false;
+                term.inputPosition = initialInputPosition;
+                break;
+            }
+        }
+
+        alternative->m_minimumSize = currentInputPosition - initialInputPosition;
+        return currentCallFrameSize;
+    }
+
+    unsigned setupDisjunctionOffsets(PatternDisjunction* disjunction, unsigned initialCallFrameSize, unsigned initialInputPosition)
+    {
+        if ((disjunction != m_pattern.m_body) && (disjunction->m_alternatives.size() > 1))
+            initialCallFrameSize += YarrStackSpaceForBackTrackInfoAlternative;
+
+        unsigned minimumInputSize = UINT_MAX;
+        unsigned maximumCallFrameSize = 0;
+        bool hasFixedSize = true;
+
+        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt) {
+            PatternAlternative* alternative = disjunction->m_alternatives[alt];
+            unsigned currentAlternativeCallFrameSize = setupAlternativeOffsets(alternative, initialCallFrameSize, initialInputPosition);
+            minimumInputSize = min(minimumInputSize, alternative->m_minimumSize);
+            maximumCallFrameSize = max(maximumCallFrameSize, currentAlternativeCallFrameSize);
+            hasFixedSize &= alternative->m_hasFixedSize;
+        }
+        
+        ASSERT(minimumInputSize != UINT_MAX);
+        ASSERT(maximumCallFrameSize >= initialCallFrameSize);
+
+        disjunction->m_hasFixedSize = hasFixedSize;
+        disjunction->m_minimumSize = minimumInputSize;
+        disjunction->m_callFrameSize = maximumCallFrameSize;
+        return maximumCallFrameSize;
+    }
+
+    void setupOffsets()
+    {
+        setupDisjunctionOffsets(m_pattern.m_body, 0, 0);
+    }
+
+    // This optimization identifies sets of parentheses that we will never need to backtrack.
+    // In these cases we do not need to store state from prior iterations.
+    // We can presently avoid backtracking for:
+    //   * where the parens are at the end of the regular expression (last term in any of the
+    //     alternatives of the main body disjunction).
+    //   * where the parens are non-capturing, and quantified unbounded greedy (*).
+    //   * where the parens do not contain any capturing subpatterns.
+    void checkForTerminalParentheses()
+    {
+        // This check is much too crude; should be just checking whether the candidate
+        // node contains nested capturing subpatterns, not the whole expression!
+        if (m_pattern.m_numSubpatterns)
+            return;
+
+        Vector<PatternAlternative*>& alternatives = m_pattern.m_body->m_alternatives;
+        for (size_t i = 0; i < alternatives.size(); ++i) {
+            Vector<PatternTerm>& terms = alternatives[i]->m_terms;
+            if (terms.size()) {
+                PatternTerm& term = terms.last();
+                if (term.type == PatternTerm::TypeParenthesesSubpattern
+                    && term.quantityType == QuantifierGreedy
+                    && term.quantityCount == quantifyInfinite
+                    && !term.capture())
+                    term.parentheses.isTerminal = true;
+            }
+        }
+    }
+
+    void optimizeBOL()
+    {
+        // Look for expressions containing beginning of line (^) anchoring and unroll them.
+        // e.g. /^a|^b|c/ becomes /^a|^b|c/ which is executed once followed by /c/ which loops
+        // This code relies on the parsing code tagging alternatives with m_containsBOL and
+        // m_startsWithBOL and rolling those up to containing alternatives.
+        // At this point, this is only valid for non-multiline expressions.
+        PatternDisjunction* disjunction = m_pattern.m_body;
+        
+        if (!m_pattern.m_containsBOL || m_pattern.m_multiline)
+            return;
+        
+        PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true);
+
+        // Set alternatives in disjunction to "onceThrough"
+        for (unsigned alt = 0; alt < disjunction->m_alternatives.size(); ++alt)
+            disjunction->m_alternatives[alt]->setOnceThrough();
+
+        if (loopDisjunction) {
+            // Move alternatives from loopDisjunction to disjunction
+            for (unsigned alt = 0; alt < loopDisjunction->m_alternatives.size(); ++alt)
+                disjunction->m_alternatives.append(loopDisjunction->m_alternatives[alt]);
+                
+            loopDisjunction->m_alternatives.clear();
+        }
+    }
+
+    bool containsCapturingTerms(PatternAlternative* alternative, size_t firstTermIndex, size_t lastTermIndex)
+    {
+        Vector<PatternTerm>& terms = alternative->m_terms;
+
+        for (size_t termIndex = firstTermIndex; termIndex <= lastTermIndex; ++termIndex) {
+            PatternTerm& term = terms[termIndex];
+
+            if (term.m_capture)
+                return true;
+
+            if (term.type == PatternTerm::TypeParenthesesSubpattern) {
+                PatternDisjunction* nestedDisjunction = term.parentheses.disjunction;
+                for (unsigned alt = 0; alt < nestedDisjunction->m_alternatives.size(); ++alt) {
+                    if (containsCapturingTerms(nestedDisjunction->m_alternatives[alt], 0, nestedDisjunction->m_alternatives[alt]->m_terms.size() - 1))
+                        return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    // This optimization identifies alternatives in the form of 
+    // [^].*[?]<expression>.*[$] for expressions that don't have any 
+    // capturing terms. The alternative is changed to <expression> 
+    // followed by processing of the dot stars to find and adjust the 
+    // beginning and the end of the match.
+    void optimizeDotStarWrappedExpressions()
+    {
+        Vector<PatternAlternative*>& alternatives = m_pattern.m_body->m_alternatives;
+        if (alternatives.size() != 1)
+            return;
+
+        PatternAlternative* alternative = alternatives[0];
+        Vector<PatternTerm>& terms = alternative->m_terms;
+        if (terms.size() >= 3) {
+            bool startsWithBOL = false;
+            bool endsWithEOL = false;
+            size_t termIndex, firstExpressionTerm, lastExpressionTerm;
+
+            termIndex = 0;
+            if (terms[termIndex].type == PatternTerm::TypeAssertionBOL) {
+                startsWithBOL = true;
+                ++termIndex;
+            }
+            
+            PatternTerm& firstNonAnchorTerm = terms[termIndex];
+            if ((firstNonAnchorTerm.type != PatternTerm::TypeCharacterClass) || (firstNonAnchorTerm.characterClass != m_pattern.newlineCharacterClass()) || !((firstNonAnchorTerm.quantityType == QuantifierGreedy) || (firstNonAnchorTerm.quantityType == QuantifierNonGreedy)))
+                return;
+            
+            firstExpressionTerm = termIndex + 1;
+            
+            termIndex = terms.size() - 1;
+            if (terms[termIndex].type == PatternTerm::TypeAssertionEOL) {
+                endsWithEOL = true;
+                --termIndex;
+            }
+            
+            PatternTerm& lastNonAnchorTerm = terms[termIndex];
+            if ((lastNonAnchorTerm.type != PatternTerm::TypeCharacterClass) || (lastNonAnchorTerm.characterClass != m_pattern.newlineCharacterClass()) || (lastNonAnchorTerm.quantityType != QuantifierGreedy))
+                return;
+            
+            lastExpressionTerm = termIndex - 1;
+
+            if (firstExpressionTerm > lastExpressionTerm)
+                return;
+
+            if (!containsCapturingTerms(alternative, firstExpressionTerm, lastExpressionTerm)) {
+                for (termIndex = terms.size() - 1; termIndex > lastExpressionTerm; --termIndex)
+                    terms.remove(termIndex);
+
+                for (termIndex = firstExpressionTerm; termIndex > 0; --termIndex)
+                    terms.remove(termIndex - 1);
+
+                terms.append(PatternTerm(startsWithBOL, endsWithEOL));
+                
+                m_pattern.m_containsBOL = false;
+            }
+        }
+    }
+
+private:
+    YarrPattern& m_pattern;
+    PatternAlternative* m_alternative;
+    CharacterClassConstructor m_characterClassConstructor;
+    bool m_invertCharacterClass;
+    bool m_invertParentheticalAssertion;
+};
+
+const char* YarrPattern::compile(const UString& patternString)
+{
+    YarrPatternConstructor constructor(*this);
+
+    if (const char* error = parse(constructor, patternString))
+        return error;
+    
+    // If the pattern contains illegal backreferences reset & reparse.
+    // Quoting Netscape's "What's new in JavaScript 1.2",
+    //      "Note: if the number of left parentheses is less than the number specified
+    //       in \#, the \# is taken as an octal escape as described in the next row."
+    if (containsIllegalBackReference()) {
+        unsigned numSubpatterns = m_numSubpatterns;
+
+        constructor.reset();
+#if !ASSERT_DISABLED
+        const char* error =
+#endif
+            parse(constructor, patternString, numSubpatterns);
+
+        ASSERT(!error);
+        ASSERT(numSubpatterns == m_numSubpatterns);
+    }
+
+    constructor.checkForTerminalParentheses();
+    constructor.optimizeDotStarWrappedExpressions();
+    constructor.optimizeBOL();
+        
+    constructor.setupOffsets();
+
+    return 0;
+}
+
+YarrPattern::YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error)
+    : m_ignoreCase(ignoreCase)
+    , m_multiline(multiline)
+    , m_containsBackreferences(false)
+    , m_containsBOL(false)
+    , m_numSubpatterns(0)
+    , m_maxBackReference(0)
+    , newlineCached(0)
+    , digitsCached(0)
+    , spacesCached(0)
+    , wordcharCached(0)
+    , nondigitsCached(0)
+    , nonspacesCached(0)
+    , nonwordcharCached(0)
+{
+    *error = compile(pattern);
+}
+
+} }
diff --git a/yarr/YarrPattern.h b/yarr/YarrPattern.h
new file mode 100644 (file)
index 0000000..97c3870
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged
+ *
+ * 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 YarrPattern_h
+#define YarrPattern_h
+
+#include <runtime/UString.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace JSC { namespace Yarr {
+
+struct PatternDisjunction;
+
+struct CharacterRange {
+    UChar begin;
+    UChar end;
+
+    CharacterRange(UChar begin, UChar end)
+        : begin(begin)
+        , end(end)
+    {
+    }
+};
+
+struct CharacterClassTable : RefCounted<CharacterClassTable> {
+    const char* m_table;
+    bool m_inverted;
+    static PassRefPtr<CharacterClassTable> create(const char* table, bool inverted)
+    {
+        return adoptRef(new CharacterClassTable(table, inverted));
+    }
+
+private:
+    CharacterClassTable(const char* table, bool inverted)
+        : m_table(table)
+        , m_inverted(inverted)
+    {
+    }
+};
+
+struct CharacterClass {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    // All CharacterClass instances have to have the full set of matches and ranges,
+    // they may have an optional table for faster lookups (which must match the
+    // specified matches and ranges)
+    CharacterClass(PassRefPtr<CharacterClassTable> table)
+        : m_table(table)
+    {
+    }
+    Vector<UChar> m_matches;
+    Vector<CharacterRange> m_ranges;
+    Vector<UChar> m_matchesUnicode;
+    Vector<CharacterRange> m_rangesUnicode;
+    RefPtr<CharacterClassTable> m_table;
+};
+
+enum QuantifierType {
+    QuantifierFixedCount,
+    QuantifierGreedy,
+    QuantifierNonGreedy,
+};
+
+struct PatternTerm {
+    enum Type {
+        TypeAssertionBOL,
+        TypeAssertionEOL,
+        TypeAssertionWordBoundary,
+        TypePatternCharacter,
+        TypeCharacterClass,
+        TypeBackReference,
+        TypeForwardReference,
+        TypeParenthesesSubpattern,
+        TypeParentheticalAssertion,
+        TypeDotStarEnclosure,
+    } type;
+    bool m_capture :1;
+    bool m_invert :1;
+    union {
+        UChar patternCharacter;
+        CharacterClass* characterClass;
+        unsigned backReferenceSubpatternId;
+        struct {
+            PatternDisjunction* disjunction;
+            unsigned subpatternId;
+            unsigned lastSubpatternId;
+            bool isCopy;
+            bool isTerminal;
+        } parentheses;
+        struct {
+            bool bolAnchor : 1;
+            bool eolAnchor : 1;
+        } anchors;
+    };
+    QuantifierType quantityType;
+    unsigned quantityCount;
+    int inputPosition;
+    unsigned frameLocation;
+
+    PatternTerm(UChar ch)
+        : type(PatternTerm::TypePatternCharacter)
+        , m_capture(false)
+        , m_invert(false)
+    {
+        patternCharacter = ch;
+        quantityType = QuantifierFixedCount;
+        quantityCount = 1;
+    }
+
+    PatternTerm(CharacterClass* charClass, bool invert)
+        : type(PatternTerm::TypeCharacterClass)
+        , m_capture(false)
+        , m_invert(invert)
+    {
+        characterClass = charClass;
+        quantityType = QuantifierFixedCount;
+        quantityCount = 1;
+    }
+
+    PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool capture = false, bool invert = false)
+        : type(type)
+        , m_capture(capture)
+        , m_invert(invert)
+    {
+        parentheses.disjunction = disjunction;
+        parentheses.subpatternId = subpatternId;
+        parentheses.isCopy = false;
+        parentheses.isTerminal = false;
+        quantityType = QuantifierFixedCount;
+        quantityCount = 1;
+    }
+    
+    PatternTerm(Type type, bool invert = false)
+        : type(type)
+        , m_capture(false)
+        , m_invert(invert)
+    {
+        quantityType = QuantifierFixedCount;
+        quantityCount = 1;
+    }
+
+    PatternTerm(unsigned spatternId)
+        : type(TypeBackReference)
+        , m_capture(false)
+        , m_invert(false)
+    {
+        backReferenceSubpatternId = spatternId;
+        quantityType = QuantifierFixedCount;
+        quantityCount = 1;
+    }
+
+    PatternTerm(bool bolAnchor, bool eolAnchor)
+        : type(TypeDotStarEnclosure)
+        , m_capture(false)
+        , m_invert(false)
+    {
+        anchors.bolAnchor = bolAnchor;
+        anchors.eolAnchor = eolAnchor;
+        quantityType = QuantifierFixedCount;
+        quantityCount = 1;
+    }
+    
+    static PatternTerm ForwardReference()
+    {
+        return PatternTerm(TypeForwardReference);
+    }
+
+    static PatternTerm BOL()
+    {
+        return PatternTerm(TypeAssertionBOL);
+    }
+
+    static PatternTerm EOL()
+    {
+        return PatternTerm(TypeAssertionEOL);
+    }
+
+    static PatternTerm WordBoundary(bool invert)
+    {
+        return PatternTerm(TypeAssertionWordBoundary, invert);
+    }
+    
+    bool invert()
+    {
+        return m_invert;
+    }
+
+    bool capture()
+    {
+        return m_capture;
+    }
+    
+    void quantify(unsigned count, QuantifierType type)
+    {
+        quantityCount = count;
+        quantityType = type;
+    }
+};
+
+struct PatternAlternative {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    PatternAlternative(PatternDisjunction* disjunction)
+        : m_parent(disjunction)
+        , m_onceThrough(false)
+        , m_hasFixedSize(false)
+        , m_startsWithBOL(false)
+        , m_containsBOL(false)
+    {
+    }
+
+    PatternTerm& lastTerm()
+    {
+        ASSERT(m_terms.size());
+        return m_terms[m_terms.size() - 1];
+    }
+    
+    void removeLastTerm()
+    {
+        ASSERT(m_terms.size());
+        m_terms.shrink(m_terms.size() - 1);
+    }
+    
+    void setOnceThrough()
+    {
+        m_onceThrough = true;
+    }
+    
+    bool onceThrough()
+    {
+        return m_onceThrough;
+    }
+
+    Vector<PatternTerm> m_terms;
+    PatternDisjunction* m_parent;
+    unsigned m_minimumSize;
+    bool m_onceThrough : 1;
+    bool m_hasFixedSize : 1;
+    bool m_startsWithBOL : 1;
+    bool m_containsBOL : 1;
+};
+
+struct PatternDisjunction {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    PatternDisjunction(PatternAlternative* parent = 0)
+        : m_parent(parent)
+        , m_hasFixedSize(false)
+    {
+    }
+    
+    ~PatternDisjunction()
+    {
+        deleteAllValues(m_alternatives);
+    }
+
+    PatternAlternative* addNewAlternative()
+    {
+        PatternAlternative* alternative = new PatternAlternative(this);
+        m_alternatives.append(alternative);
+        return alternative;
+    }
+
+    Vector<PatternAlternative*> m_alternatives;
+    PatternAlternative* m_parent;
+    unsigned m_minimumSize;
+    unsigned m_callFrameSize;
+    bool m_hasFixedSize;
+};
+
+// You probably don't want to be calling these functions directly
+// (please to be calling newlineCharacterClass() et al on your
+// friendly neighborhood YarrPattern instance to get nicely
+// cached copies).
+CharacterClass* newlineCreate();
+CharacterClass* digitsCreate();
+CharacterClass* spacesCreate();
+CharacterClass* wordcharCreate();
+CharacterClass* nondigitsCreate();
+CharacterClass* nonspacesCreate();
+CharacterClass* nonwordcharCreate();
+
+struct TermChain {
+    TermChain(PatternTerm term)
+        : term(term)
+    {}
+
+    PatternTerm term;
+    Vector<TermChain> hotTerms;
+};
+
+struct YarrPattern {
+    YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error);
+
+    ~YarrPattern()
+    {
+        deleteAllValues(m_disjunctions);
+        deleteAllValues(m_userCharacterClasses);
+    }
+
+    void reset()
+    {
+        m_numSubpatterns = 0;
+        m_maxBackReference = 0;
+
+        m_containsBackreferences = false;
+        m_containsBOL = false;
+
+        newlineCached = 0;
+        digitsCached = 0;
+        spacesCached = 0;
+        wordcharCached = 0;
+        nondigitsCached = 0;
+        nonspacesCached = 0;
+        nonwordcharCached = 0;
+
+        deleteAllValues(m_disjunctions);
+        m_disjunctions.clear();
+        deleteAllValues(m_userCharacterClasses);
+        m_userCharacterClasses.clear();
+    }
+
+    bool containsIllegalBackReference()
+    {
+        return m_maxBackReference > m_numSubpatterns;
+    }
+
+    CharacterClass* newlineCharacterClass()
+    {
+        if (!newlineCached)
+            m_userCharacterClasses.append(newlineCached = newlineCreate());
+        return newlineCached;
+    }
+    CharacterClass* digitsCharacterClass()
+    {
+        if (!digitsCached)
+            m_userCharacterClasses.append(digitsCached = digitsCreate());
+        return digitsCached;
+    }
+    CharacterClass* spacesCharacterClass()
+    {
+        if (!spacesCached)
+            m_userCharacterClasses.append(spacesCached = spacesCreate());
+        return spacesCached;
+    }
+    CharacterClass* wordcharCharacterClass()
+    {
+        if (!wordcharCached)
+            m_userCharacterClasses.append(wordcharCached = wordcharCreate());
+        return wordcharCached;
+    }
+    CharacterClass* nondigitsCharacterClass()
+    {
+        if (!nondigitsCached)
+            m_userCharacterClasses.append(nondigitsCached = nondigitsCreate());
+        return nondigitsCached;
+    }
+    CharacterClass* nonspacesCharacterClass()
+    {
+        if (!nonspacesCached)
+            m_userCharacterClasses.append(nonspacesCached = nonspacesCreate());
+        return nonspacesCached;
+    }
+    CharacterClass* nonwordcharCharacterClass()
+    {
+        if (!nonwordcharCached)
+            m_userCharacterClasses.append(nonwordcharCached = nonwordcharCreate());
+        return nonwordcharCached;
+    }
+
+    bool m_ignoreCase : 1;
+    bool m_multiline : 1;
+    bool m_containsBackreferences : 1;
+    bool m_containsBOL : 1;
+    unsigned m_numSubpatterns;
+    unsigned m_maxBackReference;
+    PatternDisjunction* m_body;
+    Vector<PatternDisjunction*, 4> m_disjunctions;
+    Vector<CharacterClass*> m_userCharacterClasses;
+
+private:
+    const char* compile(const UString& patternString);
+
+    CharacterClass* newlineCached;
+    CharacterClass* digitsCached;
+    CharacterClass* spacesCached;
+    CharacterClass* wordcharCached;
+    CharacterClass* nondigitsCached;
+    CharacterClass* nonspacesCached;
+    CharacterClass* nonwordcharCached;
+};
+
+} } // namespace JSC::Yarr
+
+#endif // YarrPattern_h
diff --git a/yarr/YarrSyntaxChecker.cpp b/yarr/YarrSyntaxChecker.cpp
new file mode 100644 (file)
index 0000000..51fda94
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 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. 
+ */
+
+#include "config.h"
+#include "YarrSyntaxChecker.h"
+
+#include "YarrParser.h"
+
+namespace JSC { namespace Yarr {
+
+class SyntaxChecker {
+public:
+    void assertionBOL() {}
+    void assertionEOL() {}
+    void assertionWordBoundary(bool) {}
+    void atomPatternCharacter(UChar) {}
+    void atomBuiltInCharacterClass(BuiltInCharacterClassID, bool) {}
+    void atomCharacterClassBegin(bool = false) {}
+    void atomCharacterClassAtom(UChar) {}
+    void atomCharacterClassRange(UChar, UChar) {}
+    void atomCharacterClassBuiltIn(BuiltInCharacterClassID, bool) {}
+    void atomCharacterClassEnd() {}
+    void atomParenthesesSubpatternBegin(bool = true) {}
+    void atomParentheticalAssertionBegin(bool = false) {}
+    void atomParenthesesEnd() {}
+    void atomBackReference(unsigned) {}
+    void quantifyAtom(unsigned, unsigned, bool) {}
+    void disjunction() {}
+};
+
+const char* checkSyntax(const UString& pattern)
+{
+    SyntaxChecker syntaxChecker;
+    return parse(syntaxChecker, pattern);
+}
+
+}} // JSC::YARR
diff --git a/yarr/YarrSyntaxChecker.h b/yarr/YarrSyntaxChecker.h
new file mode 100644 (file)
index 0000000..2013671
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 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 YarrSyntaxChecker_h
+#define YarrSyntaxChecker_h
+
+#include <runtime/UString.h>
+
+namespace JSC { namespace Yarr {
+
+const char* checkSyntax(const UString& pattern);
+
+}} // JSC::YARR
+
+#endif // YarrSyntaxChecker_h
+
diff --git a/yarr/yarr.pri b/yarr/yarr.pri
new file mode 100644 (file)
index 0000000..a7b1242
--- /dev/null
@@ -0,0 +1,7 @@
+# Yet Another Regex Runtime - Qt4 build info
+
+SOURCES += \
+    yarr/YarrInterpreter.cpp \
+    yarr/YarrPattern.cpp \
+    yarr/YarrSyntaxChecker.cpp
+