]> 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())
     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));
 #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"
 #define APIShims_h
 
 #include "CallFrame.h"
+#include "GCActivityCallback.h"
 #include "JSLock.h"
 #include <wtf/WTFThreadData.h>
 
 #include "JSLock.h"
 #include <wtf/WTFThreadData.h>
 
@@ -38,8 +39,12 @@ protected:
         : m_globalData(globalData)
         , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
     {
         : m_globalData(globalData)
         , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
     {
+        UNUSED_PARAM(registerThread);
+#if ENABLE(JSC_MULTIPLE_THREADS)
         if (registerThread)
         if (registerThread)
-            globalData->heap.registerThread();
+            globalData->heap.machineThreads().addCurrentThread();
+#endif
+        m_globalData->heap.activityCallback()->synchronize();
         m_globalData->timeoutChecker.start();
     }
 
         m_globalData->timeoutChecker.start();
     }
 
@@ -85,6 +90,7 @@ public:
 
     ~APICallbackShim()
     {
 
     ~APICallbackShim()
     {
+        m_globalData->heap.activityCallback()->synchronize();
         wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable);
     }
 
         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 */
 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)
 
 #undef JS_EXPORT
 #if defined(JS_NO_EXPORT)
-    #define JS_EXPORT
+#define JS_EXPORT
 #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__)
 #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
 #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
 #endif
 
 #ifdef __cplusplus
index 9c5f6d73e6e1ab66503fd177f6817400a399335b..fa9d216dd11250127ee685fe1ec8d59ff268c99e 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "APIShims.h"
 #include "APICast.h"
 
 #include "APIShims.h"
 #include "APICast.h"
+#include <runtime/Error.h>
 #include <runtime/JSGlobalObject.h>
 #include <runtime/JSLock.h>
 #include <runtime/ObjectPrototype.h>
 #include <runtime/JSGlobalObject.h>
 #include <runtime/JSLock.h>
 #include <runtime/ObjectPrototype.h>
 
 namespace JSC {
 
 
 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)
 {
     , m_class(jsClass)
     , m_callback(callback)
 {
+    ASSERT(inherits(&s_info));
     if (m_class)
         JSClassRetain(jsClass);
 }
     if (m_class)
         JSClassRetain(jsClass);
 }
@@ -52,17 +54,18 @@ JSCallbackConstructor::~JSCallbackConstructor()
         JSClassRelease(m_class);
 }
 
         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) {
     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++)
         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;
 
         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)
             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)
 }
 
 ConstructType JSCallbackConstructor::getConstructData(ConstructData& constructData)
index e52994724e2fd0d4b9c290c5890bceccaeb2e923..64b237dfd3d8baacc8a99389380f05edea69212d 100644 (file)
 #define JSCallbackConstructor_h
 
 #include "JSObjectRef.h"
 #define JSCallbackConstructor_h
 
 #include "JSObjectRef.h"
-#include <runtime/JSObject.h>
+#include <runtime/JSObjectWithGlobalObject.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-class JSCallbackConstructor : public JSObject {
+class JSCallbackConstructor : public JSObjectWithGlobalObject {
 public:
 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; }
     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:
     }
 
 protected:
@@ -49,7 +49,6 @@ protected:
 
 private:
     virtual ConstructType getConstructData(ConstructData&);
 
 private:
     virtual ConstructType getConstructData(ConstructData&);
-    virtual const ClassInfo* classInfo() const { return &info; }
 
     JSClassRef m_class;
     JSObjectCallAsConstructorCallback m_callback;
 
     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 "APIShims.h"
 #include "APICast.h"
 #include "CodeBlock.h"
+#include "ExceptionHelpers.h"
 #include "JSFunction.h"
 #include "FunctionPrototype.h"
 #include <runtime/JSGlobalObject.h>
 #include "JSFunction.h"
 #include "FunctionPrototype.h"
 #include <runtime/JSGlobalObject.h>
@@ -39,35 +40,36 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSCallbackFunction);
 
 
 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)
 {
     , 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);
 {
     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++)
     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);
 
     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)
     }
     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)
 }
 
 CallType JSCallbackFunction::getCallData(CallData& callData)
index 10dae6b73f0437c8a68f743573deaf601e6fca8c..55c9ed4ae87c2290efb480446e98065d9c1849ef 100644 (file)
@@ -33,22 +33,21 @@ namespace JSC {
 
 class JSCallbackFunction : public InternalFunction {
 public:
 
 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
     
     // 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&);
     }
 
 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;
 };
 
     JSObjectCallAsFunctionCallback m_callback;
 };
index b36c19414473121bce973eab757dd36a1da995b0..6a7462a9040f8ca1d7fb24ab959fd6003587cb64 100644 (file)
 #include "config.h"
 #include "JSCallbackObject.h"
 
 #include "config.h"
 #include "JSCallbackObject.h"
 
-#include "Collector.h"
+#include "Heap.h"
 #include <wtf/text/StringHash.h>
 
 namespace JSC {
 
 #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.
 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
 } // 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
  * 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 "JSObjectRef.h"
 #include "JSValueRef.h"
 #include "JSObject.h"
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-struct JSCallbackObjectData {
+struct JSCallbackObjectData : WeakHandleOwner {
     JSCallbackObjectData(void* privateData, JSClassRef jsClass)
         : privateData(privateData)
         , jsClass(jsClass)
     JSCallbackObjectData(void* privateData, JSClassRef jsClass)
         : privateData(privateData)
         , jsClass(jsClass)
@@ -53,11 +54,11 @@ struct JSCallbackObjectData {
         return m_privateProperties->getPrivateProperty(propertyName);
     }
     
         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)
     {
         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)
     }
     
     void deletePrivateProperty(const Identifier& propertyName)
@@ -67,11 +68,11 @@ struct JSCallbackObjectData {
         m_privateProperties->deletePrivateProperty(propertyName);
     }
 
         m_privateProperties->deletePrivateProperty(propertyName);
     }
 
-    void markChildren(MarkStack& markStack)
+    void visitChildren(SlotVisitor& visitor)
     {
         if (!m_privateProperties)
             return;
     {
         if (!m_privateProperties)
             return;
-        m_privateProperties->markChildren(markStack);
+        m_privateProperties->visitChildren(visitor);
     }
 
     void* privateData;
     }
 
     void* privateData;
@@ -79,56 +80,57 @@ struct JSCallbackObjectData {
     struct JSPrivatePropertyMap {
         JSValue getPrivateProperty(const Identifier& propertyName) const
         {
     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();
             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)
         {
         }
         
         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)
         {
             for (PrivatePropertyMap::iterator ptr = m_propertyMap.begin(); ptr != m_propertyMap.end(); ++ptr) {
                 if (ptr->second)
-                    markStack.append(ptr->second);
+                    visitor.append(&ptr->second);
             }
         }
 
     private:
             }
         }
 
     private:
-        typedef HashMap<RefPtr<UString::Rep>, JSValue, IdentifierRepHash> PrivatePropertyMap;
+        typedef HashMap<RefPtr<StringImpl>, WriteBarrier<Unknown>, IdentifierRepHash> PrivatePropertyMap;
         PrivatePropertyMap m_propertyMap;
     };
     OwnPtr<JSPrivatePropertyMap> m_privateProperties;
         PrivatePropertyMap m_propertyMap;
     };
     OwnPtr<JSPrivatePropertyMap> m_privateProperties;
+    virtual void finalize(Handle<Unknown>, void*);
 };
 
     
 template <class Base>
 class JSCallbackObject : public Base {
 public:
 };
 
     
 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();
 
 
     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;
 
 
     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
     }
     
     JSValue getPrivateProperty(const Identifier& propertyName) const
@@ -136,9 +138,9 @@ public:
         return m_callbackObjectData->getPrivateProperty(propertyName);
     }
     
         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)
     }
     
     void deletePrivateProperty(const Identifier& propertyName)
@@ -147,13 +149,12 @@ public:
     }
 
 protected:
     }
 
 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&);
 
 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&);
     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 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);
  
     }
 
     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&);
 
     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 "APIShims.h"
 #include "APICast.h"
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSCallbackFunction.h"
 #include "JSClassRef.h"
 #include "JSCallbackFunction.h"
 #include "JSClassRef.h"
+#include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
 #include "JSObjectRef.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)
 {
 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>
     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>
     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());
 }
     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));
     }
         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>
 }
 
 template <class Base>
@@ -133,7 +137,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
                 value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
             if (exception) {
                 value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 slot.setValue(jsUndefined());
                 return true;
             }
                 slot.setValue(jsUndefined());
                 return true;
             }
@@ -144,14 +148,17 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
         }
         
         if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) {
         }
         
         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 (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
-            if (staticFunctions->contains(propertyName.ustring().rep())) {
+            if (staticFunctions->contains(propertyName.impl())) {
                 slot.setCustom(this, staticFunctionGetter);
                 return true;
             }
                 slot.setCustom(this, staticFunctionGetter);
                 return true;
             }
@@ -161,12 +168,6 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie
     return Base::getOwnPropertySlot(exec, propertyName, slot);
 }
 
     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)
 {
 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)
                 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 (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) {
                 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)
                         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 (result || exception)
                         return;
-                } else
-                    throwError(exec, ReferenceError, "Attempt to set a property that is not settable.");
+                }
             }
         }
         
         if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
             }
         }
         
         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;
                 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;
             }
         }
                 return;
             }
         }
@@ -263,13 +263,13 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p
                 result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception);
             }
             if (exception)
                 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 (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;
                 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 (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;
                 if (entry->attributes & kJSPropertyAttributeDontDelete)
                     return false;
                 return true;
@@ -307,17 +307,18 @@ ConstructType JSCallbackObject<Base>::getConstructData(ConstructData& constructD
 }
 
 template <class Base>
 }
 
 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) {
     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++)
             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;
             {
             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)
                 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
         }
     }
     
     ASSERT_NOT_REACHED(); // getConstructData should prevent us from reaching here
-    return 0;
+    return JSValue::encode(JSValue());
 }
 
 template <class Base>
 }
 
 template <class Base>
@@ -350,7 +351,7 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue
                 result = hasInstance(execRef, thisRef, valueRef, &exception);
             }
             if (exception)
                 result = hasInstance(execRef, thisRef, valueRef, &exception);
             }
             if (exception)
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
             return result;
         }
     }
             return result;
         }
     }
@@ -370,18 +371,18 @@ CallType JSCallbackObject<Base>::getCallData(CallData& callData)
 }
 
 template <class Base>
 }
 
 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);
 {
     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) {
         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++)
             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;
             {
             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)
                 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
         }
     }
     
     ASSERT_NOT_REACHED(); // getCallData should prevent us from reaching here
-    return JSValue();
+    return JSValue::encode(JSValue());
 }
 
 template <class Base>
 }
 
 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) {
             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));
                 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) {
             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));
                 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) {
                 value = convertToType(ctx, thisRef, kJSTypeNumber, &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 return 0;
             }
 
                 return 0;
             }
 
@@ -483,7 +484,7 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const
                 value = convertToType(ctx, thisRef, kJSTypeString, &exception);
             }
             if (exception) {
                 value = convertToType(ctx, thisRef, kJSTypeString, &exception);
             }
             if (exception) {
-                exec->setException(toJS(exec, exception));
+                throwError(exec, toJS(exec, exception));
                 return "";
             }
             if (value)
                 return "";
             }
             if (value)
@@ -516,16 +517,14 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const
 }
 
 template <class Base>
 }
 
 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;
     
     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 (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());
                 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) {
                         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 jsUndefined();
                     }
                     if (value)
                         return toJS(exec, value);
                 }
 
-    return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback.");
+    return JSValue();
 }
 
 template <class Base>
 }
 
 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)) {
     
     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) {
                 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 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>
 }
 
 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) {
                 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 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
 }
 
 } // 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)
 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))
 
     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());
 }
 
     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);
             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;
         }
             }
             ++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);
             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;
         }
             }
             ++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. 
 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();
 
     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));
 }
 
     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;
 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
     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()));
 }
 
     return adoptRef(new OpaqueJSClass(&definition, protoClass.get()));
 }
 
-OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass)
+OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSClass* jsClass)
     : m_class(jsClass)
 {
     if (jsClass->m_staticValues) {
     : 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);
             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;
         }
     } 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);
             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
         }
             
     } else
@@ -209,14 +204,14 @@ OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec)
 {
     OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second;
     if (!contextData)
 {
     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 *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)
 }
 
 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
 
     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))
         if (parentClass) {
             if (JSObject* prototype = parentClass->prototype(exec))
-                jsClassData.cachedPrototype->setPrototype(prototype);
+                jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype);
         }
     }
     return jsClassData.cachedPrototype.get();
         }
     }
     return jsClassData.cachedPrototype.get();
index ae60aadef91baa47b8e345f7ed4fb8263834457b..d346cc5dfcb036508e3915f790f11b71a1e378c8 100644 (file)
 
 #include "JSObjectRef.h"
 
 
 #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/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)
     {
     StaticValueEntry(JSObjectGetPropertyCallback _getProperty, JSObjectSetPropertyCallback _setProperty, JSPropertyAttributes _attributes)
         : getProperty(_getProperty), setProperty(_setProperty), attributes(_attributes)
     {
@@ -46,7 +47,9 @@ struct StaticValueEntry : FastAllocBase {
     JSPropertyAttributes attributes;
 };
 
     JSPropertyAttributes attributes;
 };
 
-struct StaticFunctionEntry : FastAllocBase {
+struct StaticFunctionEntry {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes)
         : callAsFunction(_callAsFunction), attributes(_attributes)
     {
     StaticFunctionEntry(JSObjectCallAsFunctionCallback _callAsFunction, JSPropertyAttributes _attributes)
         : callAsFunction(_callAsFunction), attributes(_attributes)
     {
@@ -56,15 +59,17 @@ struct StaticFunctionEntry : FastAllocBase {
     JSPropertyAttributes attributes;
 };
 
     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 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:
     ~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;
 
     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();
     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 "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 "JSCallbackObject.h"
 #include "JSClassRef.h"
 #include "JSGlobalObject.h"
 #include "JSObject.h"
+#include "UStringBuilder.h"
 #include <wtf/text/StringHash.h>
 
 #include <wtf/text/StringHash.h>
 
+
 #if OS(DARWIN)
 #include <mach-o/dyld.h>
 
 #if OS(DARWIN)
 #include <mach-o/dyld.h>
 
@@ -46,7 +50,7 @@ using namespace JSC;
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
 JSContextGroupRef JSContextGroupCreate()
 {
     initializeThreading();
-    return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).releaseRef());
+    return toRef(JSGlobalData::createContextGroup(ThreadStackTypeSmall).leakRef());
 }
 
 JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
 }
 
 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 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
     {
     if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
 #else
     {
@@ -93,16 +97,16 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
 #endif
 
     if (!globalObjectClass) {
 #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()));
     }
 
         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();
     ExecState* exec = globalObject->globalExec();
     JSValue prototype = globalObjectClass->prototype(exec);
     if (!prototype)
         prototype = jsNull();
-    globalObject->resetPrototype(prototype);
+    globalObject->resetPrototype(*globalData, prototype);
     return JSGlobalContextRetain(toGlobalRef(exec));
 }
 
     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
     // * 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 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();
         globalData.heap.destroy();
-    else if (releasingGlobalObject)
-        globalData.heap.collectAllGarbage();
+    } else if (releasingGlobalObject) {
+        globalData.heap.activityCallback()->synchronize();
+        (*globalData.heap.activityCallback())();
+    }
 
     globalData.deref();
 
 
     globalData.deref();
 
@@ -173,3 +181,60 @@ JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
 
     return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
 }
 
     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);
 
 */
 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
 #ifdef __cplusplus
 }
 #endif
index 8fdbdab9059300a8af7fa22f428dd3bc0eb987d5..2df010a5189f7c6ed2c9aef9c18e31f37089543b 100644 (file)
@@ -59,7 +59,7 @@ JSClassRef JSClassCreate(const JSClassDefinition* definition)
         ? OpaqueJSClass::createNoAutomaticPrototype(definition)
         : OpaqueJSClass::create(definition);
     
         ? OpaqueJSClass::createNoAutomaticPrototype(definition)
         : OpaqueJSClass::create(definition);
     
-    return jsClass.release().releaseRef();
+    return jsClass.release().leakRef();
 }
 
 JSClassRef JSClassRetain(JSClassRef jsClass)
 }
 
 JSClassRef JSClassRetain(JSClassRef jsClass)
@@ -79,11 +79,11 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
     APIEntryShim entryShim(exec);
 
     if (!jsClass)
     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))
     if (JSObject* prototype = jsClass->prototype(exec))
-        object->setPrototype(prototype);
+        object->setPrototype(exec->globalData(), prototype);
 
     return toRef(object);
 }
 
     return toRef(object);
 }
@@ -95,7 +95,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name,
 
     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
     
 
     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)
 }
 
 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();
 
     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);
 }
 
     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()));
 
         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());
     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]));
 
     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());
     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);
 
     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());
     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]));
 
     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());
     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* 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)
 }
 
 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
@@ -341,10 +340,10 @@ void* JSObjectGetPrivate(JSObjectRef object)
 {
     JSObject* jsObject = toJS(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();
         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;
 }
     
     return 0;
 }
@@ -353,11 +352,12 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data)
 {
     JSObject* jsObject = toJS(object);
     
 {
     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;
         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;
     }
         
         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()));
     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);
         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);
 }
 
     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);
     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()));
     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;
     }
         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;
         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()));
     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;
     }
         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;
         return true;
     }
     return false;
@@ -481,7 +481,9 @@ JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size
     return result;
 }
 
     return result;
 }
 
-struct OpaqueJSPropertyNameArray : FastAllocBase {
+struct OpaqueJSPropertyNameArray {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     OpaqueJSPropertyNameArray(JSGlobalData* globalData)
         : refCount(0)
         , globalData(globalData)
     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)
     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);
 }
     
     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
  *
  * 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
 
 #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); }
 #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 };
 
 
 enum AdoptTag { Adopt };
 
-template <typename T> class JSRetainPtr {
+template<typename T> class JSRetainPtr {
 public:
 public:
-    JSRetainPtr() : m_ptr(0) {}
+    JSRetainPtr() : m_ptr(0) { }
     JSRetainPtr(T ptr) : m_ptr(ptr) { if (ptr) JSRetain(ptr); }
     JSRetainPtr(T ptr) : m_ptr(ptr) { if (ptr) JSRetain(ptr); }
-
     JSRetainPtr(AdoptTag, T ptr) : m_ptr(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 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; }
     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&);
     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);
     JSRetainPtr& operator=(T);
-    template <typename U> JSRetainPtr& operator=(U*);
+    template<typename U> JSRetainPtr& operator=(U*);
 
     void adopt(T);
     
     void swap(JSRetainPtr&);
 
 
     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;
 };
 
 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)
 {
     T optr = o.get();
     if (optr)
@@ -87,7 +125,7 @@ template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(const JSR
     return *this;
 }
 
     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)
 {
     T optr = o.get();
     if (optr)
@@ -99,7 +137,7 @@ template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T
     return *this;
 }
 
     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);
 {
     if (optr)
         JSRetain(optr);
@@ -110,7 +148,7 @@ template <typename T> inline JSRetainPtr<T>& JSRetainPtr<T>::operator=(T optr)
     return *this;
 }
 
     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;
 {
     T ptr = m_ptr;
     m_ptr = optr;
@@ -118,7 +156,7 @@ template <typename T> inline void JSRetainPtr<T>::adopt(T optr)
         JSRelease(ptr);
 }
 
         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);
 {
     if (optr)
         JSRetain(optr);
@@ -129,42 +167,42 @@ template <typename T> template <typename U> inline JSRetainPtr<T>& JSRetainPtr<T
     return *this;
 }
 
     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);
 }
 
 {
     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);
 }
 
 {
     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(); 
 }
 
 { 
     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; 
 }
 
 { 
     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(); 
 }
 
 {
     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(); 
 }
 
 { 
     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; 
 }
 
 {
     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(); 
 }
 { 
     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();
 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)
 }
 
 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))
         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.
     }
 
     // Null string.
-    return OpaqueJSString::create().releaseRef();
+    return OpaqueJSString::create().leakRef();
 }
 
 JSStringRef JSStringRetain(JSStringRef string)
 }
 
 JSStringRef JSStringRetain(JSStringRef string)
index 51871b121dbc5107ade79a319eed1660e704186a..c5c154402cb558154d5b2a82289405a428d94a3b 100644 (file)
@@ -38,7 +38,7 @@ extern "C" {
 #endif
 
 #if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) \
 #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.
 /*!
 @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.
  * 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"
 
 #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) {
     // 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);
         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 {
     } 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()) {
     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);
             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;
 }
     }
     return false;
 }
@@ -219,7 +219,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value)
     if (isnan(value))
         value = NaN;
 
     if (isnan(value))
         value = NaN;
 
-    return toRef(exec, jsNumber(exec, value));
+    return toRef(exec, jsNumber(value));
 }
 
 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
 }
 
 JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string)
@@ -234,7 +234,8 @@ JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string)
 {
     ExecState* exec = toJS(ctx);
     APIEntryShim entryShim(exec);
 {
     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());
 }
 
     return toRef(exec, parser.tryLiteralParse());
 }
 
@@ -252,7 +253,7 @@ JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsig
         exec->clearException();
         return 0;
     }
         exec->clearException();
         return 0;
     }
-    return OpaqueJSString::create(result).releaseRef();
+    return OpaqueJSString::create(result).leakRef();
 }
 
 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
 }
 
 bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
@@ -295,7 +296,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef*
         exec->clearException();
         stringRef.clear();
     }
         exec->clearException();
         stringRef.clear();
     }
-    return stringRef.release().releaseRef();
+    return stringRef.release().leakRef();
 }
 
 JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
 }
 
 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 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:
 
 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 "JSValue.h"
 #include "JSWeakObjectMapRefInternal.h"
 #include <wtf/HashMap.h>
-#include <wtf/RefCounted.h>
 #include <wtf/text/StringHash.h>
 
 using namespace WTF;
 #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;
     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)
 }
 
 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)));
 }
 
     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);
 {
     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
 }
 
 #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
  @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);
 
  */
 JS_EXPORT JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef ctx, void* data, JSWeakMapDestroyedCallback destructor);
 
@@ -79,14 +78,12 @@ JS_EXPORT JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef ma
 
 /*!
  @function
 
 /*!
  @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 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
 }
 
 #ifdef __cplusplus
 }
index f740abe3b135c36d24aaba853387b1ffdb825275..9a116e6b2f63937d0d02d088c61a554c9fc23b86 100644 (file)
@@ -35,7 +35,7 @@ using namespace JSC;
 PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring)
 {
     if (!ustring.isNull())
 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;
 }
 
     return 0;
 }
 
@@ -43,7 +43,7 @@ UString OpaqueJSString::ustring() const
 {
     if (this && m_characters)
         return UString(m_characters, m_length);
 {
     if (this && m_characters)
         return UString(m_characters, m_length);
-    return UString::null();
+    return UString();
 }
 
 Identifier OpaqueJSString::identifier(JSGlobalData* globalData) const
 }
 
 Identifier OpaqueJSString::identifier(JSGlobalData* globalData) const
index 473c815069189f57b77be0f46f724777fba7ab49..69c0962a66703b57b3384e5b1ead7bc467364caf 100644 (file)
@@ -33,7 +33,7 @@ namespace JSC {
     class JSGlobalData;
 }
 
     class JSGlobalData;
 }
 
-struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> {
+struct OpaqueJSString : public ThreadSafeRefCounted<OpaqueJSString> {
 
     static PassRefPtr<OpaqueJSString> create() // null
     {
 
     static PassRefPtr<OpaqueJSString> create() // null
     {
@@ -54,7 +54,7 @@ struct OpaqueJSString : public ThreadSafeShared<OpaqueJSString> {
     JSC::Identifier identifier(JSC::JSGlobalData*) const;
 
 private:
     JSC::Identifier identifier(JSC::JSGlobalData*) const;
 
 private:
-    friend class WTF::ThreadSafeShared<OpaqueJSString>;
+    friend class WTF::ThreadSafeRefCounted<OpaqueJSString>;
 
     OpaqueJSString()
         : m_characters(0)
 
     OpaqueJSString()
         : m_characters(0)
index 28b4ec8137fcb0eff0c0c0d52772333eeac51aec..e82d41d77b9b62a36049a499910f7c380a75f3c4 100644 (file)
 #include <wtf/Assertions.h>
 #include <wtf/UnusedParam.h>
 
 #include <wtf/Assertions.h>
 #include <wtf/UnusedParam.h>
 
+#if OS(WINDOWS)
+#include <windows.h>
+#endif
+
 #if COMPILER(MSVC)
 
 #include <wtf/MathExtras.h>
 #if COMPILER(MSVC)
 
 #include <wtf/MathExtras.h>
@@ -307,8 +311,19 @@ static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef objec
     return JSValueMakeNull(context);
 }
 
     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 },
 static JSStaticValue evilStaticValues[] = {
     { "nullGetSet", 0, 0, kJSPropertyAttributeNone },
+    { "nullGetForwardSet", 0, MyObject_set_nullGetForwardSet, kJSPropertyAttributeNone },
     { 0, 0, 0, 0 }
 };
 
     { 0, 0, 0, 0 }
 };
 
@@ -351,6 +366,111 @@ static JSClassRef MyObject_class(JSContextRef context)
     return jsClass;
 }
 
     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);
 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;
 }
 
     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[])
 {
 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];
     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);
 
     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);
     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");
     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");
     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");
         printf("PASS: Set private property.\n");
-    }
+    aStackRef = 0;
     if (JSObjectSetPrivateProperty(context, aHeapRef, privatePropertyName, aHeapRef)) {
         printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n");
     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");
         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;
     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");
         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");
     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);
     JSGarbageCollect(context);
-    
+
     for (int i = 0; i < 10000; i++)
         JSObjectMake(context, 0, 0);
 
     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 (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);
     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");
 
 
     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;
     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");
 
 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) {
 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);
 
 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");
 
 shouldThrow("MyObject.nullCall()");
 shouldThrow("MyObject.hasPropertyLie");
 
@@ -246,6 +249,32 @@ shouldThrow("String(EvilExceptionObject)");
 
 shouldBe("EmptyObject", "[object CallbackObject]");
 
 
 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";
 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
 #
 # 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 \
 VPATH = \
     $(JavaScriptCore) \
     $(JavaScriptCore)/parser \
-    $(JavaScriptCore)/pcre \
     $(JavaScriptCore)/docs \
     $(JavaScriptCore)/runtime \
     $(JavaScriptCore)/interpreter \
     $(JavaScriptCore)/docs \
     $(JavaScriptCore)/runtime \
     $(JavaScriptCore)/interpreter \
@@ -36,19 +35,31 @@ VPATH = \
 
 .PHONY : all
 all : \
 
 .PHONY : all
 all : \
+    ArrayConstructor.lut.h \
     ArrayPrototype.lut.h \
     ArrayPrototype.lut.h \
-    chartables.c \
+    BooleanPrototype.lut.h \
+    DateConstructor.lut.h \
     DatePrototype.lut.h \
     DatePrototype.lut.h \
-    Grammar.cpp \
+    ErrorPrototype.lut.h \
+    HeaderDetection.h \
     JSONObject.lut.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 \
     Lexer.lut.h \
     MathObject.lut.h \
     NumberConstructor.lut.h \
+    NumberPrototype.lut.h \
+    ObjectConstructor.lut.h \
+    ObjectPrototype.lut.h \
     RegExpConstructor.lut.h \
     RegExpConstructor.lut.h \
+    RegExpPrototype.lut.h \
+    RegExpJitTables.h \
     RegExpObject.lut.h \
     RegExpObject.lut.h \
+    StringConstructor.lut.h \
     StringPrototype.lut.h \
     docs/bytecode.html \
     StringPrototype.lut.h \
     docs/bytecode.html \
-    RegExpJitTables.h \
 #
 
 # lookup tables for classes
 #
 
 # lookup tables for classes
@@ -58,24 +69,38 @@ all : \
 Lexer.lut.h: create_hash_table Keywords.table
        $^ > $@
 
 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 $^ $@
 
 docs/bytecode.html: make-bytecode-docs.pl Interpreter.cpp 
        perl $^ $@
 
-#character tables for Yarr
+# character tables for Yarr
+
 RegExpJitTables.h: create_regex_tables
        python $^ > $@
 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 += \
 }
 
 LUT_FILES += \
+    runtime/ArrayConstructor.cpp \
     runtime/ArrayPrototype.cpp \
     runtime/ArrayPrototype.cpp \
+    runtime/BooleanPrototype.cpp \
+    runtime/DateConstructor.cpp \
     runtime/DatePrototype.cpp \
     runtime/DatePrototype.cpp \
+    runtime/ErrorPrototype.cpp \
+    runtime/JSGlobalObject.cpp \
     runtime/JSONObject.cpp \
     runtime/MathObject.cpp \
     runtime/NumberConstructor.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/RegExpConstructor.cpp \
     runtime/RegExpObject.cpp \
-    runtime/StringPrototype.cpp
+    runtime/RegExpPrototype.cpp \
+    runtime/StringConstructor.cpp \
+    runtime/StringPrototype.cpp \
 
 KEYWORDLUT_FILES += \
     parser/Keywords.table
 
 
 KEYWORDLUT_FILES += \
     parser/Keywords.table
 
-JSCBISON += \
-    parser/Grammar.y
-
-RVCT_STUB_FILES += \
+JIT_STUB_FILES += \
     jit/JITStubs.cpp
 
 defineTest(addExtraCompiler) {
     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)
 
 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.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)
 
 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
 
 #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)
 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 += \
 
 bin_PROGRAMS += \
-       Programs/jsc
+       Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@$(EXEEXT)
 
 noinst_PROGRAMS += \
 
 noinst_PROGRAMS += \
+       Programs/jsc \
        Programs/minidom
 
        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)
 Programs_minidom_CPPFLAGS = \
        $(global_cppflags) \
        $(javascriptcore_cppflags)
@@ -597,58 +102,72 @@ Programs_minidom_CFLAGS = \
        $(GLOBALDEPS_CFLAGS)
 
 Programs_minidom_LDADD = \
        $(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_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)
 
        $(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)
 
        -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
 
 # Clean rules for JavaScriptCore
+# FIXME: Should this list be generated from javascriptcore_built_nosources?
 CLEANFILES += \
 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 \
+       Programs/jsc-@WEBKITGTK_API_MAJOR_VERSION@ \
        Programs/minidom
        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>
        <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>
        <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
 _JSContextGroupCreate
 _JSContextGroupRelease
 _JSContextGroupRetain
+_JSContextCreateBacktrace
 _JSEndProfiling
 _JSEvaluateScript
 _JSGarbageCollect
 _JSEndProfiling
 _JSEvaluateScript
 _JSGarbageCollect
@@ -87,38 +88,43 @@ _JSValueUnprotect
 _JSWeakObjectMapClear
 _JSWeakObjectMapCreate
 _JSWeakObjectMapGet
 _JSWeakObjectMapClear
 _JSWeakObjectMapCreate
 _JSWeakObjectMapGet
+_JSWeakObjectMapRemove
 _JSWeakObjectMapSet
 _WTFLog
 _WTFLogVerbose
 _WTFReportArgumentAssertionFailure
 _WTFReportAssertionFailure
 _WTFReportAssertionFailureWithMessage
 _JSWeakObjectMapSet
 _WTFLog
 _WTFLogVerbose
 _WTFReportArgumentAssertionFailure
 _WTFReportAssertionFailure
 _WTFReportAssertionFailureWithMessage
+_WTFReportBacktrace
 _WTFReportError
 _WTFReportFatalError
 _WebCoreWebThreadIsLockedOrDisabled
 _WTFReportError
 _WTFReportFatalError
 _WebCoreWebThreadIsLockedOrDisabled
-__Z12jsRegExpFreeP8JSRegExp
-__Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc
-__Z15jsRegExpExecutePK8JSRegExpPKtiiPii
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
 __ZN14OpaqueJSString6createERKN3JSC7UStringE
-__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN7WebCore10StringImplE
-__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN7WebCore10StringImplE
+__ZN3JSC10HandleHeap12writeBarrierEPNS_7JSValueERKS1_
+__ZN3JSC10HandleHeap4growEv
+__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN3WTF10StringImplE
+__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN3WTF10StringImplE
 __ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_12JSGlobalDataE
 __ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_9ExecStateE
 __ZN3JSC10Identifier3addEPNS_9ExecStateEPKc
 __ZN3JSC10Identifier4fromEPNS_9ExecStateEi
 __ZN3JSC10Identifier4fromEPNS_9ExecStateEj
 __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
 __ZN3JSC11ParserArena5resetEv
 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
-__ZN3JSC12DateInstance4infoE
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd
-__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd
+__ZN3JSC11createErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC11regExpFlagsERKNS_7UStringE
+__ZN3JSC12DateInstance6s_infoE
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEPNS_9StructureEd
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC12JSGlobalData11jsArrayVPtrE
 __ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC12JSGlobalData11jsArrayVPtrE
 __ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE
@@ -128,8 +134,15 @@ __ZN3JSC12JSGlobalData13startSamplingEv
 __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC12JSGlobalData14resetDateCacheEv
 __ZN3JSC12JSGlobalData14sharedInstanceEv
 __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE
 __ZN3JSC12JSGlobalData14resetDateCacheEv
 __ZN3JSC12JSGlobalData14sharedInstanceEv
+__ZN3JSC12JSGlobalData15dumpRegExpTraceEv
+__ZN3JSC12JSGlobalData22clearBuiltinStructuresEv
+#ifndef NDEBUG
+__ZN3JSC12JSGlobalData23releaseExecutableMemoryEv
+#endif
 __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalDataD1Ev
 __ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE
 __ZN3JSC12JSGlobalDataD1Ev
+__ZN3JSC12RegExpObject6s_infoE
+__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEPNS_9StructureEPNS_6RegExpE
 __ZN3JSC12SamplingTool5setupEv
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
 __ZN3JSC12SmallStrings27createSingleCharacterStringEPNS_12JSGlobalDataEh
 __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
 __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
 __ZN3JSC12nonInlineNaNEv
 __ZN3JSC13SamplingFlags4stopEv
 __ZN3JSC13SamplingFlags5startEv
 __ZN3JSC13SamplingFlags7s_flagsE
 __ZN3JSC13StatementNode6setLocEii
 __ZN3JSC14JSGlobalObject10globalExecEv
+__ZN3JSC14JSGlobalObject11disableEvalEv
 __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
 __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
 __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
 __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
-__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject13visitChildrenERNS_9MarkStackE
+__ZN3JSC14JSGlobalObject16addStaticGlobalsEPNS0_18GlobalPropertyInfoEi
 __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
 __ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
-__ZN3JSC14JSGlobalObject25destroyJSGlobalObjectDataEPv
+__ZN3JSC14JSGlobalObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC14JSGlobalObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE  
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
+__ZN3JSC14JSGlobalObject6s_infoE
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3JSC14MachineThreads16addCurrentThreadEv
+__ZN3JSC14MachineThreads29makeUsableFromMultipleThreadsEv
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
+__ZN3JSC14ScopeChainNode6s_infoE
 __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
 __ZN3JSC14TimeoutChecker5resetEv
 __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
 __ZN3JSC16InternalFunction4nameEPNS_9ExecStateE
-__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_10IdentifierE
+__ZN3JSC16InternalFunction6s_infoE
+__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEPNS_14JSGlobalObjectEPNS_9StructureERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC16toUInt32SlowCaseEdRb
+__ZN3JSC16createRangeErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC16slowValidateCellEPNS_14JSGlobalObjectE
+__ZN3JSC16slowValidateCellEPNS_6JSCellE
+__ZN3JSC16throwSyntaxErrorEPNS_9ExecStateE
 __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb
 __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
 __ZN3JSC18PropertyDescriptor11setWritableEb
 __ZN3JSC18PropertyDescriptor12setUndefinedEv
 __ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
@@ -186,30 +211,40 @@ __ZN3JSC18PropertyDescriptor17defaultAttributesE
 __ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
 __ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
 __ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
 __ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
 __ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
 __ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
+__ZN3JSC19SourceProviderCache5clearEv
+__ZN3JSC19SourceProviderCacheD1Ev
 __ZN3JSC19initializeThreadingEv
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
 __ZN3JSC19initializeThreadingEv
 __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
+__ZN3JSC20createReferenceErrorEPNS_9ExecStateERKNS_7UStringE
+__ZN3JSC22globalMemoryStatisticsEv
+__ZN3JSC22objectConstructorTableE
 __ZN3JSC23AbstractSamplingCounter4dumpEv
 __ZN3JSC23AbstractSamplingCounter4dumpEv
-__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
+__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
 __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
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
 __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
 __ZN3JSC3NaNE
-__ZN3JSC4Heap14primaryHeapEndEv
-__ZN3JSC4Heap15recordExtraCostEm
+__ZN3JSC41constructFunctionSkippingEvalEnabledCheckEPNS_9ExecStateEPNS_14JSGlobalObjectERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
+__ZN3JSC4Heap16activityCallbackEv
+__ZN3JSC4Heap16allocateSlowCaseEm
 __ZN3JSC4Heap16objectTypeCountsEv
 __ZN3JSC4Heap16objectTypeCountsEv
-__ZN3JSC4Heap16primaryHeapBeginEv
 __ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC4Heap17globalObjectCountEv
 __ZN3JSC4Heap17collectAllGarbageEv
 __ZN3JSC4Heap17globalObjectCountEv
+__ZN3JSC4Heap19setActivityCallbackEN3WTF10PassOwnPtrINS_18GCActivityCallbackEEE
 __ZN3JSC4Heap20protectedObjectCountEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
 __ZN3JSC4Heap20protectedObjectCountEv
 __ZN3JSC4Heap25protectedObjectTypeCountsEv
 __ZN3JSC4Heap26protectedGlobalObjectCountEv
-__ZN3JSC4Heap6isBusyEv
+__ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
 __ZN3JSC4Heap7destroyEv
 __ZN3JSC4Heap7protectENS_7JSValueE
-__ZN3JSC4Heap8allocateEm
 __ZN3JSC4Heap9unprotectENS_7JSValueE
 __ZN3JSC4Heap9unprotectENS_7JSValueE
+__ZN3JSC4Yarr11YarrPatternC1ERKNS_7UStringEbbPPKc
+__ZN3JSC4Yarr11byteCompileERNS0_11YarrPatternEPN3WTF20BumpPointerAllocatorE
+__ZN3JSC4Yarr9interpretEPNS0_15BytecodePatternEPKtjjPi
 __ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC6JSCell11getJSNumberEv
 __ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE
 __ZN3JSC6JSCell11getCallDataERNS_8CallDataE
 __ZN3JSC6JSCell11getJSNumberEv
@@ -225,29 +260,36 @@ __ZN3JSC6JSCell9getObjectEv
 __ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
 __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
 __ZN3JSC6JSLock12DropAllLocksD1Ev
 __ZN3JSC6JSLock12DropAllLocksC1ENS_14JSLockBehaviorE
 __ZN3JSC6JSLock12DropAllLocksC1EPNS_9ExecStateE
 __ZN3JSC6JSLock12DropAllLocksD1Ev
+__ZN3JSC6JSLock26currentThreadIsHoldingLockEv
 __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock9lockCountEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
 __ZN3JSC6JSLock4lockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE
 __ZN3JSC6JSLock9lockCountEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
-__ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
-__ZN3JSC7JSArray12markChildrenERNS_9MarkStackE
+__ZN3JSC6RegExp6createEPNS_12JSGlobalDataERKNS_7UStringENS_11RegExpFlagsE
+__ZN3JSC6RegExpD1Ev
+__ZN3JSC7JSArray13visitChildrenERNS_9MarkStackE
 __ZN3JSC7JSArray15setSubclassDataEPv
 __ZN3JSC7JSArray15setSubclassDataEPv
-__ZN3JSC7JSArray4infoE
+__ZN3JSC7JSArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
+__ZN3JSC7JSArray6s_infoE
 __ZN3JSC7JSArray9setLengthEj
 __ZN3JSC7JSArray9setLengthEj
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
-__ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE
-__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
+__ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureERKNS_7ArgListE
+__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
 __ZN3JSC7JSArrayD2Ev
 __ZN3JSC7JSArrayD2Ev
+__ZN3JSC7JSValue13isValidCalleeEv
 __ZN3JSC7Profile10restoreAllEv
 __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
 __ZN3JSC7Profile10restoreAllEv
 __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE
 __ZN3JSC7Profile7forEachEMNS_11ProfileNodeEFvvE
-__ZN3JSC7UString4fromEd
-__ZN3JSC7UString4fromEi
-__ZN3JSC7UString4fromEj
-__ZN3JSC7UString4fromEl
+__ZN3JSC7UString6numberEd
+__ZN3JSC7UString6numberEi
+__ZN3JSC7UString6numberEj
+__ZN3JSC7UString6numberEl
 __ZN3JSC7UStringC1EPKc
 __ZN3JSC7UStringC1EPKc
+__ZN3JSC7UStringC1EPKcj
+__ZN3JSC7UStringC1EPKt
 __ZN3JSC7UStringC1EPKtj
 __ZN3JSC7UStringC1EPKtj
+__ZN3JSC7toInt32Ed
 __ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
 __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE
 __ZN3JSC8Debugger6attachEPNS_14JSGlobalObjectE
 __ZN3JSC8Debugger6detachEPNS_14JSGlobalObjectE
@@ -257,14 +299,18 @@ __ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
 __ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
 __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
 __ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC8JSObject12markChildrenERNS_9MarkStackE
+__ZN3JSC8JSObject13visitChildrenERNS_9MarkStackE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC8JSObject15unwrappedObjectEv
 __ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj
 __ZN3JSC8JSObject15unwrappedObjectEv
 __ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
-__ZN3JSC8JSObject17createInheritorIDEv
 __ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
 __ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
+__ZN3JSC8JSObject17preventExtensionsERNS_12JSGlobalDataE
+__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_10JSFunctionEj
 __ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
 __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
 __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
 __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
 __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
 __ZN3JSC8Profiler13stopProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler14startProfilingEPNS_9ExecStateERKNS_7UStringE
 __ZN3JSC8Profiler8profilerEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
+__ZN3JSC8evaluateEPNS_9ExecStateEPNS_14ScopeChainNodeERKNS_10SourceCodeENS_7JSValueE
+__ZN3JSC8isZombieEPKNS_6JSCellE
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
 __ZN3JSC9MarkStack10s_pageSizeE
 __ZN3JSC9CodeBlockD1Ev
 __ZN3JSC9CodeBlockD2Ev
 __ZN3JSC9MarkStack10s_pageSizeE
-__ZN3JSC9MarkStack12releaseStackEPvm
-__ZN3JSC9MarkStack13allocateStackEm
 __ZN3JSC9MarkStack18initializePagesizeEv
 __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
 __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_
 __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
 __ZN3WTF10fastCallocEmm
 __ZN3WTF10fastMallocEm
 __ZN3WTF10fastStrDupEPKc
+__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbbb
+__ZN3WTF11OSAllocator18releaseDecommittedEPvm
+__ZN3WTF11commentAtomE
 __ZN3WTF11currentTimeEv
 __ZN3WTF11currentTimeEv
+__ZN3WTF11dtoaRoundDPEPcdiRbRiRj
+__ZN3WTF11dtoaRoundSFEPcdiRbRiRj
+__ZN3WTF11emptyStringEv
 __ZN3WTF11fastReallocEPvm
 __ZN3WTF11fastReallocEPvm
+__ZN3WTF12AtomicString11addSlowCaseEPNS_10StringImplE
+__ZN3WTF12AtomicString16fromUTF8InternalEPKcS2_
+__ZN3WTF12AtomicString3addEPKc
+__ZN3WTF12AtomicString3addEPKt
+__ZN3WTF12AtomicString3addEPKtj
+__ZN3WTF12AtomicString3addEPKtjj
+__ZN3WTF12AtomicString4findEPKtjj
+__ZN3WTF12AtomicString4initEv
 __ZN3WTF12createThreadEPFPvS0_ES0_
 __ZN3WTF12createThreadEPFPvS0_ES0_PKc
 __ZN3WTF12detachThreadEj
 __ZN3WTF12isMainThreadEv
 __ZN3WTF12randomNumberEv
 __ZN3WTF12createThreadEPFPvS0_ES0_
 __ZN3WTF12createThreadEPFPvS0_ES0_PKc
 __ZN3WTF12detachThreadEj
 __ZN3WTF12isMainThreadEv
 __ZN3WTF12randomNumberEv
+__ZN3WTF13StringBuilder11reifyStringEv
+__ZN3WTF13StringBuilder11shrinkToFitEv
+__ZN3WTF13StringBuilder15reserveCapacityEj
+__ZN3WTF13StringBuilder6appendEPKcj
+__ZN3WTF13StringBuilder6appendEPKtj
+__ZN3WTF13StringBuilder6resizeEj
 __ZN3WTF13WTFThreadData10staticDataE
 __ZN3WTF13WTFThreadDataC1Ev
 __ZN3WTF13WTFThreadDataD1Ev
 __ZN3WTF13WTFThreadData10staticDataE
 __ZN3WTF13WTFThreadDataC1Ev
 __ZN3WTF13WTFThreadDataD1Ev
@@ -321,17 +417,29 @@ __ZN3WTF13currentThreadEv
 __ZN3WTF13tryFastCallocEmm
 __ZN3WTF13tryFastMallocEm
 __ZN3WTF14fastMallocSizeEPKv
 __ZN3WTF13tryFastCallocEmm
 __ZN3WTF13tryFastMallocEm
 __ZN3WTF14fastMallocSizeEPKv
+__ZN3WTF14numberToStringEdPt
+__ZN3WTF14tryFastReallocEPvm
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF15ThreadCondition9broadcastEv
 __ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
 __ZN3WTF15ThreadConditionC1Ev
 __ZN3WTF15ThreadConditionD1Ev
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __ZN3WTF15ThreadCondition6signalEv
 __ZN3WTF15ThreadCondition9broadcastEv
 __ZN3WTF15ThreadCondition9timedWaitERNS_5MutexEd
 __ZN3WTF15ThreadConditionC1Ev
 __ZN3WTF15ThreadConditionD1Ev
+__ZN3WTF15charactersToIntEPKtmPb
 __ZN3WTF16callOnMainThreadEPFvPvES0_
 __ZN3WTF16callOnMainThreadEPFvPvES0_
+__ZN3WTF16codePointCompareERKNS_6StringES2_
 __ZN3WTF16fastZeroedMallocEm
 __ZN3WTF16fastZeroedMallocEm
+__ZN3WTF17charactersToFloatEPKtmPbS2_
+__ZN3WTF17equalIgnoringCaseEPKtPKcj
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplEPKc
+__ZN3WTF17equalIgnoringCaseEPNS_10StringImplES1_
+__ZN3WTF18calculateDSTOffsetEdd
+__ZN3WTF18calculateUTCOffsetEv
+__ZN3WTF18charactersToDoubleEPKtmPbS2_
 __ZN3WTF18dateToDaysFrom1970Eiii
 __ZN3WTF18monthFromDayInYearEib
 __ZN3WTF19initializeThreadingEv
 __ZN3WTF18dateToDaysFrom1970Eiii
 __ZN3WTF18monthFromDayInYearEib
 __ZN3WTF19initializeThreadingEv
+__ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_
 __ZN3WTF20fastMallocStatisticsEv
 __ZN3WTF20initializeMainThreadEv
 __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
 __ZN3WTF20fastMallocStatisticsEv
 __ZN3WTF20initializeMainThreadEv
 __ZN3WTF21RefCountedLeakCounter16suppressMessagesEPKc
@@ -340,125 +448,88 @@ __ZN3WTF21RefCountedLeakCounter9decrementEv
 __ZN3WTF21RefCountedLeakCounter9incrementEv
 __ZN3WTF21RefCountedLeakCounterC1EPKc
 __ZN3WTF21RefCountedLeakCounterD1Ev
 __ZN3WTF21RefCountedLeakCounter9incrementEv
 __ZN3WTF21RefCountedLeakCounterC1EPKc
 __ZN3WTF21RefCountedLeakCounterD1Ev
+__ZN3WTF21charactersToIntStrictEPKtmPbi
+__ZN3WTF22cancelCallOnMainThreadEPFvPvES0_
+__ZN3WTF22charactersToUIntStrictEPKtmPbi
 __ZN3WTF23callOnMainThreadAndWaitEPFvPvES0_
 __ZN3WTF23dayInMonthFromDayInYearEib
 __ZN3WTF23waitForThreadCompletionEjPPv
 __ZN3WTF27releaseFastMallocFreeMemoryEv
 __ZN3WTF28setMainThreadCallbacksPausedEb
 __ZN3WTF23callOnMainThreadAndWaitEPFvPvES0_
 __ZN3WTF23dayInMonthFromDayInYearEib
 __ZN3WTF23waitForThreadCompletionEjPPv
 __ZN3WTF27releaseFastMallocFreeMemoryEv
 __ZN3WTF28setMainThreadCallbacksPausedEb
-__ZN3WTF32doubleToStringInJavaScriptFormatEdPcPj
+__ZN3WTF29cryptographicallyRandomNumberEv
+__ZN3WTF29cryptographicallyRandomValuesEPvm
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
 __ZN3WTF39initializeMainThreadToProcessMainThreadEv
 __ZN3WTF3MD58addBytesEPKhm
 __ZN3WTF36lockAtomicallyInitializedStaticMutexEv
 __ZN3WTF37parseDateFromNullTerminatedCharactersEPKc
 __ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
 __ZN3WTF39initializeMainThreadToProcessMainThreadEv
 __ZN3WTF3MD58addBytesEPKhm
-__ZN3WTF3MD58checksumEv
+__ZN3WTF3MD58checksumERNS_6VectorIhLm16EEE
 __ZN3WTF3MD5C1Ev
 __ZN3WTF3MD5C1Ev
+__ZN3WTF4SHA111computeHashERNS_6VectorIhLm20EEE
+__ZN3WTF4SHA18addBytesEPKhm
+__ZN3WTF4SHA1C1Ev
+__ZN3WTF4dtoaEPcdRbRiRj
 __ZN3WTF5Mutex4lockEv
 __ZN3WTF5Mutex6unlockEv
 __ZN3WTF5Mutex7tryLockEv
 __ZN3WTF5MutexC1Ev
 __ZN3WTF5MutexD1Ev
 __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
 __ZN3WTF6strtodEPKcPPc
 __ZN3WTF7CString11mutableDataEv
 __ZN3WTF7CString16newUninitializedEmRPc
 __ZN3WTF7CStringC1EPKc
-__ZN3WTF7CStringC1EPKcj
+__ZN3WTF7CStringC1EPKcm
 __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
 __ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
 __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b
 __ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b
+__ZN3WTF7xmlAtomE
 __ZN3WTF8Collator18setOrderLowerFirstEb
 __ZN3WTF8CollatorC1EPKc
 __ZN3WTF8CollatorD1Ev
 __ZN3WTF8Collator18setOrderLowerFirstEb
 __ZN3WTF8CollatorC1EPKc
 __ZN3WTF8CollatorD1Ev
+__ZN3WTF8Internal21fastMallocMatchFailedEPv
 __ZN3WTF8fastFreeEPv
 __ZN3WTF8msToYearEd
 __ZN3WTF8fastFreeEPv
 __ZN3WTF8msToYearEd
+__ZN3WTF8nullAtomE
+__ZN3WTF8starAtomE
+__ZN3WTF8textAtomE
 __ZN3WTF9ByteArray6createEm
 __ZN3WTF9dayInYearEdi
 __ZN3WTF9ByteArray6createEm
 __ZN3WTF9dayInYearEdi
+__ZN3WTF9emptyAtomE
+__ZN3WTF9xmlnsAtomE
+__ZN3WTFeqERKNS_12AtomicStringEPKc
+__ZN3WTFeqERKNS_12AtomicStringERKNS_6VectorItLm0EEE
 __ZN3WTFeqERKNS_7CStringES2_
 __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
 __ZNK3JSC10JSFunction23isHostFunctionNonInlineEv
-__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE
+__ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE
 __ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
 __ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
 __ZNK3JSC14JSGlobalObject14isDynamicScopeERb
 __ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE
 __ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE
 __ZNK3JSC14JSGlobalObject14isDynamicScopeERb
-__ZNK3JSC16InternalFunction9classInfoEv
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
 __ZNK3JSC17DebuggerCallFrame10thisObjectEv
 __ZNK3JSC17DebuggerCallFrame12functionNameEv
 __ZNK3JSC16JSVariableObject16isVariableObjectEv
 __ZNK3JSC17DebuggerCallFrame10thisObjectEv
 __ZNK3JSC17DebuggerCallFrame12functionNameEv
@@ -472,74 +543,79 @@ __ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
 __ZNK3JSC18PropertyDescriptor6getterEv
 __ZNK3JSC18PropertyDescriptor6setterEv
 __ZNK3JSC18PropertyDescriptor8writableEv
 __ZNK3JSC18PropertyDescriptor6getterEv
 __ZNK3JSC18PropertyDescriptor6setterEv
 __ZNK3JSC18PropertyDescriptor8writableEv
-__ZNK3JSC4Heap10statisticsEv
+__ZNK3JSC19SourceProviderCache8byteSizeEv
 __ZNK3JSC4Heap11objectCountEv
 __ZNK3JSC4Heap11objectCountEv
+__ZNK3JSC4Heap4sizeEv
+__ZNK3JSC4Heap8capacityEv
 __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell14isGetterSetterEv
 __ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
 __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC6JSCell14isGetterSetterEv
 __ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE
-__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateE
+__ZNK3JSC6JSCell8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell8toStringEPNS_9ExecStateE
-__ZNK3JSC6JSCell9classInfoEv
 __ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
 __ZNK3JSC6JSCell9getUInt32ERj
 __ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE
 __ZNK3JSC7ArgList8getSliceEiRS0_
 __ZNK3JSC7JSArray12subclassDataEv
 __ZNK3JSC6JSCell9getStringEPNS_9ExecStateE
 __ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE
 __ZNK3JSC6JSCell9getUInt32ERj
 __ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE
 __ZNK3JSC7ArgList8getSliceEiRS0_
 __ZNK3JSC7JSArray12subclassDataEv
-__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE
+__ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
 __ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
 __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
 __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE
 __ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE
 __ZNK3JSC7JSValue9toIntegerEPNS_9ExecStateE
-__ZNK3JSC7UString10UTF8StringEb
-__ZNK3JSC7UString14toStrictUInt32EPb
+__ZNK3JSC7UString20substringSharingImplEjj
+__ZNK3JSC7UString4utf8Eb
 __ZNK3JSC7UString5asciiEv
 __ZNK3JSC7UString5asciiEv
-__ZNK3JSC7UString6is8BitEv
-__ZNK3JSC7UString6substrEjj
-__ZNK3JSC7UString8toUInt32EPb
-__ZNK3JSC7UString8toUInt32EPbb
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
 __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateERKNS_10IdentifierE
 __ZNK3JSC8JSObject11hasPropertyEPNS_9ExecStateEj
 __ZNK3JSC8JSObject12defaultValueEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
 __ZNK3JSC8JSObject12toThisObjectEPNS_9ExecStateE
+__ZNK3JSC8JSObject18toStrictThisObjectEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
 __ZNK3JSC8JSObject8toNumberEPNS_9ExecStateE
-__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
+__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
 __ZNK3JSC8JSObject9classNameEv
 __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
 __ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE
 __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
 __ZNK3JSC9HashTable11deleteTableEv
 __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
 __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
 __ZTVN3JSC12StringObjectE
 __ZTVN3JSC14JSGlobalObjectE
+__ZTVN3JSC14ScopeChainNodeE
 __ZTVN3JSC15JSWrapperObjectE
 __ZTVN3JSC15JSWrapperObjectE
+__ZTVN3JSC15WeakHandleOwnerE
 __ZTVN3JSC16InternalFunctionE
 __ZTVN3JSC16JSVariableObjectE
 __ZTVN3JSC8DebuggerE
 __ZTVN3JSC16InternalFunctionE
 __ZTVN3JSC16JSVariableObjectE
 __ZTVN3JSC8DebuggerE
@@ -548,5 +624,12 @@ __ZTVN3JSC8JSStringE
 _jscore_fastmalloc_introspection
 _kJSClassDefinitionEmpty
 
 _jscore_fastmalloc_introspection
 _kJSClassDefinitionEmpty
 
-# iOS Methods
+# iOS methods
+__ZN3WTF11isWebThreadEv
+__ZN3JSC12JSGlobalData23recompileAllJSFunctionsEv
 __ZN3JSC12JSGlobalData20sharedInstanceExistsEv
 __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': '../../WebKit/chromium',
       },{
         # WebKit is checked out in src/chromium/third_party/WebKit
-        'chromium_src_dir': '../../../..',
+        'chromium_src_dir': '../../../../..',
       }],
     ],
   },
       }],
     ],
   },
         '../wtf/unicode',
       ],
       'sources': [
         '../wtf/unicode',
       ],
       'sources': [
+        '<@(javascriptcore_publicheader_files)',
+        '<@(javascriptcore_privateheader_files)',
         '<@(javascriptcore_files)',
       ],
       'sources/': [
         '<@(javascriptcore_files)',
       ],
       'sources/': [
         ['exclude', '../'],
         # ... Then include what we want.
         ['include', '../wtf/'],
         ['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)$'],
         # 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/CurrentTime\\.cpp$'],
+        ['exclude', 'wtf/OSRandomSource\\.cpp$'],
         ['exclude', 'wtf/MainThread.cpp$'],
         ['exclude', 'wtf/TC.*\\.(cpp|h)$'],
       ],
         ['exclude', 'wtf/MainThread.cpp$'],
         ['exclude', 'wtf/TC.*\\.(cpp|h)$'],
       ],
           '../',
           '../wtf',
         ],
           '../',
           '../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',
       },
       'export_dependent_settings': [
         'wtf_config',
           'sources/': [
             ['exclude', 'ThreadIdentifierDataPthreads\\.(h|cpp)$'],
             ['exclude', 'ThreadingPthreads\\.cpp$'],
           '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',
           ],
           ],
           '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',
       'type': '<(library)',
       'dependencies': [
         'wtf',
       'msvs_guid': '49909552-0B0C-4C14-8CF6-DB8A2ADE0934',
       'actions': [
         {
       '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': [
           'inputs': [
-            '../pcre/dftables',
+            '../KeywordLookupGenerator.py',
+            '../parser/Keywords.table'
+          ],
+          'arguments': [
           ],
           'outputs': [
           ],
           'outputs': [
-            '<(INTERMEDIATE_DIR)/chartables.c',
+            '<(INTERMEDIATE_DIR)/KeywordLookup.h',
           ],
           ],
-          'action': ['perl', '-w', '<@(_inputs)', '<@(_outputs)'],
+          'action': ['python', '<@(_inputs)', '<@(_arguments)', '<@(_outputs)'],
         },
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
         },
       ],
       'include_dirs': [
         '<(INTERMEDIATE_DIR)',
+        '../runtime',
       ],
       'sources': [
         '<@(javascriptcore_files)',
       ],
       'sources': [
         '<@(javascriptcore_files)',
         # First exclude everything ...
         ['exclude', '../'],
         # ... Then include what we want.
         # 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',
       ],
       'export_dependent_settings': [
         'wtf',
index 787e0e6813f7ac507cd3230b59b1b5d261c2b66a..c101031bdda2ac707c2874123b24fc8e2b1c032c 100644 (file)
 {
     'variables': {
 {
     '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/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/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/JSCallbackConstructor.cpp',
             'API/JSCallbackConstructor.h',
             'API/JSCallbackFunction.cpp',
             'API/JSClassRef.cpp',
             'API/JSClassRef.h',
             'API/JSContextRef.cpp',
             'API/JSClassRef.cpp',
             'API/JSClassRef.h',
             'API/JSContextRef.cpp',
-            'API/JSContextRef.h',
-            'API/JSContextRefPrivate.h',
             'API/JSObjectRef.cpp',
             'API/JSObjectRef.cpp',
-            'API/JSObjectRef.h',
             'API/JSProfilerPrivate.cpp',
             'API/JSProfilerPrivate.cpp',
-            'API/JSProfilerPrivate.h',
-            'API/JSRetainPtr.h',
             'API/JSStringRef.cpp',
             'API/JSStringRef.cpp',
-            'API/JSStringRef.h',
             'API/JSStringRefBSTR.cpp',
             'API/JSStringRefBSTR.h',
             'API/JSStringRefCF.cpp',
             'API/JSStringRefBSTR.cpp',
             'API/JSStringRefBSTR.h',
             'API/JSStringRefCF.cpp',
-            'API/JSStringRefCF.h',
             'API/JSValueRef.cpp',
             'API/JSValueRef.cpp',
-            'API/JSValueRef.h',
+            'API/JSWeakObjectMapRefPrivate.cpp',
             'API/OpaqueJSString.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/ARMv7Assembler.h',
+            'assembler/AbstractMacroAssembler.h',
             'assembler/AssemblerBuffer.h',
             'assembler/AssemblerBuffer.h',
+            'assembler/AssemblerBufferWithConstantPool.h',
             'assembler/CodeLocation.h',
             'assembler/CodeLocation.h',
+            'assembler/LinkBuffer.h',
+            'assembler/MIPSAssembler.h',
             'assembler/MacroAssembler.h',
             'assembler/MacroAssembler.h',
+            'assembler/MacroAssemblerARM.cpp',
+            'assembler/MacroAssemblerARM.h',
             'assembler/MacroAssemblerARMv7.h',
             'assembler/MacroAssemblerARMv7.h',
-            'assembler/MacroAssemblerCodeRef.h',
+            'assembler/MacroAssemblerMIPS.h',
             'assembler/MacroAssemblerX86.h',
             'assembler/MacroAssemblerX86.h',
-            'assembler/MacroAssemblerX86_64.h',
             'assembler/MacroAssemblerX86Common.h',
             'assembler/MacroAssemblerX86Common.h',
+            'assembler/MacroAssemblerX86_64.h',
+            'assembler/RepatchBuffer.h',
             'assembler/X86Assembler.h',
             'bytecode/CodeBlock.cpp',
             'bytecode/CodeBlock.h',
             'assembler/X86Assembler.h',
             'bytecode/CodeBlock.cpp',
             'bytecode/CodeBlock.h',
             'bytecode/JumpTable.cpp',
             'bytecode/JumpTable.h',
             'bytecode/Opcode.cpp',
             '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',
             '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/Label.h',
             'bytecompiler/LabelScope.h',
+            'bytecompiler/NodesCodegen.cpp',
             'bytecompiler/RegisterID.h',
             '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.cpp',
-            'debugger/Debugger.h',
             'debugger/DebuggerActivation.cpp',
             'debugger/DebuggerActivation.cpp',
-            'debugger/DebuggerActivation.h',
             'debugger/DebuggerCallFrame.cpp',
             '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/parseerr.h',
             'icu/unicode/platform.h',
             'icu/unicode/putil.h',
             'icu/unicode/uversion.h',
             'interpreter/CachedCall.h',
             'interpreter/CallFrame.cpp',
             'icu/unicode/uversion.h',
             'interpreter/CachedCall.h',
             'interpreter/CallFrame.cpp',
-            'interpreter/CallFrame.h',
             'interpreter/CallFrameClosure.h',
             'interpreter/Interpreter.cpp',
             'interpreter/CallFrameClosure.h',
             'interpreter/Interpreter.cpp',
-            'interpreter/Interpreter.h',
-            'interpreter/Register.h',
             'interpreter/RegisterFile.cpp',
             'interpreter/RegisterFile.cpp',
-            'interpreter/RegisterFile.h',
-            'JavaScriptCorePrefix.h',
             'jit/ExecutableAllocator.cpp',
             'jit/ExecutableAllocator.cpp',
-            'jit/ExecutableAllocator.h',
             'jit/ExecutableAllocatorFixedVMPool.cpp',
             '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/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/JITInlineMethods.h',
             'jit/JITOpcodes.cpp',
             'jit/JITOpcodes32_64.cpp',
             'jit/JITPropertyAccess32_64.cpp',
             'jit/JITStubCall.h',
             'jit/JITStubs.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',
             '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/Lexer.cpp',
             'parser/Lexer.h',
             'parser/NodeConstructors.h',
             'parser/Parser.h',
             'parser/ParserArena.cpp',
             'parser/ParserArena.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.cpp',
-            'profiler/Profile.h',
             'profiler/ProfileGenerator.cpp',
             'profiler/ProfileGenerator.h',
             'profiler/ProfileNode.cpp',
             'profiler/ProfileGenerator.cpp',
             'profiler/ProfileGenerator.h',
             'profiler/ProfileNode.cpp',
-            'profiler/ProfileNode.h',
             'profiler/Profiler.cpp',
             'profiler/Profiler.cpp',
-            'profiler/Profiler.h',
             'profiler/ProfilerServer.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.cpp',
-            'runtime/ArgList.h',
             'runtime/Arguments.cpp',
             'runtime/Arguments.h',
             'runtime/ArrayConstructor.cpp',
             'runtime/ArrayConstructor.h',
             'runtime/ArrayPrototype.cpp',
             '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/BatchedTransitionOptimizer.h',
             'runtime/BooleanConstructor.cpp',
             'runtime/BooleanConstructor.h',
             'runtime/BooleanObject.cpp',
-            'runtime/BooleanObject.h',
             'runtime/BooleanPrototype.cpp',
             'runtime/BooleanPrototype.h',
             'runtime/CallData.cpp',
             '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.cpp',
-            'runtime/CommonIdentifiers.h',
             'runtime/Completion.cpp',
             'runtime/Completion.cpp',
-            'runtime/Completion.h',
             'runtime/ConstructData.cpp',
             'runtime/ConstructData.cpp',
-            'runtime/ConstructData.h',
             'runtime/DateConstructor.cpp',
             'runtime/DateConstructor.h',
             'runtime/DateConversion.cpp',
             'runtime/DateConversion.h',
             'runtime/DateInstance.cpp',
             '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/DatePrototype.cpp',
             'runtime/DatePrototype.h',
             'runtime/Error.cpp',
-            'runtime/Error.h',
             'runtime/ErrorConstructor.cpp',
             'runtime/ErrorConstructor.h',
             'runtime/ErrorInstance.cpp',
             'runtime/ErrorConstructor.cpp',
             'runtime/ErrorConstructor.h',
             'runtime/ErrorInstance.cpp',
             'runtime/ErrorPrototype.cpp',
             'runtime/ErrorPrototype.h',
             'runtime/ExceptionHelpers.cpp',
             'runtime/ErrorPrototype.cpp',
             'runtime/ErrorPrototype.h',
             'runtime/ExceptionHelpers.cpp',
-            'runtime/ExceptionHelpers.h',
+            'runtime/Executable.cpp',
+            'runtime/Executable.h',
             'runtime/FunctionConstructor.cpp',
             'runtime/FunctionConstructor.cpp',
-            'runtime/FunctionConstructor.h',
             'runtime/FunctionPrototype.cpp',
             'runtime/FunctionPrototype.cpp',
-            'runtime/FunctionPrototype.h',
+            'runtime/GCActivityCallback.cpp',
+            'runtime/GCActivityCallbackCF.cpp',
             'runtime/GetterSetter.cpp',
             'runtime/GetterSetter.h',
             'runtime/GetterSetter.cpp',
             'runtime/GetterSetter.h',
-            'runtime/GlobalEvalFunction.cpp',
-            'runtime/GlobalEvalFunction.h',
             'runtime/Identifier.cpp',
             'runtime/Identifier.cpp',
-            'runtime/Identifier.h',
             'runtime/InitializeThreading.cpp',
             'runtime/InitializeThreading.cpp',
-            'runtime/InitializeThreading.h',
             'runtime/InternalFunction.cpp',
             'runtime/InternalFunction.cpp',
-            'runtime/InternalFunction.h',
+            'runtime/JSAPIValueWrapper.cpp',
             'runtime/JSActivation.cpp',
             'runtime/JSActivation.h',
             'runtime/JSArray.cpp',
             'runtime/JSActivation.cpp',
             'runtime/JSActivation.h',
             'runtime/JSArray.cpp',
-            'runtime/JSArray.h',
             'runtime/JSByteArray.cpp',
             'runtime/JSByteArray.cpp',
-            'runtime/JSByteArray.h',
             'runtime/JSCell.cpp',
             'runtime/JSCell.cpp',
-            'runtime/JSCell.h',
             'runtime/JSFunction.cpp',
             'runtime/JSFunction.cpp',
-            'runtime/JSFunction.h',
             'runtime/JSGlobalData.cpp',
             'runtime/JSGlobalData.cpp',
-            'runtime/JSGlobalData.h',
             'runtime/JSGlobalObject.cpp',
             'runtime/JSGlobalObject.cpp',
-            'runtime/JSGlobalObject.h',
             'runtime/JSGlobalObjectFunctions.cpp',
             'runtime/JSGlobalObjectFunctions.h',
             'runtime/JSGlobalObjectFunctions.cpp',
             'runtime/JSGlobalObjectFunctions.h',
-            'runtime/JSImmediate.cpp',
-            'runtime/JSImmediate.h',
             'runtime/JSLock.cpp',
             'runtime/JSLock.cpp',
-            'runtime/JSLock.h',
             'runtime/JSNotAnObject.cpp',
             'runtime/JSNotAnObject.h',
             'runtime/JSNumberCell.cpp',
             '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/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/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.cpp',
-            'runtime/JSValue.h',
             'runtime/JSVariableObject.cpp',
             'runtime/JSVariableObject.cpp',
-            'runtime/JSVariableObject.h',
             'runtime/JSWrapperObject.cpp',
             'runtime/JSWrapperObject.cpp',
-            'runtime/JSWrapperObject.h',
+            'runtime/JSZombie.cpp',
+            'runtime/JSZombie.h',
             'runtime/LiteralParser.cpp',
             'runtime/LiteralParser.h',
             'runtime/Lookup.cpp',
             '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.cpp',
-            'runtime/MathObject.h',
+            'runtime/MemoryStatistics.cpp',
             'runtime/NativeErrorConstructor.cpp',
             'runtime/NativeErrorConstructor.h',
             'runtime/NativeErrorPrototype.cpp',
             'runtime/NativeErrorPrototype.h',
             '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/NumberConstructor.cpp',
             'runtime/NumberConstructor.h',
             'runtime/NumberObject.cpp',
-            'runtime/NumberObject.h',
             'runtime/NumberPrototype.cpp',
             'runtime/NumberPrototype.cpp',
-            'runtime/NumberPrototype.h',
             'runtime/ObjectConstructor.cpp',
             'runtime/ObjectConstructor.h',
             'runtime/ObjectPrototype.cpp',
             'runtime/ObjectConstructor.cpp',
             'runtime/ObjectConstructor.h',
             'runtime/ObjectPrototype.cpp',
-            'runtime/ObjectPrototype.h',
             'runtime/Operations.cpp',
             'runtime/Operations.cpp',
-            'runtime/Operations.h',
             'runtime/PropertyDescriptor.cpp',
             'runtime/PropertyDescriptor.cpp',
-            'runtime/PropertyDescriptor.h',
-            'runtime/PropertyMapHashTable.h',
             'runtime/PropertyNameArray.cpp',
             'runtime/PropertyNameArray.cpp',
-            'runtime/PropertyNameArray.h',
             'runtime/PropertySlot.cpp',
             'runtime/PropertySlot.cpp',
-            'runtime/PropertySlot.h',
-            'runtime/Protect.h',
-            'runtime/PrototypeFunction.cpp',
-            'runtime/PrototypeFunction.h',
-            'runtime/PutPropertySlot.h',
             'runtime/RegExp.cpp',
             'runtime/RegExp.cpp',
-            'runtime/RegExp.h',
             'runtime/RegExpCache.cpp',
             'runtime/RegExpCache.cpp',
-            'runtime/RegExpCache.h',
             'runtime/RegExpConstructor.cpp',
             'runtime/RegExpConstructor.h',
             'runtime/RegExpConstructor.cpp',
             'runtime/RegExpConstructor.h',
-            'runtime/RegExpKey.h',
             'runtime/RegExpMatchesArray.h',
             'runtime/RegExpObject.cpp',
             'runtime/RegExpMatchesArray.h',
             'runtime/RegExpObject.cpp',
-            'runtime/RegExpObject.h',
             'runtime/RegExpPrototype.cpp',
             'runtime/RegExpPrototype.h',
             'runtime/RegExpPrototype.cpp',
             'runtime/RegExpPrototype.h',
+            'runtime/RopeImpl.cpp',
             'runtime/ScopeChain.cpp',
             'runtime/ScopeChain.cpp',
-            'runtime/ScopeChain.h',
             'runtime/ScopeChainMark.h',
             'runtime/SmallStrings.cpp',
             '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/StringConstructor.cpp',
             'runtime/StringConstructor.h',
             'runtime/StringObject.cpp',
-            'runtime/StringObject.h',
-            'runtime/StringObjectThatMasqueradesAsUndefined.h',
             'runtime/StringPrototype.cpp',
             'runtime/StringPrototype.cpp',
-            'runtime/StringPrototype.h',
+            'runtime/StringRecursionChecker.cpp',
+            'runtime/StringRecursionChecker.h',
             'runtime/Structure.cpp',
             'runtime/Structure.cpp',
-            'runtime/Structure.h',
             'runtime/StructureChain.cpp',
             'runtime/StructureChain.cpp',
-            'runtime/StructureChain.h',
-            'runtime/StructureTransitionTable.h',
-            'runtime/SymbolTable.h',
-            'runtime/Terminator.h',
             'runtime/TimeoutChecker.cpp',
             'runtime/TimeoutChecker.cpp',
-            'runtime/TimeoutChecker.h',
+            'runtime/Tracing.d',
             'runtime/Tracing.h',
             'runtime/UString.cpp',
             '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.cpp',
-            'wtf/Assertions.h',
-            'wtf/Atomics.h',
-            'wtf/AVLTree.h',
             'wtf/ByteArray.cpp',
             '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.cpp',
-            'wtf/CurrentTime.h',
             'wtf/DateMath.cpp',
             '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.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.cpp',
-            'wtf/HashTable.h',
-            'wtf/HashTraits.h',
-            'wtf/ListHashSet.h',
-            'wtf/ListRefPtr.h',
-            'wtf/Locker.h',
             'wtf/MD5.cpp',
             'wtf/MD5.cpp',
-            'wtf/MD5.h',
             'wtf/MainThread.cpp',
             'wtf/MainThread.cpp',
-            'wtf/MainThread.h',
             'wtf/MallocZoneSupport.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.cpp',
-            'wtf/RandomNumber.h',
             'wtf/RandomNumberSeed.h',
             'wtf/RandomNumberSeed.h',
-            'wtf/RefCounted.h',
             'wtf/RefCountedLeakCounter.cpp',
             '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/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/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/TCPageMap.h',
             'wtf/TCSpinLock.h',
             'wtf/TCSystemAlloc.cpp',
             'wtf/TCSystemAlloc.h',
+            'wtf/ThreadFunctionInvocation.h',
             'wtf/ThreadIdentifierDataPthreads.cpp',
             'wtf/ThreadIdentifierDataPthreads.h',
             'wtf/ThreadIdentifierDataPthreads.cpp',
             'wtf/ThreadIdentifierDataPthreads.h',
+            'wtf/ThreadSpecificWin.cpp',
             'wtf/Threading.cpp',
             'wtf/Threading.cpp',
-            'wtf/Threading.h',
             'wtf/ThreadingNone.cpp',
             'wtf/ThreadingNone.cpp',
-            'wtf/ThreadingPrimitives.h',
             'wtf/ThreadingPthreads.cpp',
             'wtf/ThreadingWin.cpp',
             'wtf/ThreadingPthreads.cpp',
             'wtf/ThreadingWin.cpp',
-            'wtf/ThreadSafeShared.h',
-            'wtf/ThreadSpecific.h',
-            'wtf/ThreadSpecificWin.cpp',
             'wtf/TypeTraits.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.cpp',
-            'wtf/text/AtomicString.h',
-            'wtf/text/AtomicStringImpl.h',
             'wtf/text/CString.cpp',
             'wtf/text/CString.cpp',
-            'wtf/text/CString.h',
-            'wtf/text/StringHash.h',
+            'wtf/text/StringBuilder.cpp',
             'wtf/text/StringImpl.cpp',
             'wtf/text/StringImpl.cpp',
-            'wtf/text/StringImpl.h',
             'wtf/text/StringStatics.cpp',
             'wtf/text/WTFString.cpp',
             'wtf/text/StringStatics.cpp',
             'wtf/text/WTFString.cpp',
-            'wtf/text/WTFString.h',
-            'wtf/unicode/Collator.h',
             'wtf/unicode/CollatorDefault.cpp',
             '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/UnicodeGLib.cpp',
             'wtf/unicode/glib/UnicodeGLib.h',
-            'wtf/unicode/glib/UnicodeMacrosFromICU.h',
             'wtf/unicode/icu/CollatorICU.cpp',
             'wtf/unicode/icu/CollatorICU.cpp',
-            'wtf/unicode/icu/UnicodeIcu.h',
             'wtf/unicode/qt4/UnicodeQt4.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/win/MainThreadWin.cpp',
             'wtf/win/OwnPtrWin.cpp',
+            'wtf/wince/FastMallocWinCE.h',
+            'wtf/wince/MemoryManager.cpp',
+            'wtf/wince/MemoryManager.h',
             'wtf/wx/MainThreadWx.cpp',
             '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
 __ZN3WTF17TCMalloc_PageHeap10AllocLargeEm
 __ZN3WTF17TCMalloc_PageHeap8GrowHeapEm
 __ZN3WTF17TCMalloc_PageHeap6DeleteEPNS_4SpanE
+__ZN3WTF16fastZeroedMallocEm
 __ZN3WTF8fastFreeEPv
 __ZN3WTF19initializeThreadingEv
 __ZN3WTF8fastFreeEPv
 __ZN3WTF19initializeThreadingEv
-__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
-__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3WTFL14threadMapMutexEv
+__ZN3WTF20initializeMainThreadEv
+__ZN3WTFL24initializeMainThreadOnceEv
+__ZN3WTF5MutexC1Ev
+__ZN3WTF28initializeMainThreadPlatformEv
 __ZN3JSC19initializeThreadingEv
 __ZN3JSCL23initializeThreadingOnceEv
 __ZN3JSC19initializeThreadingEv
 __ZN3JSCL23initializeThreadingOnceEv
+__ZN3WTF10StringImpl5emptyEv
 __ZN3WTF13WTFThreadDataC1Ev
 __ZN3WTF13WTFThreadDataC1Ev
-__ZN3JSC17initializeUStringEv
-__ZN7WebCore10StringImpl5emptyEv
+__ZN3WTF11StackBounds10initializeEv
 __ZN3JSC12JSGlobalData10storeVPtrsEv
 __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
 __ZN3WTF15initializeDatesEv
 __ZN3WTF11currentTimeEv
 __ZN3WTF8msToYearEd
+__ZN3JSC12RegisterFile19initializeThreadingEv
 __ZN3WTF39initializeMainThreadToProcessMainThreadEv
 __ZN3WTF39initializeMainThreadToProcessMainThreadEv
-__ZN3WTFL43initializeMainThreadToProcessMainThreadOnceEv
-__ZN3WTF47initializeMainThreadToProcessMainThreadPlatformEv
-__ZN3WTF20initializeMainThreadEv
-__ZN3WTF15ThreadConditionC1Ev
-__ZN7WebCore10StringImpl6createEPKtj
-__ZN7WebCore10StringImpl19createUninitializedEjRPt
+__ZN3WTF36lockAtomicallyInitializedStaticMutexEv
+__ZN3WTF38unlockAtomicallyInitializedStaticMutexEv
+__ZN3WTF6StringC1EPKc
+__ZN3WTF10StringImpl6createEPKc
+__ZN3WTF10StringImpl6createEPKcj
+__ZN3WTF10StringImpl19createUninitializedEjRPt
+__ZN3WTF5equalEPKNS_10StringImplES2_
+__ZN3WTF10StringImpl6createEPKtj
+__ZN3WTF12isMainThreadEv
+__ZN3WTF10StringImplD1Ev
+__ZN3WTF10StringImplD2Ev
 __ZN3WTF5Mutex4lockEv
 __ZN3WTF5Mutex4lockEv
+__ZNK3WTF6String14threadsafeCopyEv
+__ZNK3WTF10StringImpl14threadsafeCopyEv
 __ZN3WTF5Mutex6unlockEv
 __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
 __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
 __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
 __ZN3WTF13currentThreadEv
 __ZN3WTF20ThreadIdentifierData10identifierEv
-__ZNK7WebCore6String15stripWhiteSpaceEv
-__ZN7WebCore10StringImpl15stripWhiteSpaceEv
-__ZN7WebCore5equalEPKNS_10StringImplES2_
-__ZN7WebCoreplEPKcRKNS_6StringE
-__ZN7WebCore6StringC1EPKt
-__ZN7WebCore6StringC2EPKt
-__ZNK7WebCore6String7isEmptyEv
+__ZNK3WTF6String15stripWhiteSpaceEv
+__ZN3WTF10StringImpl15stripWhiteSpaceEv
+_JSStringCreateWithCFString
+_JSStringRetain
+_JSStringRelease
+__ZN3WTF6String6numberEi
 __ZN3WTF16callOnMainThreadEPFvPvES0_
 __ZN3WTF16callOnMainThreadEPFvPvES0_
-__ZN3WTF5DequeINS_19FunctionWithContextEE14expandCapacityEv
+__ZN3WTF5DequeINS_19FunctionWithContextELm0EE14expandCapacityEv
 __ZN3WTF37scheduleDispatchFunctionsOnMainThreadEv
 __ZN3WTF15ThreadCondition4waitERNS_5MutexE
 __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
 __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
 __ZN3JSC12JSGlobalDataC2ENS0_14GlobalDataTypeENS_15ThreadStackTypeE
+__ZN3JSC21createIdentifierTableEv
 __ZN3JSC17CommonIdentifiersC1EPNS_12JSGlobalDataE
 __ZN3JSC17CommonIdentifiersC2EPNS_12JSGlobalDataE
 __ZN3JSC10Identifier3addEPNS_12JSGlobalDataEPKc
 __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
 __ZN3JSC10IdentifierC1EPNS_12JSGlobalDataEPKc
 __ZN3JSC12SmallStringsC1Ev
 __ZN3JSC19ExecutableAllocator17intializePageSizeEv
+__ZNK3JSC19ExecutableAllocator7isValidEv
+__ZN3WTF11OSAllocator18reserveUncommittedEmNS0_5UsageEbb
 __ZN3JSC14ExecutablePool11systemAllocEm
 __ZN3JSC14ExecutablePool11systemAllocEm
+__ZN3WTF11OSAllocator6commitEPvmbb
 __ZN3JSC5LexerC1EPNS_12JSGlobalDataE
 __ZN3JSC11ParserArenaC1Ev
 __ZN3JSC11ParserArenaC2Ev
 __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
 __ZN3JSC9JITThunksC1EPNS_12JSGlobalDataE
+__ZN3JSC9JITThunksC2EPNS_12JSGlobalDataE
 __ZN3JSC3JITC1EPNS_12JSGlobalDataEPNS_9CodeBlockE
 __ZN3JSC3JITC2EPNS_12JSGlobalDataEPNS_9CodeBlockE
 __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
 __ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDE
 __ZN3JSC12X86Assembler3jCCENS0_9ConditionE
+__ZN3JSC15AssemblerBuffer11ensureSpaceEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter11oneByteOp64ENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDEi
 __ZN3JSC12X86Assembler23X86InstructionFormatter11memoryModRMEiNS_12X86Registers10RegisterIDEi
+__ZN3JSC23MacroAssemblerX86Common8branch32ENS0_19RelationalConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32E
 __ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDE
 __ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDEiNS_12X86Registers10RegisterIDE
-__ZN3JSC15AssemblerBuffer11ensureSpaceEi
-__ZN3JSC20MacroAssemblerX86_644callEv
-__ZN3JSC20MacroAssemblerX86_647loadPtrENS_22AbstractMacroAssemblerINS_12X86AssemblerEE15ImplicitAddressENS_12X86Registers10Regi
-__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDENS_12X86Registers10RegisterIDE
 __ZN3JSC3JIT32compileOpCallInitializeCallFrameEv
 __ZN3JSC3JIT32compileOpCallInitializeCallFrameEv
-__ZN3JSC15AssemblerBuffer4growEi
-__ZN3WTF11fastReallocEPvm
-__ZN3WTF11fastReallocILb1EEEPvS1_m
+__ZN3JSC20MacroAssemblerX86_6413branchTestPtrENS_23MacroAssemblerX86Common15ResultConditionENS_12X86Registers10RegisterIDENS_22AbstractMacroAssemblerINS_12X86AssemblerEE12TrustedImm32E
+__ZN3JSC12X86Assembler23X86InstructionFormatter9oneByteOpENS0_15OneByteOpcodeIDENS_12X86Registers10RegisterIDE
+__ZN3WTF6VectorIcLm128EE14expandCapacityEm
+__ZN3WTF6VectorIcLm128EE4growEm
+__ZN3JSC3JIT27privateCompileCTINativeCallEPNS_12JSGlobalDataEb
+__ZNK3JSC22AbstractMacroAssemblerINS_12X86AssemblerEE4Jump4linkEPS2_
 __ZN3WTF10RefCountedIN3JSC14ExecutablePoolEE5derefEv
 __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
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
+__ZN3WTF12randomNumberEv
+__ZN3WTF29cryptographicallyRandomNumberEv
+__ZN3WTF35cryptographicallyRandomValuesFromOSEPhm
 __ZN3JSC14JSGlobalObject4initEPNS_8JSObjectE
 __ZN3JSC14JSGlobalObject5resetENS_7JSValueE
 __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
 __ZN3JSC7UStringC1EPKc
 __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE
-__ZN3JSC8JSObject17putDirectInternalERKNS_10IdentifierENS_7JSValueEjbRNS_15PutPropertySlotEPNS_6JSCellE
 __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm
 __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
 __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
 __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
 __ZN3JSC14JSGlobalObject10globalExecEv
-__ZN3JSC4Heap9unprotectENS_7JSValueE
-__ZN3JSC14TimeoutChecker5resetEv
-__ZN3JSC8evaluateEPNS_9ExecStateERNS_10ScopeChainERKNS_10SourceCodeENS_7JSValueE
+_JSGlobalContextRetain
+__ZN3JSC14MachineThreads16addCurrentThreadEv
 __ZN3JSC6JSLockC1EPNS_9ExecStateE
 __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
 __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
 __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
 __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
 __ZN3JSC13StatementNode6setLocEii
-__ZN3WTF6VectorIPN3JSC20ParserArenaDeletableELm0EE14expandCapacityEm
 __ZN3JSC14SourceElements6appendEPNS_13StatementNodeE
 __ZNK3JSC13StatementNode16isEmptyStatementEv
 __ZN3WTF6VectorIPN3JSC13StatementNodeELm0EE14expandCapacityEm
 __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
 __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
 __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
 __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
 __ZN3JSC17BytecodeGenerator8generateEv
 __ZN3JSC11ProgramNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator13emitDebugHookENS_11DebugHookIDEii
@@ -349,1787 +627,1589 @@ __ZN3JSC17BytecodeGenerator12newTemporaryEv
 __ZN3JSC17BytecodeGenerator11newRegisterEv
 __ZN3JSC17BytecodeGenerator8emitLoadEPNS_10RegisterIDENS_7JSValueE
 __ZN3JSC17BytecodeGenerator16addConstantValueENS_7JSValueE
 __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
 __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
 __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
 __ZN3JSC9CodeBlock11shrinkToFitEv
 __ZN3WTF6VectorIN3JSC11InstructionELm0EE14shrinkCapacityEm
-__ZN3WTF6VectorIPN3JSC12CallLinkInfoELm0EE14shrinkCapacityEm
+__ZN3WTF6VectorIN3JSC17StructureStubInfoELm0EE14shrinkCapacityEm
 __ZN3WTF6VectorIN3JSC10IdentifierELm0EE14shrinkCapacityEm
 __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
 __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
 __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
 __ZN3JSC3JIT11emit_op_endEPNS_11InstructionE
-__ZN3WTF6VectorIN3JSC9JumpTableELm0EE14shrinkCapacityEm
+__ZN3JSC3JIT22privateCompileLinkPassEv
 __ZN3JSC3JIT23privateCompileSlowCasesEv
 __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
 __ZN3JSC3JIT16emitSlow_op_callEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3JSC3JIT22compileOpCallSetupArgsEPNS_11InstructionE
-__ZN3JSC3JIT21emitSlow_op_put_by_idEPNS_11InstructionERPNS_13SlowCaseEntryE
-__ZN3WTF6VectorIN3JSC18MethodCallLinkInfoELm0EE14expandCapacityEm
+__ZN3JSC3JIT21compileOpCallSlowCaseEPNS_11InstructionERPNS_13SlowCaseEntryEjNS_8OpcodeIDE
+__ZN3WTF6VectorIN3JSC18MethodCallLinkInfoELm0EE4growEm
 __ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv
 __ZN3JSC17BytecodeGenerator18dumpsGeneratedCodeEv
+__ZN3JSC4Heap29reportExtraMemoryCostSlowCaseEm
+__ZN3JSC17BytecodeGeneratorD2Ev
+__ZThn16_N3JSC11ProgramNodeD0Ev
+__ZN3JSC11ProgramNodeD0Ev
+__ZN3JSC12RegisterFile12globalObjectEv
+__ZN3JSC14JSGlobalObject13copyGlobalsToERNS_12RegisterFileE
+__ZN3JSC12RegisterFile15setGlobalObjectEPNS_14JSGlobalObjectE
 _ctiTrampoline
 _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
 _cti_op_get_by_id_method_check
-__ZN3JSC13DatePrototype18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
+__ZNK3JSC7JSValue3getEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_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
 __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
 __ZN3JSC13AssignDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode6isPureERNS_17BytecodeGeneratorE
-__ZN3JSC17BytecodeGenerator8emitMoveEPNS_10RegisterIDES2_
-__ZN3JSC17ObjectLiteralNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator13emitNewObjectEPNS_10RegisterIDE
-__ZN3JSC21FunctionCallValueNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC15DotAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC12FuncExprNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator25emitNewFunctionExpressionEPNS_10RegisterIDEPNS_12FuncExprNodeE
 __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
 __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
 __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
 __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
 __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
 __ZN3JSC17BytecodeGenerator8newLabelEv
-__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
-__ZN3JSC17BytecodeGenerator15emitJumpIfFalseEPNS_10RegisterIDEPNS_5LabelE
+__ZN3JSC17BytecodeGenerator20emitGetPropertyNamesEPNS_10RegisterIDES2_S2_S2_PNS_5LabelE
 __ZN3JSC17BytecodeGenerator8emitJumpEPNS_5LabelE
 __ZN3JSC17BytecodeGenerator9emitLabelEPNS_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
 __ZN3JSC19BracketAccessorNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
 __ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
 __ZN3JSC17BytecodeGenerator12emitGetByValEPNS_10RegisterIDES2_S2_
-__ZN3JSC17PrefixResolveNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
-__ZN3JSC17BytecodeGenerator10emitPreIncEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator12emitPutByValEPNS_10RegisterIDES2_S2_
+__ZNK3JSC14ExpressionNode26hasConditionContextCodegenEv
+__ZN3JSC15StrictEqualNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
+__ZN3JSC17BytecodeGenerator14emitEqualityOpENS_8OpcodeIDEPNS_10RegisterIDES3_S3_
 __ZN3JSC17BytecodeGenerator14emitJumpIfTrueEPNS_10RegisterIDEPNS_5LabelE
 __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
 __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
 __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
 __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
 __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
 _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
 _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
 __ZN3JSC3JIT14emit_op_jnlessEPNS_11InstructionE
+__ZN3JSC3JIT18emitSlow_op_jfalseEPNS_11InstructionERPNS_13SlowCaseEntryE
+__ZN3JSC3JIT21emitSlow_op_constructEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT18emitSlow_op_jnlessEPNS_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
 _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
 __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
 __ZN3JSC12BinaryOpNode10emitStrcatERNS_17BytecodeGeneratorEPNS_10RegisterIDES4_PNS_21ReadModifyResolveNodeE
-__ZNK3JSC10StringNode8isStringEv
 __ZNK3JSC14ExpressionNode8isStringEv
 __ZN3JSC17BytecodeGenerator15emitToPrimitiveEPNS_10RegisterIDES2_
 __ZN3JSC17BytecodeGenerator10emitStrcatEPNS_10RegisterIDES2_i
 __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
 __ZN3JSC3JIT20emit_op_to_primitiveEPNS_11InstructionE
-__ZN3JSC23MacroAssemblerX86Common4moveENS_22AbstractMacroAssemblerINS_12X86AssemblerEE6ImmPtrENS_12X86Registers10RegisterIDE
 __ZN3JSC3JIT14emit_op_strcatEPNS_11InstructionE
 __ZN3JSC3JIT14emit_op_strcatEPNS_11InstructionE
-__ZN3JSC3JIT15emitSlow_op_modEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT24emitSlow_op_to_primitiveEPNS_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
 _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
 __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
 __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
 __ZN3WTF9HashTableIPN3JSC8JSObjectES3_NS_17IdentityExtractorIS3_EENS_7PtrHashIS3_EENS_10HashTraitsIS3_EES9_E6rehashEi
-__ZNK3JSC8JSObject3getEPNS_9ExecStateERKNS_10IdentifierE
 __ZN3JSC15JSStringBuilder5buildEPNS_9ExecStateE
 __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
 _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
 __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
 __ZN3JSC24ApplyFunctionCallDotNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZNK3JSC14ExpressionNode13isSimpleArrayEv
 __ZN3JSC17BytecodeGenerator26emitJumpIfNotFunctionApplyEPNS_10RegisterIDEPNS_5LabelE
-__ZN3JSC17BytecodeGenerator22willResolveToArgumentsERKNS_10IdentifierE
-__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_
+__ZNK3JSC12JSActivation14isDynamicScopeERb
+__ZN3JSC17BytecodeGenerator15emitLoadVarargsEPNS_10RegisterIDES2_S2_
 __ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
 __ZN3JSC17BytecodeGenerator15emitCallVarargsEPNS_10RegisterIDES2_S2_S2_jjj
-__ZN3JSC3JIT16emit_op_jneq_ptrEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_load_varargsEPNS_11InstructionE
 __ZN3JSC3JIT20emit_op_call_varargsEPNS_11InstructionE
 __ZN3JSC3JIT20compileOpCallVarargsEPNS_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
 __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_
 __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
 __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
 __ZNK3JSC17RegExpConstructor14arrayOfMatchesEPNS_9ExecStateE
 __ZN3JSC18RegExpMatchesArrayC2EPNS_9ExecStateEPNS_24RegExpConstructorPrivateE
-__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEEj
+__ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureEjNS_17ArrayCreationModeE
 __ZN3JSC7JSArray15setSubclassDataEPv
 __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
 __ZN3JSC12RegExpObjectD1Ev
+__ZN3JSC12JSActivationD1Ev
+__ZN3JSC16JSCallbackObjectINS_24JSObjectWithGlobalObjectEED1Ev
+__ZN3JSC20JSCallbackObjectDataD0Ev
+_JSClassRelease
+__ZN3JSC15WeakHandleOwnerD2Ev
+__ZN3JSC14ExecutablePool13systemReleaseERNS0_10AllocationE
+__ZN3WTF11OSAllocator8decommitEPvm
 __ZN3JSC18RegExpMatchesArrayD1Ev
 __ZN3JSC18RegExpMatchesArrayD1Ev
-__ZNK3JSC7JSArray12subclassDataEv
-__ZN3JSC15ObjectPrototype18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC22JSPropertyNameIteratorD1Ev
 __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
 __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
 __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
 __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
 __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
 _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
 __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
 _cti_op_push_new_scope
-__ZN3WTF7HashMapINS_6RefPtrIN7WebCore10StringImplEEEN3JSC16SymbolTableEntryENS5_17IdentifierRepHashENS_10HashTraitsIS4_EENS5_26
 __ZN3JSC19JSStaticScopeObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
 __ZN3JSC12JSActivation3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
 _cti_op_pop_scope
 __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
 __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
 __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
 __ZN3JSC7JSArray4sortEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataE
-__ZN3WTF6VectorIN3JSC26AVLTreeNodeForArrayCompareELm0EE14expandCapacityEm
-__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeEPNS_
+__ZN3JSC11Interpreter20prepareForRepeatCallEPNS_18FunctionExecutableEPNS_9ExecStateEPNS_10JSFunctionEiPNS_14ScopeChainNodeE
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
 __ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE6insertEi
-__ZN3JSC11Interpreter7executeERNS_16CallFrameClosureEPNS_7JSValueE
-__ZN3WTF7AVLTreeIN3JSC32AVLTreeAbstractorForArrayCompareELj44ENS_18AVLTreeDefaultBSetILj44EEEE7balanceEi
 __ZN3JSC11Interpreter13endRepeatCallERNS_16CallFrameClosureE
 __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
 __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
 __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
 __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
 __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
 _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
 __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
 __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
 __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
 __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
 __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
 __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
 __ZNK3JSC8JSObject20propertyIsEnumerableEPNS_9ExecStateERKNS_10IdentifierE
-__ZN3JSC7JSArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC14JSGlobalObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
+__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
 __ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
 __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
 __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
 __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
 __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
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
+__ZN3JSC8DebuggerD2Ev
 __ZN3WTF14ThreadSpecificINS_13WTFThreadDataEE7destroyEPv
 __ZN3WTF13WTFThreadDataD1Ev
 __ZN3WTF14ThreadSpecificINS_13WTFThreadDataEE7destroyEPv
 __ZN3WTF13WTFThreadDataD1Ev
-__ZN7WebCore17AtomicStringTable7destroyEPS0_
+__ZN3WTF17AtomicStringTable7destroyEPS0_
 __ZN3JSC15IdentifierTableD1Ev
 __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
 # JavaScriptCore - Qt4 build info
+
+include(../common.pri)
+
 VPATH += $$PWD
 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 {
 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 \
     $$PWD/.. \
+    $$PWD/../ThirdParty \
     $$PWD/assembler \
     $$PWD/bytecode \
     $$PWD/bytecompiler \
     $$PWD/assembler \
     $$PWD/bytecode \
     $$PWD/bytecompiler \
+    $$PWD/heap \
+    $$PWD/dfg \
     $$PWD/debugger \
     $$PWD/interpreter \
     $$PWD/jit \
     $$PWD/parser \
     $$PWD/debugger \
     $$PWD/interpreter \
     $$PWD/jit \
     $$PWD/parser \
-    $$PWD/pcre \
     $$PWD/profiler \
     $$PWD/runtime \
     $$PWD/wtf \
     $$PWD/profiler \
     $$PWD/runtime \
     $$PWD/wtf \
+    $$PWD/wtf/gobject \
     $$PWD/wtf/symbian \
     $$PWD/wtf/unicode \
     $$PWD/yarr \
     $$PWD/API \
     $$PWD/ForwardingHeaders \
     $$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
 
 
 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
 }
 
 wince* {
     INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat
-    DEFINES += WINCEBASIC
-
-    INCLUDEPATH += $$PWD/../JavaScriptCore/os-wince
     INCLUDEPATH += $$PWD/../JavaScriptCore/os-win32
 }
 
 
     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* {
     # 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 {
         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
         # 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
         # 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
     }
 
         POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}lib$${JAVASCRIPTCORE_TARGET}.a
     }
 
@@ -109,3 +107,4 @@ defineTest(addJavaScriptCoreLib) {
 
     return(true)
 }
 
     return(true)
 }
+
index 8b0a0efa1123c092c9e2da9db70d518f4347e21c..3e0caf8df920b5de0aa9b7a3b187ae2dcaba22ff 100644 (file)
@@ -16,20 +16,6 @@ CONFIG += depend_includepath
 
 contains(QT_CONFIG, embedded):CONFIG += embedded
 
 
 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
 # 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
 }
 
     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
 
 *-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
 }
 
     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 \
 
 SOURCES += \
     API/JSBase.cpp \
@@ -79,7 +60,11 @@ SOURCES += \
     API/JSValueRef.cpp \
     API/OpaqueJSString.cpp \
     assembler/ARMAssembler.cpp \
     API/JSValueRef.cpp \
     API/OpaqueJSString.cpp \
     assembler/ARMAssembler.cpp \
+    assembler/ARMv7Assembler.cpp \
     assembler/MacroAssemblerARM.cpp \
     assembler/MacroAssemblerARM.cpp \
+    assembler/MacroAssemblerSH4.h \
+    assembler/MacroAssemblerSH4.cpp \
+    assembler/SH4Assembler.h \
     bytecode/CodeBlock.cpp \
     bytecode/JumpTable.cpp \
     bytecode/Opcode.cpp \
     bytecode/CodeBlock.cpp \
     bytecode/JumpTable.cpp \
     bytecode/Opcode.cpp \
@@ -87,20 +72,36 @@ SOURCES += \
     bytecode/StructureStubInfo.cpp \
     bytecompiler/BytecodeGenerator.cpp \
     bytecompiler/NodesCodegen.cpp \
     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 \
     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 \
     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/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 \
     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 \
     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/Lexer.cpp \
     parser/Nodes.cpp \
     parser/ParserArena.cpp \
     parser/Parser.cpp \
+    parser/SourceProviderCache.cpp \
     profiler/Profile.cpp \
     profiler/ProfileGenerator.cpp \
     profiler/ProfileNode.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/BooleanObject.cpp \
     runtime/BooleanPrototype.cpp \
     runtime/CallData.cpp \
-    runtime/Collector.cpp \
     runtime/CommonIdentifiers.cpp \
     runtime/Completion.cpp \
     runtime/ConstructData.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/Executable.cpp \
     runtime/FunctionConstructor.cpp \
     runtime/FunctionPrototype.cpp \
+    runtime/GCActivityCallback.cpp \
     runtime/GetterSetter.cpp \
     runtime/GetterSetter.cpp \
-    runtime/GlobalEvalFunction.cpp \
     runtime/Identifier.cpp \
     runtime/InitializeThreading.cpp \
     runtime/InternalFunction.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/JSGlobalData.cpp \
     runtime/JSGlobalObject.cpp \
     runtime/JSGlobalObjectFunctions.cpp \
-    runtime/JSImmediate.cpp \
     runtime/JSLock.cpp \
     runtime/JSNotAnObject.cpp \
     runtime/JSLock.cpp \
     runtime/JSNotAnObject.cpp \
-    runtime/JSNumberCell.cpp \
     runtime/JSObject.cpp \
     runtime/JSObject.cpp \
+    runtime/JSObjectWithGlobalObject.cpp \
     runtime/JSONObject.cpp \
     runtime/JSPropertyNameIterator.cpp \
     runtime/JSStaticScopeObject.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/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 \
     runtime/MathObject.cpp \
     runtime/NativeErrorConstructor.cpp \
     runtime/NativeErrorPrototype.cpp \
@@ -184,7 +181,6 @@ SOURCES += \
     runtime/PropertyDescriptor.cpp \
     runtime/PropertyNameArray.cpp \
     runtime/PropertySlot.cpp \
     runtime/PropertyDescriptor.cpp \
     runtime/PropertyNameArray.cpp \
     runtime/PropertySlot.cpp \
-    runtime/PrototypeFunction.cpp \
     runtime/RegExpConstructor.cpp \
     runtime/RegExp.cpp \
     runtime/RegExpObject.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/RopeImpl.cpp \
     runtime/ScopeChain.cpp \
     runtime/SmallStrings.cpp \
+    runtime/StrictEvalActivation.cpp \
     runtime/StringConstructor.cpp \
     runtime/StringObject.cpp \
     runtime/StringPrototype.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 \
     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
 
 # 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
 /* 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
 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 {
             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;
         }
     } 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 {
             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);
 }
 
     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);
 {
     // 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);
 
         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.
 
     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) {
         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);
 
                 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,
             r0 = 0,
             r1,
             r2,
-            r3,
-            S0 = r3,
+            r3, S0 = r3,
             r4,
             r5,
             r6,
             r7,
             r4,
             r5,
             r6,
             r7,
-            r8,
-            S1 = r8,
+            r8, S1 = r8,
             r9,
             r10,
             r11,
             r12,
             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,
         } 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
         } 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 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() { }
 
 
         ARMAssembler() { }
 
@@ -118,12 +140,12 @@ namespace JSC {
             MVN = (0xf << 21),
             MUL = 0x00000090,
             MULL = 0x00c00090,
             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,
             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
 #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,
 #if WTF_ARM_ARCH_AT_LEAST(5)
             CLZ = 0x016f0f10,
-            BKPT = 0xe120070,
+            BKPT = 0xe1200070,
             BLX = 0x012fff30,
             BLX = 0x012fff30,
+            NOP_T2 = 0xf3af8000,
 #endif
 #if WTF_ARM_ARCH_AT_LEAST(7)
             MOVW = 0x03000000,
 #endif
 #if WTF_ARM_ARCH_AT_LEAST(7)
             MOVW = 0x03000000,
@@ -183,61 +207,37 @@ namespace JSC {
         enum {
             padForAlign8  = 0x00,
             padForAlign16 = 0x0000,
         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;
 
         };
 
         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)
         {
         // 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);
         }
 
             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);
         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);
         }
 
             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);
         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));
         }
 
             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)
         }
 
         void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
@@ -516,29 +521,39 @@ namespace JSC {
             dtr_u(true, reg, ARMRegisters::sp, 0, cc);
         }
 
             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)
         }
 
 #if WTF_ARM_ARCH_AT_LEAST(5)
@@ -557,6 +572,11 @@ namespace JSC {
             dtr_dr(true, ARMRegisters::S0, ARMRegisters::S0, ARMRegisters::S0);
 #endif
         }
             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)
         {
 
         void bx(int rm, Condition cc = AL)
         {
@@ -567,19 +587,17 @@ namespace JSC {
 #endif
         }
 
 #endif
         }
 
-        JmpSrc blx(int rm, Condition cc = AL)
+        AssemblerLabel blx(int rm, Condition cc = AL)
         {
 #if WTF_ARM_ARCH_AT_LEAST(5)
         {
 #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);
             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
             bx(rm, cc);
 #endif
-            return JmpSrc(s);
+            return m_buffer.label();
         }
 
         static ARMWord lsl(int reg, ARMWord value)
         }
 
         static ARMWord lsl(int reg, ARMWord value)
@@ -626,9 +644,9 @@ namespace JSC {
 
         // General helpers
 
 
         // General helpers
 
-        int size()
+        size_t codeSize() const
         {
         {
-            return m_buffer.size();
+            return m_buffer.codeSize();
         }
 
         void ensureSpace(int insnSpace, int constSpace)
         }
 
         void ensureSpace(int insnSpace, int constSpace)
@@ -641,12 +659,13 @@ namespace JSC {
             return m_buffer.sizeOfConstantPool();
         }
 
             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);
         {
             while (!m_buffer.isAligned(alignment))
                 mov_r(ARMRegisters::r0, ARMRegisters::r0);
@@ -654,21 +673,24 @@ namespace JSC {
             return label();
         }
 
             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));
         {
             ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
-            int s = m_buffer.uncheckedSize();
+            m_jumps.append(m_buffer.codeSize() | (useConstantPool & 0x1));
             ldr_un_imm(rd, InvalidBranchTarget, cc);
             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);
         }
 
         {
             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
 
 
         // Patching helpers
 
@@ -717,9 +739,17 @@ namespace JSC {
 
         static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
 
 
         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
 
         // 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);
         }
         {
             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));
         }
         {
             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 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);
         }
 
             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)
         {
         }
 
         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)
         {
         }
 
         static void relinkCall(void* from, void* to)
         {
-            patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
+            patchPointerInternal(getAbsoluteJumpAddress(from), to);
         }
 
         // Address operations
 
         }
 
         // 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
 
         }
 
         // 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
         }
 
         // Handle immediates
@@ -825,6 +843,15 @@ namespace JSC {
         void moveImm(ARMWord imm, int dest);
         ARMWord encodeComplexImm(ARMWord imm, int dest);
 
         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);
         // 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 {
 
 
 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
 }
 
 #endif
index 13ad3e0d3259d83e4147a139082734bc62b376f4..f5101c76b7e44c2f6f894a4958824a76a0e0fb3c 100644 (file)
@@ -340,6 +340,8 @@ public:
         return m_type != TypeInvalid;
     }
 
         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); }
     // 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 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; }
 
     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;
 };
 
     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,
 typedef enum {
     SRType_LSL,
     SRType_LSR,
@@ -412,7 +380,6 @@ typedef enum {
     SRType_RRX = SRType_ROR
 } ARMShiftType;
 
     SRType_RRX = SRType_ROR
 } ARMShiftType;
 
-class ARMv7Assembler;
 class ShiftTypeAndAmount {
     friend class ARMv7Assembler;
 
 class ShiftTypeAndAmount {
     friend class ARMv7Assembler;
 
@@ -462,8 +429,8 @@ public:
     typedef enum {
         ConditionEQ,
         ConditionNE,
     typedef enum {
         ConditionEQ,
         ConditionNE,
-        ConditionHS,
-        ConditionLO,
+        ConditionHS, ConditionCS = ConditionHS,
+        ConditionLO, ConditionCC = ConditionLO,
         ConditionMI,
         ConditionPL,
         ConditionVS,
         ConditionMI,
         ConditionPL,
         ConditionVS,
@@ -475,16 +442,28 @@ public:
         ConditionGT,
         ConditionLE,
         ConditionAL,
         ConditionGT,
         ConditionLE,
         ConditionAL,
-        
-        ConditionCS = ConditionHS,
-        ConditionCC = ConditionLO,
+        ConditionInvalid
     } Condition;
 
     } 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)
     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;
     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;
         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:
     };
 
 private:
@@ -696,6 +617,7 @@ private:
         OP_LSR_reg_T2   = 0xFA20,
         OP_ASR_reg_T2   = 0xFA40,
         OP_ROR_reg_T2   = 0xFA60,
         OP_LSR_reg_T2   = 0xFA20,
         OP_ASR_reg_T2   = 0xFA40,
         OP_ROR_reg_T2   = 0xFA60,
+        OP_CLZ          = 0xFAB0,
         OP_SMULL_T1     = 0xFB80,
     } OpcodeID1;
 
         OP_SMULL_T1     = 0xFB80,
     } OpcodeID1;
 
@@ -787,10 +709,10 @@ public:
 
         if (rn == ARMRegisters::sp) {
             if (!(rd & 8) && imm.isUInt10()) {
 
         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()) {
                 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)) {
                 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);
     {
         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.
     }
 
     // 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);
     {
         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.
     }
 
     // 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));
     {
         // 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?
     }
 
     // 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);
     {
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
         ASSERT(rd != ARMRegisters::pc);
@@ -866,7 +788,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block.
     }
 
     // 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);
     {
         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());
     }
 
             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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -882,7 +804,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_AND_imm_T1, rn, rd, imm);
     }
 
         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));
     {
         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));
     }
 
         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);
     {
         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());
     }
 
             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));
     {
         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));
     }
 
         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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -917,39 +839,40 @@ public:
     }
     
     // Only allowed in IT (if then) block if last instruction.
     }
     
     // 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);
     {
         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.
     }
     
     // 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);
     {
         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.
     }
 
     // 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);
     {
         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());
     {
         ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
@@ -957,7 +880,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMN_imm, rn, (RegisterID)0xf, imm);
     }
 
         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());
     {
         ASSERT(rn != ARMRegisters::pc);
         ASSERT(imm.isEncodedImm());
@@ -968,14 +891,14 @@ public:
             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_CMP_imm_T2, rn, (RegisterID)0xf, imm);
     }
 
             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));
     }
 
     {
         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());
     {
         if ((rn | rm) & 8)
             cmp(rn, rm, ShiftTypeAndAmount());
@@ -984,7 +907,7 @@ public:
     }
 
     // xor is not spelled with an 'e'. :-(
     }
 
     // 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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -993,7 +916,7 @@ public:
     }
 
     // xor is not spelled with an 'e'. :-(
     }
 
     // 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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1012,28 +935,28 @@ public:
             eor(rd, rn, rm, ShiftTypeAndAmount());
     }
 
             eor(rd, rn, rm, ShiftTypeAndAmount());
     }
 
-    void it(Condition cond)
+    ALWAYS_INLINE void it(Condition cond)
     {
         m_formatter.oneWordOp8Imm8(OP_IT, ifThenElse(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));
     }
 
     {
         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));
     }
 
     {
         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.
     {
         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());
     {
         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())
         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());
     }
 
         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.
     //
     // 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
     // _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);
     {
         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.
     }
 
     // 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));
     {
         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.
     }
 
     // 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());
     {
         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
     // _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);
     {
         ASSERT(rt != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1137,7 +1068,7 @@ public:
         m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRH_imm_T3, rn, rt, offset);
     }
 
         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)
     {
         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);
     }
 
         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));
     {
         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));
     }
 
         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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1212,7 +1143,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_LSL_reg_T2, rn, FourFours(0xf, rd, 0, rm));
     }
 
         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));
     {
         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));
     }
 
         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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1228,7 +1159,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_LSR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
     }
 
         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());
     {
         ASSERT(imm.isValid());
         ASSERT(!imm.isEncodedImm());
@@ -1237,7 +1168,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm);
     }
 
         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));
     {
         ASSERT(imm.isValid());
         ASSERT(!BadReg(rd));
@@ -1250,19 +1181,19 @@ public:
             movT3(rd, imm);
     }
 
             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);
     }
 
     {
         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);
     }
 
     {
         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));
     {
         ASSERT(imm.isEncodedImm());
         ASSERT(!BadReg(rd));
@@ -1270,14 +1201,14 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MVN_imm, 0xf, rd, imm);
     }
 
         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));
     }
 
     {
         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);
     {
         if (!((rd | rm) & 8))
             m_formatter.oneWordOp10Reg3Reg3(OP_MVN_reg_T1, rm, rd);
@@ -1285,13 +1216,13 @@ public:
             mvn(rd, rm, ShiftTypeAndAmount());
     }
 
             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);
     }
 
     {
         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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1299,7 +1230,7 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_ORR_imm_T1, rn, rd, imm);
     }
 
         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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1317,7 +1248,7 @@ public:
             orr(rd, rn, rm, ShiftTypeAndAmount());
     }
 
             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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1335,7 +1266,7 @@ public:
             orr_S(rd, rn, rm, ShiftTypeAndAmount());
     }
 
             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));
     {
         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));
     }
 
         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));
     {
         ASSERT(!BadReg(rd));
         ASSERT(!BadReg(rn));
@@ -1351,7 +1282,7 @@ public:
         m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
     }
 
         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));
     {
         ASSERT(!BadReg(rdLo));
         ASSERT(!BadReg(rdHi));
@@ -1362,7 +1293,7 @@ public:
     }
 
     // rt == ARMRegisters::pc only allowed if last instruction in IT (if then) block.
     }
 
     // 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);
     {
         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())
         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());
     }
         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
     // _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);
     {
         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.
     }
 
     // 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));
     {
         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));
     }
 
             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));
     {
         // 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()) {
         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()) {
             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);
     {
         ASSERT(rd != ARMRegisters::pc);
         ASSERT(rn != ARMRegisters::pc);
@@ -1464,7 +1395,7 @@ public:
             m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_RSB_imm_T2, rn, rd, imm);
     }
 
             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);
     {
         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.
     }
 
     // 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);
     {
         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()) {
         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()) {
             return;
         } else if (!((rd | rn) & 8)) {
             if (imm.isUInt3()) {
@@ -1508,7 +1439,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block?
     }
 
     // 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);
     {
         ASSERT((rd != ARMRegisters::sp) || (rn == ARMRegisters::sp));
         ASSERT(rd != ARMRegisters::pc);
@@ -1518,7 +1449,7 @@ public:
     }
 
     // Not allowed in an IT (if then) block.
     }
 
     // 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);
     {
         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());
     }
 
             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());
     {
         ASSERT(!BadReg(rn));
         ASSERT(imm.isEncodedImm());
@@ -1534,14 +1465,14 @@ public:
         m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_TST_imm, rn, (RegisterID)0xf, imm);
     }
 
         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));
     }
 
     {
         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());
     {
         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);
     }
 
         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)
     }
 
     int executableOffsetFor(int location)
@@ -1668,16 +1586,11 @@ public:
         return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
     }
     
         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:
 
     
     // 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();
     }
     {
         return a.from() < b.from();
     }
@@ -1702,34 +1615,34 @@ public:
         if (jumpType == JumpConditionFixedSize)
             return LinkConditionalBX;
         
         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
         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
             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 = 
             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
             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
             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;
             if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
                 if (!mayTriggerErrata)
                     return LinkJumpT4;
@@ -1764,7 +1677,7 @@ public:
         return m_jumpsToLink;
     }
 
         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:
     {
         switch (record.linkType()) {
         case LinkJumpT1:
@@ -1795,10 +1708,11 @@ public:
     }
 
     void* unlinkedCode() { return m_formatter.data(); }
     }
 
     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;
     }
 
         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.
 
     // 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);
     }
 
         
         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(!(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);
     }
 
         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);
     }
     {
         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
     }
@@ -1865,6 +1777,13 @@ public:
         
         setInt32(where, value);
     }
         
         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)
     {
 
     static void repatchPointer(void* where, void* value)
     {
@@ -1873,20 +1792,9 @@ public:
         setPointer(where, value);
     }
 
         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:
     }
 
 private:
@@ -1969,6 +1877,33 @@ private:
 
         ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t));
     }
 
         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)
     {
 
     static void setPointer(void* code, void* value)
     {
@@ -2225,66 +2160,79 @@ private:
         return op | (imm.m_value.i << 10) | imm.m_value.imm4;
     }
 
         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 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:
     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);
         }
         
         {
             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);
         }
 
         {
             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);
         }
 
         {
             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);
         }
 
         {
             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));
         }
         {
             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);
         }
 
         {
             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);
         }
 
         {
             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);
         }
         
         {
             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);
         }
         
         {
             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);
         }
 
         {
             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;
         {
             ARMThumbImmediate newImm = imm;
             newImm.m_value.imm4 = imm4;
@@ -2293,7 +2241,7 @@ private:
             m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm));
         }
 
             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);
         {
             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.
         //    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));
         {
             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)
 
         // 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) {
         {
             bool up = true;
             if (imm < 0) {
@@ -2331,10 +2279,14 @@ private:
 
         // Administrative methods:
 
 
         // 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(); }
         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;
 
     private:
         AssemblerBuffer m_buffer;
index 5db2cb9fcd8bd9acced94328766cdb2c71841dbf..7d9d0925c5ee42931c3f7568eec49d7dda05049f 100644 (file)
@@ -26,8 +26,8 @@
 #ifndef AbstractMacroAssembler_h
 #define AbstractMacroAssembler_h
 
 #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>
 
 #include <wtf/Noncopyable.h>
 #include <wtf/UnusedParam.h>
 
@@ -41,6 +41,7 @@ class RepatchBuffer;
 template <class AssemblerType>
 class AbstractMacroAssembler {
 public:
 template <class AssemblerType>
 class AbstractMacroAssembler {
 public:
+    friend class JITWriteBarrierBase;
     typedef AssemblerType AssemblerType_T;
 
     typedef MacroAssemblerCodePtr CodePtr;
     typedef AssemblerType AssemblerType_T;
 
     typedef MacroAssemblerCodePtr CodePtr;
@@ -49,9 +50,6 @@ public:
     class Jump;
 
     typedef typename AssemblerType::RegisterID RegisterID;
     class Jump;
 
     typedef typename AssemblerType::RegisterID RegisterID;
-    typedef typename AssemblerType::JmpSrc JmpSrc;
-    typedef typename AssemblerType::JmpDst JmpDst;
-
 
     // Section 1: MacroAssembler operand types
     //
 
     // 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 {
     // 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)
         {
         }
 
             : 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
     //
     // 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)
         {
         }
             : m_value(value)
         {
         }
@@ -172,14 +170,21 @@ public:
         const void* m_value;
     };
 
         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.
     //
     // 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)
             : m_value(value)
 #if CPU(ARM) || CPU(MIPS)
             , m_isPointer(false)
@@ -188,7 +193,7 @@ public:
         }
 
 #if !CPU(X86_64)
         }
 
 #if !CPU(X86_64)
-        explicit Imm32(ImmPtr ptr)
+        explicit TrustedImm32(TrustedImmPtr ptr)
             : m_value(ptr.asIntptr())
 #if CPU(ARM) || CPU(MIPS)
             , m_isPointer(true)
             : 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
     // 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:
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // DataLabelPtr:
     };
 
     // DataLabelPtr:
@@ -264,8 +281,10 @@ public:
         {
         }
         
         {
         }
         
+        bool isSet() const { return m_label.isSet(); }
+        
     private:
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // DataLabel32:
     };
 
     // 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:
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // Call:
     };
 
     // Call:
@@ -313,7 +361,7 @@ public:
         {
         }
         
         {
         }
         
-        Call(JmpSrc jmp, Flags flags)
+        Call(AssemblerLabel jmp, Flags flags)
             : m_jmp(jmp)
             , m_flags(flags)
         {
             : m_jmp(jmp)
             , m_flags(flags)
         {
@@ -329,7 +377,7 @@ public:
             return Call(jump.m_jmp, Linkable);
         }
 
             return Call(jump.m_jmp, Linkable);
         }
 
-        JmpSrc m_jmp;
+        AssemblerLabel m_jmp;
     private:
         Flags m_flags;
     };
     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_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());
             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);
             masm->m_assembler.linkJump(m_jmp, label.m_label);
+#endif
         }
 
         }
 
+        bool isSet() const { return m_jmp.isSet(); }
+
     private:
     private:
-        JmpSrc m_jmp;
+        AssemblerLabel m_jmp;
+#if CPU(ARM_THUMB2)
+        ARMv7Assembler::JumpType m_type;
+        ARMv7Assembler::Condition m_condition;
+#endif
     };
 
     // JumpList:
     };
 
     // JumpList:
@@ -410,6 +482,11 @@ public:
             return !m_jumps.size();
         }
         
             return !m_jumps.size();
         }
         
+        void clear()
+        {
+            m_jumps.clear();
+        }
+        
         const JumpVector& jumps() { return m_jumps; }
 
     private:
         const JumpVector& jumps() { return m_jumps; }
 
     private:
@@ -418,11 +495,6 @@ public:
 
 
     // Section 3: Misc admin methods
 
 
     // Section 3: Misc admin methods
-    size_t size()
-    {
-        return m_assembler.size();
-    }
-
     Label label()
     {
         return Label(this);
     Label label()
     {
         return Label(this);
@@ -458,6 +530,11 @@ public:
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
     {
         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)
     {
 
     ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
     {
@@ -473,10 +550,19 @@ public:
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
     }
     {
         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() { }
 
     void beginUninterruptedSequence() { }
     void endUninterruptedSequence() { }
 
+#ifndef NDEBUG
+    unsigned debugOffset() { return m_assembler.debugOffset(); }
+#endif
+
 protected:
     AssemblerType m_assembler;
 
 protected:
     AssemblerType m_assembler;
 
@@ -488,17 +574,12 @@ protected:
         AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
     }
 
         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);
     }
 
     {
         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);
     }
     {
         return AssemblerType::getRelocatedAddress(code, label);
     }
@@ -518,6 +599,11 @@ protected:
         AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
     }
 
         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);
     static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
     {
         AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
@@ -527,10 +613,10 @@ protected:
     {
         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
     }
     {
         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 <jit/ExecutableAllocator.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
 
 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();
                 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;
         }
 
         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;
 
                 return 0;
 
-            void* result = allocator->alloc(m_size);
+            void* result = allocator->alloc(globalData, m_index);
 
             if (!result)
                 return 0;
 
 
             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)
         {
     protected:
         void append(const char* data, int size)
         {
-            if (m_size > m_capacity - size)
+            if (!isAvailable(size))
                 grow(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;
 
         }
 
         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;
         char* m_buffer;
         int m_capacity;
-        int m_size;
+        int m_index;
     };
 
 } // namespace JSC
     };
 
 } // 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;
 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:
 public:
+    typedef struct {
+        short high;
+        short low;
+    } TwoShorts;
+
     enum {
         UniqueConst,
         ReusableConst,
     enum {
         UniqueConst,
         ReusableConst,
@@ -120,6 +127,11 @@ public:
         AssemblerBuffer::ensureSpace(insnSpace);
     }
 
         AssemblerBuffer::ensureSpace(insnSpace);
     }
 
+    void ensureSpaceForAnyOneInstruction()
+    {
+        flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t));
+    }
+
     bool isAligned(int alignment)
     {
         flushIfNoSpaceFor(alignment);
     bool isAligned(int alignment)
     {
         flushIfNoSpaceFor(alignment);
@@ -171,44 +183,32 @@ public:
         correctDeltas(8);
     }
 
         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);
     {
         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.
     }
 
     // This flushing mechanism can be called after any unconditional jumps.
@@ -246,18 +246,45 @@ private:
         m_lastConstDelta = constSize;
     }
 
         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;
     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)
 
         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)
 
         if (alignPool) {
             if (alignPool & 1)
@@ -268,18 +295,17 @@ private:
                 AssemblerBuffer::putInt(AssemblerType::padForAlign32);
         }
 
                 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) {
         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_loadOffsets.clear();
         m_numConsts = 0;
-        m_maxDistance = maxPoolSize;
     }
 
     void flushIfNoSpaceFor(int nextInsnSize)
     }
 
     void flushIfNoSpaceFor(int nextInsnSize)
index cab28cd905c1695ca447c6c896c5bf918bf0c99d..9500b1ee44f2b454abc41a872fcf2fc8c0c861e6 100644 (file)
@@ -26,8 +26,7 @@
 #ifndef CodeLocation_h
 #define CodeLocation_h
 
 #ifndef CodeLocation_h
 #define CodeLocation_h
 
-
-#include <MacroAssemblerCodeRef.h>
+#include "MacroAssemblerCodeRef.h"
 
 #if ENABLE(ASSEMBLER)
 
 
 #if ENABLE(ASSEMBLER)
 
@@ -38,6 +37,7 @@ class CodeLocationLabel;
 class CodeLocationJump;
 class CodeLocationCall;
 class CodeLocationNearCall;
 class CodeLocationJump;
 class CodeLocationCall;
 class CodeLocationNearCall;
+class CodeLocationDataLabelCompact;
 class CodeLocationDataLabel32;
 class CodeLocationDataLabelPtr;
 
 class CodeLocationDataLabel32;
 class CodeLocationDataLabelPtr;
 
@@ -61,6 +61,7 @@ public:
     CodeLocationNearCall nearCallAtOffset(int offset);
     CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
     CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
     CodeLocationNearCall nearCallAtOffset(int offset);
     CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
     CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
+    CodeLocationDataLabelCompact dataLabelCompactAtOffset(int offset);
 
 protected:
     CodeLocationCommon()
 
 protected:
     CodeLocationCommon()
@@ -127,6 +128,15 @@ public:
         : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
 };
 
         : 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() {}
 class CodeLocationDataLabelPtr : public CodeLocationCommon {
 public:
     CodeLocationDataLabelPtr() {}
@@ -178,6 +188,12 @@ inline CodeLocationDataLabel32 CodeLocationCommon::dataLabel32AtOffset(int offse
     return CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset);
 }
 
     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)
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
index ae58946d97f13a705cecef26db337d6d14c07ba9..59b5a1e6110c5e6197b2144d2bb457b5b3917c1a 100644 (file)
 
 #if ENABLE(ASSEMBLER)
 
 
 #if ENABLE(ASSEMBLER)
 
+#define DUMP_LINK_STATISTICS 0
+#define DUMP_CODE 0
+
 #include <MacroAssembler.h>
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
 #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
 // 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.
 //
 //   * 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 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::DataLabel32 DataLabel32;
     typedef MacroAssembler::DataLabelPtr DataLabelPtr;
-    typedef MacroAssembler::JmpDst JmpDst;
 #if ENABLE(BRANCH_COMPACTION)
     typedef MacroAssembler::LinkRecord LinkRecord;
     typedef MacroAssembler::JumpLinkType JumpLinkType;
 #endif
 
 public:
 #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_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
     {
 #ifndef NDEBUG
         , m_completed(false)
 #endif
     {
-        linkCode(linkOffset);
+        linkCode();
     }
 
     ~LinkBuffer()
     }
 
     ~LinkBuffer()
@@ -107,13 +123,13 @@ public:
 
     void patch(DataLabelPtr label, void* value)
     {
 
     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)
     {
         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());
     }
 
         MacroAssembler::linkPointer(code(), target, value.executableAddress());
     }
 
@@ -147,6 +163,11 @@ public:
     {
         return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label)));
     }
     {
         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.
 
     // 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)));
     }
 
         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)
     {
 private:
     template <typename T> T applyOffset(T src)
     {
@@ -195,22 +223,21 @@ private:
         return m_code;
     }
 
         return m_code;
     }
 
-    void linkCode(void* linkOffset)
+    void linkCode()
     {
     {
-        UNUSED_PARAM(linkOffset);
         ASSERT(!m_code);
 #if !ENABLE(BRANCH_COMPACTION)
         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
 #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;
         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);
         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();
         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;
             
             // 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;
             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())
             // 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
             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
             // 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
             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();
         }
 
         jumpsToLink.clear();
-        m_size = writePtr + m_assembler->size() - readPtr;
+        m_size = writePtr + initialSize - readPtr;
         m_executablePool->tryShrink(m_code, initialSize, m_size);
         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
     }
 
 #endif
     }
 
@@ -277,10 +314,58 @@ private:
         ExecutableAllocator::cacheFlush(code(), m_size);
     }
 
         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;
     RefPtr<ExecutablePool> m_executablePool;
     size_t m_size;
     void* m_code;
     MacroAssembler* m_assembler;
+    JSGlobalData* m_globalData;
 #ifndef NDEBUG
     bool m_completed;
 #endif
 #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;
 public:
     typedef MIPSRegisters::RegisterID RegisterID;
     typedef MIPSRegisters::FPRegisterID FPRegisterID;
-    typedef SegmentedVector<int, 64> Jumps;
+    typedef SegmentedVector<AssemblerLabel, 64> Jumps;
 
     MIPSAssembler()
     {
 
     MIPSAssembler()
     {
@@ -166,46 +166,6 @@ public:
         OP_SH_FT = 16
     };
 
         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();
     void emitInst(MIPSWord op)
     {
         void* oldBase = m_buffer.data();
@@ -287,6 +247,11 @@ public:
         emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT));
     }
 
         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));
     void mfhi(RegisterID rd)
     {
         emitInst(0x00000010 | (rd << OP_SH_RD));
@@ -392,6 +357,18 @@ public:
                  | (rs << OP_SH_RS));
     }
 
                  | (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)
     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);
     }
 
         emitInst(0x45000000);
     }
 
-    JmpSrc newJmpSrc()
-    {
-        return JmpSrc(m_buffer.size());
-    }
-
     void appendJump()
     {
     void appendJump()
     {
-        m_jumps.append(m_buffer.size());
+        m_jumps.append(m_buffer.label());
     }
 
     void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
     }
 
     void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
@@ -512,6 +484,12 @@ public:
                  | (ft << OP_SH_FT));
     }
 
                  | (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)
     void lwc1(FPRegisterID ft, RegisterID rs, int offset)
     {
         emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
@@ -543,12 +521,23 @@ public:
         copDelayNop();
     }
 
         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 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));
     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));
     }
 
         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));
     void ceqd(FPRegisterID fs, FPRegisterID ft)
     {
         emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
@@ -621,12 +615,12 @@ public:
 
     // General helpers
 
 
     // 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();
     {
         while (!m_buffer.isAligned(alignment))
             bkpt();
@@ -634,44 +628,26 @@ public:
         return label();
     }
 
         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:
 
     }
 
     // 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;
 
         if (!result)
             return 0;
 
@@ -679,7 +655,11 @@ public:
         return result;
     }
 
         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;
     {
         // 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.
 
     // 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);
 
         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);
     }
 
         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)));
         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);
     }
 
         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);
     }
 
     {
         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
     {
         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));
     }
 
         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 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:
     }
 
 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) {
     /* 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
             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
                 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; };
 
 #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
 #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()
     {
     // 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)
     }
     
     void peek(RegisterID dest, int index = 0)
@@ -87,44 +93,44 @@ public:
         storePtr(src, Address(stackPointerRegister, (index * sizeof(void*))));
     }
 
         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*))));
     }
 
     {
         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.
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
     
     {
         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);
     }
     {
         branchTestPtr(cond, reg).linkTo(target, this);
     }
@@ -144,17 +150,17 @@ public:
         add32(src, dest);
     }
 
         add32(src, dest);
     }
 
-    void addPtr(Imm32 imm, RegisterID srcDest)
+    void addPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         add32(imm, 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);
     }
     {
         add32(imm, src, dest);
     }
@@ -164,7 +170,7 @@ public:
         and32(src, dest);
     }
 
         and32(src, dest);
     }
 
-    void andPtr(Imm32 imm, RegisterID srcDest)
+    void andPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         and32(imm, srcDest);
     }
     {
         and32(imm, srcDest);
     }
@@ -174,12 +180,12 @@ public:
         or32(src, dest);
     }
 
         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);
     }
     {
         or32(imm, dest);
     }
@@ -189,14 +195,14 @@ public:
         sub32(src, dest);
     }
     
         sub32(src, dest);
     }
     
-    void subPtr(Imm32 imm, RegisterID dest)
+    void subPtr(TrustedImm32 imm, RegisterID dest)
     {
         sub32(imm, 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)
     }
 
     void xorPtr(RegisterID src, RegisterID dest)
@@ -204,7 +210,7 @@ public:
         xor32(src, dest);
     }
 
         xor32(src, dest);
     }
 
-    void xorPtr(Imm32 imm, RegisterID srcDest)
+    void xorPtr(TrustedImm32 imm, RegisterID srcDest)
     {
         xor32(imm, srcDest);
     }
     {
         xor32(imm, srcDest);
     }
@@ -229,10 +235,15 @@ public:
     {
         return load32WithAddressOffsetPatch(address, dest);
     }
     {
         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)
     }
 
     void storePtr(RegisterID src, ImplicitAddress address)
@@ -250,14 +261,14 @@ public:
         store32(src, address);
     }
 
         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)
     }
 
     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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
 
     {
         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);
     }
 
     {
         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;
     {
         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);
     }
     {
         return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask);
     }
index b5b20fa07d220f630746b93f396ea18d559e3d28..2db5df1f87148f365ee62a308202a91d672a353e 100644 (file)
@@ -57,7 +57,11 @@ static bool isVFPPresent()
     }
 #endif
 
     }
 #endif
 
+#if (COMPILER(RVCT) && defined(__TARGET_FPU_VFP)) || (COMPILER(GCC) && defined(__VFP_FP__))
+    return true;
+#else
     return false;
     return false;
+#endif
 }
 
 const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent();
 }
 
 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;
     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,
         Equal = ARMAssembler::EQ,
         NotEqual = ARMAssembler::NE,
         Above = ARMAssembler::HI,
@@ -52,7 +53,10 @@ public:
         GreaterThan = ARMAssembler::GT,
         GreaterThanOrEqual = ARMAssembler::GE,
         LessThan = ARMAssembler::LT,
         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,
         Overflow = ARMAssembler::VS,
         Signed = ARMAssembler::MI,
         Zero = ARMAssembler::EQ,
@@ -86,14 +90,14 @@ public:
         m_assembler.adds_r(dest, dest, src);
     }
 
         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);
     }
 
     {
         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));
     }
     {
         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);
     }
 
         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)
     {
         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));
     }
 
         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));
     }
     {
         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);
     }
 
         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);
     {
         move(imm, ARMRegisters::S0);
         m_assembler.muls_r(dest, src, ARMRegisters::S0);
@@ -162,7 +166,7 @@ public:
         m_assembler.orrs_r(dest, dest, src);
     }
 
         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));
     }
     {
         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));
     }
 
         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));
     }
     {
         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));
     }
     
         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));
     }
     {
         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);
     }
 
         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));
     }
 
     {
         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);
     {
         load32(address, ARMRegisters::S1);
         sub32(imm, ARMRegisters::S1);
@@ -223,11 +227,22 @@ public:
         m_assembler.eors_r(dest, dest, src);
     }
 
         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));
     }
 
     {
         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);
     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;
     }
         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)
     {
     }
 
     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)
     }
     
     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
         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)
     }
 
     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);
     }
 
         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);
     {
         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);
     }
 
         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)
     {
         m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
         if (imm.m_isPointer)
@@ -343,13 +355,13 @@ public:
         push(ARMRegisters::S1);
     }
 
         push(ARMRegisters::S1);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         move(imm, ARMRegisters::S0);
         push(ARMRegisters::S0);
     }
 
     {
         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);
     {
         if (imm.m_isPointer)
             m_assembler.ldr_un_imm(dest, imm.m_value);
@@ -362,9 +374,9 @@ public:
         m_assembler.mov_r(dest, src);
     }
 
         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)
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
@@ -386,59 +398,64 @@ public:
             move(src, dest);
     }
 
             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);
     }
 
     {
         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));
     }
 
     {
         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);
     {
         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));
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     {
         UNUSED_PARAM(cond);
         UNUSED_PARAM(left);
@@ -447,7 +464,7 @@ public:
         return jump();
     }
 
         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);
     {
         load16(left, ARMRegisters::S0);
         move(right, ARMRegisters::S1);
@@ -455,20 +472,20 @@ public:
         return m_assembler.jmp(ARMCondition(cond));
     }
 
         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);
     }
 
     {
         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)));
     }
 
     {
         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);
     {
         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)));
     }
 
         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);
     }
 
     {
         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);
     {
         load32(address, ARMRegisters::S1);
         return branchTest32(cond, ARMRegisters::S1, mask);
@@ -506,14 +523,14 @@ public:
         load32(address, ARMRegisters::pc);
     }
 
         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)));
     }
 
     {
         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);
     {
         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));
     }
 
         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) {
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -542,7 +559,7 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
         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) {
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -555,28 +572,28 @@ public:
         return Jump(m_assembler.jmp(ARMCondition(cond)));
     }
 
         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)));
     }
 
     {
         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)));
     }
 
     {
         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)));
     }
 
     {
         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);
     {
         ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
         or32(src, dest);
@@ -602,9 +619,7 @@ public:
 
     Call call(RegisterID target)
     {
 
     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)
     }
 
     void call(Address address)
@@ -617,62 +632,48 @@ public:
         m_assembler.bx(linkRegister);
     }
 
         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));
     }
 
     {
         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));
     }
 
     {
         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)
         if (mask.m_value == -1)
-            m_assembler.cmp_r(0, ARMRegisters::S1);
+            m_assembler.cmp_r(0, reg);
         else
         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));
     }
 
         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));
     }
 
     {
         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);
     {
         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);
     }
 
         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);
     {
         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);
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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)
     Call call()
     {
 #if WTF_ARM_ARCH_AT_LEAST(5)
@@ -730,21 +740,21 @@ public:
         return Call::fromTailJump(oldJump);
     }
 
         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;
     }
 
     {
         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;
     }
 
     {
         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);
     {
         load32(left, ARMRegisters::S1);
         dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
@@ -752,7 +762,7 @@ public:
         return jump;
     }
 
         return jump;
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
         store32(ARMRegisters::S1, address);
     {
         DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
         store32(ARMRegisters::S1, address);
@@ -761,7 +771,7 @@ public:
 
     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
     {
 
     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
     {
-        return storePtrWithPatch(ImmPtr(0), address);
+        return storePtrWithPatch(TrustedImmPtr(0), address);
     }
 
     // Floating point operators
     }
 
     // Floating point operators
@@ -772,7 +782,7 @@ public:
 
     bool supportsFloatingPointTruncate() const
     {
 
     bool supportsFloatingPointTruncate() const
     {
-        return false;
+        return s_isVFPPresent;
     }
 
     bool supportsFloatingPointSqrt() const
     }
 
     bool supportsFloatingPointSqrt() const
@@ -798,7 +808,7 @@ public:
 
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
 
     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)
     }
 
     void addDouble(Address src, FPRegisterID dest)
@@ -809,7 +819,7 @@ public:
 
     void divDouble(FPRegisterID src, FPRegisterID dest)
     {
 
     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)
     }
 
     void divDouble(Address src, FPRegisterID dest)
@@ -821,7 +831,7 @@ public:
 
     void subDouble(FPRegisterID src, FPRegisterID dest)
     {
 
     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)
     }
 
     void subDouble(Address src, FPRegisterID dest)
@@ -832,7 +842,7 @@ public:
 
     void mulDouble(FPRegisterID src, FPRegisterID dest)
     {
 
     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)
     }
 
     void mulDouble(Address src, FPRegisterID dest)
@@ -843,13 +853,13 @@ public:
 
     void sqrtDouble(FPRegisterID src, FPRegisterID dest)
     {
 
     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)
     {
     }
 
     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)
     }
 
     void convertInt32ToDouble(Address src, FPRegisterID dest)
@@ -871,8 +881,8 @@ public:
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
     {
 
     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)));
         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
     // 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)
     {
     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'.
     }
 
     // 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)
     {
     // (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.
 
         // 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
         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);
     }
 
         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
     }
 
+    void nop()
+    {
+        m_assembler.nop();
+    }
+
 protected:
 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);
     }
     {
         return static_cast<ARMAssembler::Condition>(cond);
     }
@@ -967,9 +991,9 @@ protected:
                 prepareCall();
                 m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
             } else {
                 prepareCall();
                 m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
             } else {
-                ARMWord reg = m_assembler.getImm(offset, tmpReg);
+                m_assembler.moveImm(offset, tmpReg);
                 prepareCall();
                 prepareCall();
-                m_assembler.dtr_ur(true, targetReg, base, reg);
+                m_assembler.dtr_ur(true, targetReg, base, tmpReg);
             }
         } else  {
             offset = -offset;
             }
         } else  {
             offset = -offset;
@@ -981,9 +1005,9 @@ protected:
                 prepareCall();
                 m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
             } else {
                 prepareCall();
                 m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
             } else {
-                ARMWord reg = m_assembler.getImm(offset, tmpReg);
+                m_assembler.moveImm(offset, tmpReg);
                 prepareCall();
                 prepareCall();
-                m_assembler.dtr_dr(true, targetReg, base, reg);
+                m_assembler.dtr_dr(true, targetReg, base, tmpReg);
             }
         }
 #if WTF_ARM_ARCH_AT_LEAST(5)
             }
         }
 #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;
     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)
 
     MacroAssemblerARMv7()
         : m_inUninterruptedSequence(false)
@@ -100,7 +103,7 @@ public:
 
     static const Scale ScalePtr = TimesFour;
 
 
     static const Scale ScalePtr = TimesFour;
 
-    enum Condition {
+    enum RelationalCondition {
         Equal = ARMv7Assembler::ConditionEQ,
         NotEqual = ARMv7Assembler::ConditionNE,
         Above = ARMv7Assembler::ConditionHI,
         Equal = ARMv7Assembler::ConditionEQ,
         NotEqual = ARMv7Assembler::ConditionNE,
         Above = ARMv7Assembler::ConditionHI,
@@ -110,12 +113,16 @@ public:
         GreaterThan = ARMv7Assembler::ConditionGT,
         GreaterThanOrEqual = ARMv7Assembler::ConditionGE,
         LessThan = ARMv7Assembler::ConditionLT,
         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
     };
         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,
     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)
     // 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).
 
     // may often be a memory location (explictly described using an Address
     // object).
 
@@ -148,12 +155,12 @@ public:
         m_assembler.add(dest, dest, src);
     }
 
         m_assembler.add(dest, dest, src);
     }
 
-    void add32(Imm32 imm, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID dest)
     {
         add32(imm, dest, 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())
     {
         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);
 
     {
         load32(address, dataTempRegister);
 
@@ -187,7 +194,7 @@ public:
         add32(dataTempRegister, dest);
     }
 
         add32(dataTempRegister, dest);
     }
 
-    void add32(Imm32 imm, AbsoluteAddress address)
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
     {
         load32(address.m_ptr, dataTempRegister);
 
     {
         load32(address.m_ptr, dataTempRegister);
 
@@ -209,7 +216,7 @@ public:
         m_assembler.ARM_and(dest, dest, src);
     }
 
         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())
     {
         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
     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);
     }
 
         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);
     }
     {
         m_assembler.lsl(dest, dest, imm.m_value & 0x1f);
     }
@@ -240,7 +252,7 @@ public:
         m_assembler.smull(dest, dataTempRegister, dest, src);
     }
 
         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);
     {
         move(imm, dataTempRegister);
         m_assembler.smull(dest, dataTempRegister, src, dataTempRegister);
@@ -261,7 +273,7 @@ public:
         m_assembler.orr(dest, dest, src);
     }
 
         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())
     {
         ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm.m_value);
         if (armImm.isValid())
@@ -282,7 +294,7 @@ public:
         m_assembler.asr(dest, dest, dataTempRegister);
     }
 
         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);
     }
     {
         m_assembler.asr(dest, dest, imm.m_value & 0x1f);
     }
@@ -297,7 +309,7 @@ public:
         m_assembler.lsr(dest, dest, dataTempRegister);
     }
     
         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);
     }
     {
         m_assembler.lsr(dest, dest, imm.m_value & 0x1f);
     }
@@ -307,7 +319,7 @@ public:
         m_assembler.sub(dest, dest, src);
     }
 
         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())
     {
         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);
 
     {
         load32(address, dataTempRegister);
 
@@ -341,7 +353,7 @@ public:
         sub32(dataTempRegister, dest);
     }
 
         sub32(dataTempRegister, dest);
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
         load32(address.m_ptr, dataTempRegister);
 
     {
         load32(address.m_ptr, dataTempRegister);
 
@@ -363,7 +375,7 @@ public:
         m_assembler.eor(dest, dest, src);
     }
 
         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())
     {
         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
     // 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.
 
     // operand objects to loads and store will be implicitly constructed if a
     // register is passed.
 
@@ -455,9 +467,9 @@ public:
         load32(setupArmAddress(address), dest);
     }
 
         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));
     }
 
         m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0));
     }
 
@@ -468,16 +480,18 @@ public:
 
     DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
     {
 
     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;
     }
         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;
     }
 
         return label;
     }
 
@@ -492,14 +506,14 @@ public:
         if (armImm.isValid())
             m_assembler.ldrh(dest, address.base, armImm);
         else {
         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)
     {
             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;
     }
         store32(src, ArmAddress(address.base, dataTempRegister));
         return label;
     }
@@ -514,19 +528,19 @@ public:
         store32(src, setupArmAddress(address));
     }
 
         store32(src, setupArmAddress(address));
     }
 
-    void store32(Imm32 imm, ImplicitAddress address)
+    void store32(TrustedImm32 imm, ImplicitAddress address)
     {
         move(imm, dataTempRegister);
         store32(dataTempRegister, setupArmAddress(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));
     }
 
         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);
     {
         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))) {
 
         // 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;
         }
             base = addressTempRegister;
             offset = 0;
         }
@@ -571,7 +585,7 @@ public:
 
     void loadDouble(const void* address, FPRegisterID dest)
     {
 
     void loadDouble(const void* address, FPRegisterID dest)
     {
-        move(ImmPtr(address), addressTempRegister);
+        move(TrustedImmPtr(address), addressTempRegister);
         m_assembler.vldr(dest, addressTempRegister, 0);
     }
 
         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))) {
 
         // 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;
         }
             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 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;
         }
             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 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;
     }
         notEqual.link(this);
         return result;
     }
@@ -751,7 +765,7 @@ public:
         push(dataTempRegister);
     }
 
         push(dataTempRegister);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         move(imm, dataTempRegister);
         push(dataTempRegister);
     {
         move(imm, dataTempRegister);
         push(dataTempRegister);
@@ -761,7 +775,7 @@ public:
     //
     // Move values in registers.
 
     //
     // Move values in registers.
 
-    void move(Imm32 imm, RegisterID dest)
+    void move(TrustedImm32 imm, RegisterID dest)
     {
         uint32_t value = imm.m_value;
 
     {
         uint32_t value = imm.m_value;
 
@@ -787,9 +801,9 @@ public:
         m_assembler.mov(dest, src);
     }
 
         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)
     }
 
     void swap(RegisterID reg1, RegisterID reg2)
@@ -811,6 +825,10 @@ public:
             move(src, dest);
     }
 
             move(src, dest);
     }
 
+    void nop()
+    {
+        m_assembler.nop();
+    }
 
     // Forwards / external control flow operations:
     //
 
     // 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.
     // 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
     // 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?
 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)
     {
         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 {
             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);
             }
         }
     }
 
                 m_assembler.cmp(left, dataTempRegister);
             }
         }
     }
 
-    void test32(RegisterID reg, Imm32 mask)
+    void test32(RegisterID reg, TrustedImm32 mask)
     {
         int32_t imm = mask.m_value;
 
     {
         int32_t imm = mask.m_value;
 
@@ -868,65 +886,65 @@ private:
     }
 
 public:
     }
 
 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));
     }
 
     {
         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));
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         // 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);
     }
 
     {
         // 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);
     }
 
     {
         // 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);
     }
 
     {
         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);
     }
 
     {
         // 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);
     {
         load16(left, dataTempRegister);
         m_assembler.lsl(addressTempRegister, right, 16);
@@ -934,87 +952,76 @@ public:
         return branch32(cond, dataTempRegister, addressTempRegister);
     }
 
         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);
     {
         // 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));
     }
 
     {
         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);
     }
 
     {
         // 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));
     }
 
         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));
     }
 
         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);
     }
 
         // 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);
     }
 
         // 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));
     }
 
         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);
     }
 
         // 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)
     {
     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);
     }
 
     // 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.
     
     // * 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));
     }
 
         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);
         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));
     }
 
         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);
         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));
     }
 
         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));
     }
 
         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);
         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));
     }
     
         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:
 
 
     // Miscellaneous operations:
 
@@ -1100,35 +1120,35 @@ public:
         m_assembler.bkpt(0);
     }
 
         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);
     {
         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);
     {
         m_assembler.cmp(left, right);
         m_assembler.it(armV7Condition(cond), false);
@@ -1136,13 +1156,13 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
         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);
     {
         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);
     {
         compare32(left, right);
         m_assembler.it(armV7Condition(cond), false);
@@ -1150,26 +1170,11 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
         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().
     // 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);
     {
         load32(address, dataTempRegister);
         test32(dataTempRegister, mask);
@@ -1178,7 +1183,7 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
         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);
     {
         load8(address, dataTempRegister);
         test32(dataTempRegister, mask);
@@ -1187,48 +1192,48 @@ public:
         m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0));
     }
 
         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);
     }
 
     {
         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);
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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 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.
     {
         // 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();
     {
         oldJump.link(this);
         return tailRecursiveCall();
@@ -1246,20 +1251,21 @@ protected:
         return m_inUninterruptedSequence;
     }
 
         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);
     {
         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)
     {
 
     ArmAddress setupArmAddress(BaseIndex address)
     {
@@ -1268,7 +1274,7 @@ protected:
             if (imm.isValid())
                 m_assembler.add(addressTempRegister, address.base, imm);
             else {
             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);
             }
 
                 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);
 
         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);
     }
 
         return ArmAddress(address.base, addressTempRegister);
     }
 
@@ -1291,7 +1297,7 @@ protected:
         if ((address.offset >= -0xff) && (address.offset <= 0xfff))
             return ArmAddress(address.base, address.offset);
 
         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);
     }
 
         return ArmAddress(address.base, addressTempRegister);
     }
 
@@ -1304,21 +1310,26 @@ protected:
         if (imm.isValid())
             m_assembler.add(addressTempRegister, address.base, imm);
         else {
         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;
     }
 
             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));
     }
 
     {
         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);
     }
     {
         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)
     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);
     }
     {
         ASSERT_VALID_CODE_POINTER(m_value);
     }
@@ -152,7 +184,7 @@ public:
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
     void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
 #endif
 
-    bool operator!()
+    bool operator!() const
     {
         return !m_value;
     }
     {
         return !m_value;
     }
index 9853c3408d733e33b128d41b6f1a234d46c807c6..9cdfffc8bc7c9c5beeeeaf9a1539589074504e78 100644 (file)
 
 #if ENABLE(ASSEMBLER) && CPU(MIPS)
 
 
 #if ENABLE(ASSEMBLER) && CPU(MIPS)
 
-#include "AbstractMacroAssembler.h"
 #include "MIPSAssembler.h"
 #include "MIPSAssembler.h"
+#include "AbstractMacroAssembler.h"
 
 namespace JSC {
 
 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
 public:
 
 namespace JSC {
 
 class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
 public:
+    typedef MIPSRegisters::FPRegisterID FPRegisterID;
 
     MacroAssemblerMIPS()
         : m_fixedWidth(false)
 
     MacroAssemblerMIPS()
         : m_fixedWidth(false)
@@ -56,7 +57,9 @@ public:
     // FP temp register
     static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
 
     // FP temp register
     static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
 
-    enum Condition {
+    static const int MaximumCompactPtrAlignedAddressOffset = 0x7FFFFFFF;
+
+    enum RelationalCondition {
         Equal,
         NotEqual,
         Above,
         Equal,
         NotEqual,
         Above,
@@ -66,7 +69,10 @@ public:
         GreaterThan,
         GreaterThanOrEqual,
         LessThan,
         GreaterThan,
         GreaterThanOrEqual,
         LessThan,
-        LessThanOrEqual,
+        LessThanOrEqual
+    };
+
+    enum ResultCondition {
         Overflow,
         Signed,
         Zero,
         Overflow,
         Signed,
         Zero,
@@ -94,7 +100,7 @@ public:
     // Integer arithmetic operations:
     //
     // Operations are typically two operand - operation(source, srcDst)
     // 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).
 
     // may often be a memory location (explictly described using an Address
     // object).
 
@@ -103,12 +109,12 @@ public:
         m_assembler.addu(dest, dest, src);
     }
 
         m_assembler.addu(dest, dest, src);
     }
 
-    void add32(Imm32 imm, RegisterID dest)
+    void add32(TrustedImm32 imm, RegisterID dest)
     {
         add32(imm, dest, 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) {
     {
         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) {
     {
         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
     {
         /*
            li   addrTemp, address
@@ -215,7 +221,7 @@ public:
            addu dataTemp, dataTemp, immTemp
            sw   dataTemp, 0(addrTemp)
         */
            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)
         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);
     }
 
         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);
     {
         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);
     }
     {
         m_assembler.sll(dest, dest, imm.m_value);
     }
@@ -264,7 +270,7 @@ public:
         m_assembler.mul(dest, dest, src);
     }
 
         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);
     {
         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);
     void not32(RegisterID srcDest)
     {
         m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
@@ -290,7 +301,7 @@ public:
         m_assembler.orInsn(dest, dest, src);
     }
 
         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;
     {
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
             return;
@@ -314,17 +325,27 @@ public:
         m_assembler.srav(dest, dest, shiftAmount);
     }
 
         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);
     }
 
     {
         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(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) {
     {
         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) {
     {
         if (address.offset >= -32768 && address.offset <= 32767
             && !m_fixedWidth) {
@@ -397,7 +418,7 @@ public:
         sub32(dataTempRegister, dest);
     }
 
         sub32(dataTempRegister, dest);
     }
 
-    void sub32(Imm32 imm, AbsoluteAddress address)
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
     {
         /*
            li   addrTemp, address
     {
         /*
            li   addrTemp, address
@@ -406,7 +427,7 @@ public:
            subu dataTemp, dataTemp, immTemp
            sw   dataTemp, 0(addrTemp)
         */
            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
         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);
     }
 
         m_assembler.xorInsn(dest, dest, src);
     }
 
-    void xor32(Imm32 imm, RegisterID dest)
+    void xor32(TrustedImm32 imm, RegisterID dest)
     {
         /*
             li  immTemp, imm
     {
         /*
             li  immTemp, imm
@@ -435,10 +456,15 @@ public:
         m_assembler.xorInsn(dest, dest, immTempRegister);
     }
 
         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
     // 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.
 
     // 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)
         */
     {
         /*
             li  addrTemp, address
             lw  dest, 0(addrTemp)
         */
-        move(ImmPtr(address), addrTempRegister);
+        move(TrustedImmPtr(address), addrTempRegister);
         m_assembler.lw(dest, addrTempRegister, 0);
     }
 
         m_assembler.lw(dest, addrTempRegister, 0);
     }
 
@@ -580,33 +606,36 @@ public:
             lw  dest, 0(addrTemp)
         */
         DataLabel32 dataLabel(this);
             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;
     }
         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.  */
     }
 
     /* Need to use zero-extened load half-word for load16.  */
@@ -649,7 +678,7 @@ public:
             sw  src, 0(addrTemp)
         */
         DataLabel32 dataLabel(this);
             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;
         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) {
     {
         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)
         */
     {
         /*
             li  addrTemp, address
             sw  src, 0(addrTemp)
         */
-        move(ImmPtr(address), addrTempRegister);
+        move(TrustedImmPtr(address), addrTempRegister);
         m_assembler.sw(src, addrTempRegister, 0);
     }
 
         m_assembler.sw(src, addrTempRegister, 0);
     }
 
-    void store32(Imm32 imm, void* address)
+    void store32(TrustedImm32 imm, const void* address)
     {
         /*
             li  immTemp, imm
     {
         /*
             li  immTemp, imm
@@ -750,11 +779,11 @@ public:
             sw  src, 0(addrTemp)
         */
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
             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);
             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);
         }
     }
             m_assembler.sw(immTempRegister, addrTempRegister, 0);
         }
     }
@@ -779,6 +808,15 @@ public:
 #endif
     }
 
 #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,
     // Stack manipulation operations:
     //
     // The ABI is assumed to provide a stack abstraction to memory,
@@ -805,7 +843,7 @@ public:
         push(dataTempRegister);
     }
 
         push(dataTempRegister);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         move(imm, immTempRegister);
         push(immTempRegister);
     {
         move(imm, immTempRegister);
         push(immTempRegister);
@@ -815,7 +853,7 @@ public:
     //
     // Move values in registers.
 
     //
     // 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);
     {
         if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
@@ -832,9 +870,9 @@ public:
             m_assembler.move(dest, src);
     }
 
             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)
     }
 
     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.
     // 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.
 
     // 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));
     {
         // Make sure the immediate value is unsigned 8 bits.
         ASSERT(!(right.m_value & 0xFFFFFF00));
@@ -883,11 +921,11 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
         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);
             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);
             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);
         }
             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();
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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.
     {
         load32(left, dataTempRegister);
         // Be careful that the previous load32() uses immTempRegister.
@@ -993,7 +998,7 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
         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()
     {
         load32WithUnalignedHalfWords(left, dataTempRegister);
         // Be careful that the previous load32WithUnalignedHalfWords()
@@ -1003,26 +1008,26 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     {
         ASSERT(!(right.m_value & 0xFFFF0000));
         load16(left, dataTempRegister);
@@ -1032,7 +1037,7 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
         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);
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         m_assembler.andInsn(cmpTempRegister, reg, mask);
@@ -1041,7 +1046,7 @@ public:
         return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
     }
 
         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) {
     {
         ASSERT((cond == Zero) || (cond == NonZero));
         if (mask.m_value == -1 && !m_fixedWidth) {
@@ -1053,19 +1058,19 @@ public:
         return branchTest32(cond, reg, immTempRegister);
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     {
         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.
 
     // * 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) {
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -1148,13 +1153,13 @@ public:
         return Jump();
     }
 
         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);
     }
 
     {
         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) {
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -1199,14 +1204,14 @@ public:
         return Jump();
     }
 
         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);
     }
 
     {
         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) {
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
@@ -1253,12 +1258,33 @@ public:
         return Jump();
     }
 
         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);
     }
 
     {
         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()
     // Miscellaneous operations:
 
     void breakpoint()
@@ -1273,7 +1299,7 @@ public:
         m_assembler.nop();
         m_assembler.jal();
         m_assembler.nop();
         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()
     }
 
     Call call()
@@ -1282,14 +1308,14 @@ public:
         m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
         m_assembler.jalr(MIPSRegisters::t9);
         m_assembler.nop();
         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();
     }
 
     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)
     }
 
     Call call(Address address)
@@ -1299,7 +1325,7 @@ public:
         m_assembler.jalr(MIPSRegisters::t9);
         m_assembler.nop();
         m_fixedWidth = false;
         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()
     }
 
     void ret()
@@ -1308,12 +1334,12 @@ public:
         m_assembler.nop();
     }
 
         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);
             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)
             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 == 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);
     {
         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);
     {
         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);
     {
         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);
     {
         m_fixedWidth = true;
         DataLabel32 label(this);
@@ -1414,7 +1420,7 @@ public:
         return label;
     }
 
         return label;
     }
 
-    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
     {
         m_fixedWidth = true;
         DataLabelPtr label(this);
     {
         m_fixedWidth = true;
         DataLabelPtr label(this);
@@ -1423,7 +1429,7 @@ public:
         return label;
     }
 
         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);
     {
         m_fixedWidth = true;
         dataLabel = moveWithPatch(initialRightValue, immTempRegister);
@@ -1432,7 +1438,7 @@ public:
         return temp;
     }
 
         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);
     {
         m_fixedWidth = true;
         load32(left, dataTempRegister);
@@ -1442,7 +1448,7 @@ public:
         return temp;
     }
 
         return temp;
     }
 
-    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
     {
         m_fixedWidth = true;
         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
     {
         m_fixedWidth = true;
         DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
@@ -1453,18 +1459,18 @@ public:
 
     DataLabelPtr storePtrWithPatch(ImplicitAddress address)
     {
 
     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;
     }
 
     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;
         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)
     }
 
     Call makeTailRecursiveCall(Jump oldJump)
@@ -1482,7 +1488,7 @@ public:
             lwc1        dest, 0(addrTemp)
             lwc1        dest+1, 4(addrTemp)
          */
             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);
         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
     }
 
 #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)
     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)
          */
             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);
         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);
     }
 
         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(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. */
     void insertRelaxationWords()
     {
         /* We need four words for relaxation. */
@@ -1587,7 +1634,7 @@ public:
         m_assembler.bc1t();
         m_assembler.nop();
         insertRelaxationWords();
         m_assembler.bc1t();
         m_assembler.nop();
         insertRelaxationWords();
-        return Jump(m_assembler.newJmpSrc());
+        return Jump(m_assembler.label());
     }
 
     Jump branchFalse()
     }
 
     Jump branchFalse()
@@ -1596,7 +1643,7 @@ public:
         m_assembler.bc1f();
         m_assembler.nop();
         insertRelaxationWords();
         m_assembler.bc1f();
         m_assembler.nop();
         insertRelaxationWords();
-        return Jump(m_assembler.newJmpSrc());
+        return Jump(m_assembler.label());
     }
 
     Jump branchEqual(RegisterID rs, RegisterID rt)
     }
 
     Jump branchEqual(RegisterID rs, RegisterID rt)
@@ -1605,7 +1652,7 @@ public:
         m_assembler.beq(rs, rt, 0);
         m_assembler.nop();
         insertRelaxationWords();
         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)
     }
 
     Jump branchNotEqual(RegisterID rs, RegisterID rt)
@@ -1614,7 +1661,7 @@ public:
         m_assembler.bne(rs, rt, 0);
         m_assembler.nop();
         insertRelaxationWords();
         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)
     }
 
     Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
@@ -1624,7 +1671,7 @@ public:
             return branchTrue();
         }
         if (cond == DoubleNotEqual) {
             return branchTrue();
         }
         if (cond == DoubleNotEqual) {
-            m_assembler.ceqd(left, right);
+            m_assembler.cueqd(left, right);
             return branchFalse(); // false
         }
         if (cond == DoubleGreaterThan) {
             return branchFalse(); // false
         }
         if (cond == DoubleGreaterThan) {
@@ -1632,7 +1679,7 @@ public:
             return branchFalse(); // false
         }
         if (cond == DoubleGreaterThanOrEqual) {
             return branchFalse(); // false
         }
         if (cond == DoubleGreaterThanOrEqual) {
-            m_assembler.cnged(right, left);
+            m_assembler.cnged(left, right);
             return branchFalse(); // false
         }
         if (cond == DoubleLessThan) {
             return branchFalse(); // false
         }
         if (cond == DoubleLessThan) {
@@ -1647,6 +1694,10 @@ public:
             m_assembler.cueqd(left, right);
             return branchTrue();
         }
             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
         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);
     {
         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:
     }
 
 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;
 
     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);
     }
 
     {
         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);
     }
     
     {
         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);
     }
     
     {
         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);
     }
     
     {
         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);
     }
 
     {
         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);
     }
     {
         m_assembler.subl_im(imm.m_value, address.m_ptr);
     }
@@ -98,7 +98,7 @@ public:
         m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
     }
 
         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);
     }
     {
         m_assembler.movl_i32m(imm.m_value, address);
     }
@@ -108,13 +108,13 @@ public:
         m_assembler.movl_rm(src, address);
     }
 
         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)));
     }
 
     {
         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)));
     {
         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);
     }
 
     {
         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)));
     }
 
     {
         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)));
     }
 
     {
         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);
     }
 
     {
         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; }
     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;
 
 public:
     typedef X86Assembler::FPRegisterID FPRegisterID;
+    
+    static const int MaximumCompactPtrAlignedAddressOffset = 127;
 
 
-    enum Condition {
+    enum RelationalCondition {
         Equal = X86Assembler::ConditionE,
         NotEqual = X86Assembler::ConditionNE,
         Above = X86Assembler::ConditionA,
         Equal = X86Assembler::ConditionE,
         NotEqual = X86Assembler::ConditionNE,
         Above = X86Assembler::ConditionA,
@@ -51,7 +53,10 @@ public:
         GreaterThan = X86Assembler::ConditionG,
         GreaterThanOrEqual = X86Assembler::ConditionGE,
         LessThan = X86Assembler::ConditionL,
         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,
         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)
     // 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).
 
     // may often be a memory location (explictly described using an Address
     // object).
 
@@ -92,12 +97,12 @@ public:
         m_assembler.addl_rr(src, dest);
     }
 
         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);
     }
 
     {
         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);
     }
     {
         m_assembler.addl_ir(imm.m_value, dest);
     }
@@ -117,7 +122,7 @@ public:
         m_assembler.andl_rr(src, dest);
     }
 
         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);
     }
     {
         m_assembler.andl_ir(imm.m_value, dest);
     }
@@ -132,36 +137,64 @@ public:
         m_assembler.andl_mr(src.offset, src.base, dest);
     }
 
         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);
     }
 
     {
         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)
     {
     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);
             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)
     }
     
     void mul32(RegisterID src, RegisterID dest)
@@ -174,7 +207,7 @@ public:
         m_assembler.imull_mr(src.offset, src.base, dest);
     }
     
         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);
     }
     {
         m_assembler.imull_i32r(src, imm.m_value, dest);
     }
@@ -204,7 +237,7 @@ public:
         m_assembler.orl_rr(src, dest);
     }
 
         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);
     }
     {
         m_assembler.orl_ir(imm.m_value, dest);
     }
@@ -219,76 +252,114 @@ public:
         m_assembler.orl_mr(src.offset, src.base, dest);
     }
 
         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);
     }
 
     {
         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)
     {
     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);
             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);
     }
     
     {
         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)
     {
     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);
             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);
             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(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);
     }
     
     {
         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);
     }
     {
         m_assembler.subl_im(imm.m_value, address.offset, address.base);
     }
@@ -309,12 +380,12 @@ public:
         m_assembler.xorl_rr(src, dest);
     }
 
         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);
     }
 
     {
         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);
     }
     {
         m_assembler.xorl_ir(imm.m_value, dest);
     }
@@ -329,6 +400,24 @@ public:
         m_assembler.xorl_mr(src.offset, src.base, dest);
     }
     
         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);
     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
     // 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.
 
     // 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);
     }
         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)
     {
 
     void load16(BaseIndex address, RegisterID dest)
     {
@@ -388,7 +496,7 @@ public:
         m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
     }
 
         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);
     }
     {
         m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
     }
@@ -398,6 +506,13 @@ public:
     //
     // Presently only supports SSE, not x87 floating point.
 
     //
     // 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());
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -416,6 +531,17 @@ public:
         m_assembler.addsd_rr(src, dest);
     }
 
         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());
     void addDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -428,6 +554,15 @@ public:
         m_assembler.divsd_rr(src, dest);
     }
 
         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());
     void divDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -440,6 +575,15 @@ public:
         m_assembler.subsd_rr(src, dest);
     }
 
         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());
     void subDouble(Address src, FPRegisterID dest)
     {
         ASSERT(isSSE2Present());
@@ -452,6 +596,17 @@ public:
         m_assembler.mulsd_rr(src, dest);
     }
 
         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());
     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).
     // 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);
     {
         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'.
     }
 
     // Convert 'src' to an integer, and places the resulting 'dest'.
@@ -564,7 +720,7 @@ public:
         m_assembler.push_m(address.offset, address.base);
     }
 
         m_assembler.push_m(address.offset, address.base);
     }
 
-    void push(Imm32 imm)
+    void push(TrustedImm32 imm)
     {
         m_assembler.push_i32(imm.m_value);
     }
     {
         m_assembler.push_i32(imm.m_value);
     }
@@ -574,9 +730,9 @@ public:
     //
     // Move values in registers.
 
     //
     // 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);
         // 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);
     }
 
             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);
     }
     {
         m_assembler.movq_i64r(imm.asIntptr(), dest);
     }
@@ -620,7 +776,7 @@ public:
             m_assembler.movl_rr(src, dest);
     }
 
             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);
     }
     {
         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.
     // 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:
     // 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)));
     }
 
     {
         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)));
     }
 
     {
         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);
     {
         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)));
     }
     
         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)));
     }
     
     {
         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)));
     }
 
     {
         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)));
     }
 
     {
         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)));
     }
 
     {
         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);
     }
 
     {
         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)));
     }
 
     {
         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));
 
     {
         ASSERT(!(right.m_value & 0xFFFF0000));
 
@@ -726,16 +891,14 @@ public:
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
         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)));
     }
 
         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);
         // 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)));
     }
 
         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
         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)));
     }
 
         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
         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)));
     }
     
         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
         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)));
     }
     
         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
         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.
     
     // * 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)));
     }
 
         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)));
     }
     
         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)));
     }
 
         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)));
     }
 
         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)));
     }
 
         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);
         mul32(src, dest);
+        if (cond != Overflow)
+            m_assembler.testl_rr(dest, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
 
         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);
         mul32(src, dest);
+        if (cond != Overflow)
+            m_assembler.testl_rr(dest, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
         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);
         mul32(imm, src, dest);
+        if (cond != Overflow)
+            m_assembler.testl_rr(dest, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
     
         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)));
     }
     
         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)));
     }
 
         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)));
     }
 
         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)));
     }
 
         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)));
     }
 
         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)));
     }
 
         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)));
     }
         or32(src, dest);
         return Jump(m_assembler.jCC(x86Condition(cond)));
     }
@@ -946,35 +1148,14 @@ public:
         m_assembler.ret();
     }
 
         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);
     }
 
     {
         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);
     {
         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().
 
     // 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);
     {
         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);
     }
 
         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);
     {
         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);
     }
 
         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:
 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);
     }
     {
         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::load32;
     using MacroAssemblerX86Common::store32;
     using MacroAssemblerX86Common::call;
+    using MacroAssemblerX86Common::addDouble;
     using MacroAssemblerX86Common::loadDouble;
     using MacroAssemblerX86Common::convertInt32ToDouble;
 
     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));
     }
     
         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));
     }
     
         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));
     }
 
         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));
     }
 
         sub32(imm, Address(scratchRegister));
     }
 
@@ -88,17 +89,23 @@ public:
 
     void loadDouble(const void* address, FPRegisterID dest)
     {
 
     void loadDouble(const void* address, FPRegisterID dest)
     {
-        move(ImmPtr(address), scratchRegister);
+        move(TrustedImmPtr(address), scratchRegister);
         loadDouble(scratchRegister, dest);
     }
 
         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);
     }
 
         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);
     {
         move(X86Registers::eax, scratchRegister);
         move(imm, X86Registers::eax);
@@ -108,26 +115,26 @@ public:
 
     Call call()
     {
 
     Call call()
     {
-        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+        DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
         Call result = Call(m_assembler.call(scratchRegister), Call::Linkable);
         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()
     {
         return result;
     }
 
     Call tailRecursiveCall()
     {
-        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
+        DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
         Jump newJump = Jump(m_assembler.jmp_r(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);
         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));
         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);
     }
 
         return Call::fromTailJump(newJump);
     }
 
@@ -137,30 +144,30 @@ public:
         m_assembler.addq_rr(src, dest);
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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));
     }
     
         addPtr(imm, Address(scratchRegister));
     }
     
@@ -169,7 +176,7 @@ public:
         m_assembler.andq_rr(src, dest);
     }
 
         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);
     }
     {
         m_assembler.andq_ir(imm.m_value, srcDest);
     }
@@ -179,28 +186,46 @@ public:
         m_assembler.orq_rr(src, dest);
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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(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);
     }
     
     {
         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);
     {
         move(imm, scratchRegister);
         m_assembler.subq_rr(scratchRegister, dest);
@@ -211,7 +236,7 @@ public:
         m_assembler.xorq_rr(src, dest);
     }
 
         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);
     }
     {
         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);
     }
 
         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);
     {
         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);
     }
         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)
     {
 
     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);
     {
         move(imm, scratchRegister);
         storePtr(scratchRegister, address);
@@ -287,7 +318,7 @@ public:
         m_assembler.movq_rr(src, dest);
     }
 
         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);
     {
         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);
     }
 
         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)));
     }
 
     {
         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);
     }
 
     {
         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)));
     }
 
     {
         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);
     }
 
         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)));
     }
 
     {
         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);
     }
 
     {
         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)));
     }
 
     {
         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)
     {
         // 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)));
     }
 
         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);
     {
         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)));
     }
 
         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);
     {
         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)));
     }
 
         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)));
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     }
 
     {
         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);
     {
         DataLabelPtr label = moveWithPatch(initialValue, scratchRegister);
         storePtr(scratchRegister, address);
@@ -410,20 +445,13 @@ public:
     }
 
     using MacroAssemblerX86Common::branchTest8;
     }
 
     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);
     }
 
         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; }
     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))
     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());
     }
         else
             X86Assembler::linkCall(code, call.m_jmp, function.value());
     }
index 72cf6b27f09e3507e9cdfec0c7cff904260cc03f..6ea6d8df3f6443bbcfa4e3e65dce4775790d08e6 100644 (file)
@@ -87,14 +87,14 @@ public:
         MacroAssembler::repatchInt32(dataLabel32, value);
     }
 
         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)
     }
 
     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_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_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,
         OP_CDQ                          = 0x99,
         OP_MOV_EAXOv                    = 0xA1,
         OP_MOV_OvEAX                    = 0xA3,
@@ -219,54 +221,10 @@ private:
     class X86InstructionFormatter;
 public:
 
     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()
     {
     }
 
     X86Assembler()
     {
     }
 
-    size_t size() const { return m_formatter.size(); }
-
     // Stack operations:
 
     void push_r(RegisterID reg)
     // Stack operations:
 
     void push_r(RegisterID reg)
@@ -298,7 +256,7 @@ public:
     // Arithmetic operations:
 
 #if !CPU(X86_64)
     // 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);
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
@@ -375,7 +333,7 @@ public:
         }
     }
 #else
         }
     }
 #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);
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
@@ -441,7 +399,7 @@ public:
         }
     }
 #else
         }
     }
 #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);
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
@@ -527,7 +485,7 @@ public:
         }
     }
 #else
         }
     }
 #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);
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
@@ -593,7 +551,7 @@ public:
         }
     }
 #else
         }
     }
 #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);
     {
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
@@ -866,12 +824,12 @@ public:
         }
     }
 #else
         }
     }
 #else
-    void cmpl_rm(RegisterID reg, void* addr)
+    void cmpl_rm(RegisterID reg, const void* addr)
     {
         m_formatter.oneByteOp(OP_CMP_EvGv, reg, 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);
     {
         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);
     }
         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);
     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);
     }
     
         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)
     {
         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);
     }
     {
         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)
     {
 
     void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
     {
@@ -1075,7 +1043,7 @@ public:
         m_formatter.immediate32(imm);
     }
 
         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)
     {
         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);
     }
 
         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));
     }
 
     {
         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));
     {
         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);
     }
 
         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);
     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
     
     
 #else
-    void movl_rm(RegisterID src, void* addr)
+    void movl_rm(RegisterID src, const void* addr)
     {
         if (src == X86Registers::eax)
             movl_EAXm(addr);
     {
         if (src == X86Registers::eax)
             movl_EAXm(addr);
@@ -1160,7 +1133,7 @@ public:
             m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
     }
     
             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);
     {
         if (dst == X86Registers::eax)
             movl_mEAX(addr);
@@ -1168,7 +1141,7 @@ public:
             m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
     }
 
             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);
     {
         m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
         m_formatter.immediate32(imm);
@@ -1206,16 +1179,16 @@ public:
 
     // Flow control:
 
 
     // Flow control:
 
-    JmpSrc call()
+    AssemblerLabel call()
     {
         m_formatter.oneByteOp(OP_CALL_rel32);
         return m_formatter.immediateRel32();
     }
     
     {
         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);
     {
         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)
     }
     
     void call_m(int offset, RegisterID base)
@@ -1223,19 +1196,19 @@ public:
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, base, offset);
     }
 
         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();
     }
     
     {
         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. :-/
     // 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);
     {
         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)
     }
     
     void jmp_m(int offset, RegisterID base)
@@ -1243,95 +1216,95 @@ public:
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
     }
 
         m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
     }
 
-    JmpSrc jne()
+    AssemblerLabel jne()
     {
         m_formatter.twoByteOp(jccRel32(ConditionNE));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionNE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jnz()
+    AssemblerLabel jnz()
     {
         return jne();
     }
 
     {
         return jne();
     }
 
-    JmpSrc je()
+    AssemblerLabel je()
     {
         m_formatter.twoByteOp(jccRel32(ConditionE));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jz()
+    AssemblerLabel jz()
     {
         return je();
     }
 
     {
         return je();
     }
 
-    JmpSrc jl()
+    AssemblerLabel jl()
     {
         m_formatter.twoByteOp(jccRel32(ConditionL));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionL));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jb()
+    AssemblerLabel jb()
     {
         m_formatter.twoByteOp(jccRel32(ConditionB));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionB));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jle()
+    AssemblerLabel jle()
     {
         m_formatter.twoByteOp(jccRel32(ConditionLE));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionLE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jbe()
+    AssemblerLabel jbe()
     {
         m_formatter.twoByteOp(jccRel32(ConditionBE));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionBE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jge()
+    AssemblerLabel jge()
     {
         m_formatter.twoByteOp(jccRel32(ConditionGE));
         return m_formatter.immediateRel32();
     }
 
     {
         m_formatter.twoByteOp(jccRel32(ConditionGE));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc jg()
+    AssemblerLabel jg()
     {
         m_formatter.twoByteOp(jccRel32(ConditionG));
         return m_formatter.immediateRel32();
     }
 
     {
         m_formatter.twoByteOp(jccRel32(ConditionG));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc ja()
+    AssemblerLabel ja()
     {
         m_formatter.twoByteOp(jccRel32(ConditionA));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionA));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jae()
+    AssemblerLabel jae()
     {
         m_formatter.twoByteOp(jccRel32(ConditionAE));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionAE));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc jo()
+    AssemblerLabel jo()
     {
         m_formatter.twoByteOp(jccRel32(ConditionO));
         return m_formatter.immediateRel32();
     }
 
     {
         m_formatter.twoByteOp(jccRel32(ConditionO));
         return m_formatter.immediateRel32();
     }
 
-    JmpSrc jp()
+    AssemblerLabel jp()
     {
         m_formatter.twoByteOp(jccRel32(ConditionP));
         return m_formatter.immediateRel32();
     }
     
     {
         m_formatter.twoByteOp(jccRel32(ConditionP));
         return m_formatter.immediateRel32();
     }
     
-    JmpSrc js()
+    AssemblerLabel js()
     {
         m_formatter.twoByteOp(jccRel32(ConditionS));
         return m_formatter.immediateRel32();
     }
 
     {
         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();
     {
         m_formatter.twoByteOp(jccRel32(cond));
         return m_formatter.immediateRel32();
@@ -1364,7 +1337,7 @@ public:
     }
 
 #if !CPU(X86_64)
     }
 
 #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);
     {
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
@@ -1397,6 +1370,12 @@ public:
     }
 #endif
 
     }
 #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);
     void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
     {
         m_formatter.prefix(PRE_SSE_F2);
@@ -1503,17 +1482,17 @@ public:
 
     // Assembler admin methods:
 
 
     // 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);
     {
         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.
 
     // 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());
 
         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);
     }
     
         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);
     }
 
 
         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);
     }
 
 
         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);
     }
 
         setPointer(reinterpret_cast<char*>(code) + where.m_offset, value);
     }
@@ -1568,6 +1548,13 @@ public:
     {
         setRel32(from, to);
     }
     {
         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)
     {
 
     static void repatchInt32(void* where, int32_t value)
     {
@@ -1578,57 +1565,43 @@ public:
     {
         setPointer(where, value);
     }
     {
         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:
     }
 
 private:
@@ -1642,6 +1615,11 @@ private:
     {
         reinterpret_cast<int32_t*>(where)[-1] = value;
     }
     {
         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)
     {
 
     static void setRel32(void* from, void* to)
     {
@@ -1716,6 +1694,14 @@ private:
             m_buffer.putByteUnchecked(opcode);
             memoryModRM_disp32(reg, base, offset);
         }
             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)
         {
 
         void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
         {
@@ -1726,7 +1712,7 @@ private:
         }
 
 #if !CPU(X86_64)
         }
 
 #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);
         {
             m_buffer.ensureSpace(maxInstructionSize);
             m_buffer.putByteUnchecked(opcode);
@@ -1822,6 +1808,14 @@ private:
             m_buffer.putByteUnchecked(opcode);
             memoryModRM_disp32(reg, base, offset);
         }
             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)
         {
 
         void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
         {
@@ -1917,18 +1911,29 @@ private:
             m_buffer.putInt64Unchecked(imm);
         }
 
             m_buffer.putInt64Unchecked(imm);
         }
 
-        JmpSrc immediateRel32()
+        AssemblerLabel immediateRel32()
         {
             m_buffer.putIntUnchecked(0);
         {
             m_buffer.putIntUnchecked(0);
-            return JmpSrc(m_buffer.size());
+            return label();
         }
 
         // Administrative methods:
 
         }
 
         // 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(); }
         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:
 
 
     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.
         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
  * 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 "config.h"
 #include "CodeBlock.h"
 
-#include "JIT.h"
-#include "JSValue.h"
+#include "BytecodeGenerator.h"
+#include "Debugger.h"
 #include "Interpreter.h"
 #include "Interpreter.h"
+#include "JIT.h"
+#include "JSActivation.h"
 #include "JSFunction.h"
 #include "JSStaticScopeObject.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>
 
 #include <stdio.h>
 #include <wtf/StringExtras.h>
 
@@ -49,9 +52,9 @@ namespace JSC {
 static UString escapeQuotes(const UString& str)
 {
     UString result = str;
 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;
         pos += 4;
     }
     return result;
@@ -63,19 +66,19 @@ static UString valueToSourceString(ExecState* exec, JSValue val)
         return "0";
 
     if (val.isString())
         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 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)
 {
 }
 
 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
 }
 
 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));
 
     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)
 }
 
 static UString regexpToSourceString(RegExp* regExp)
@@ -100,12 +103,12 @@ static UString regexpToSourceString(RegExp* regExp)
     if (regExp->multiline())
         postfix[index] = 'm';
 
     if (regExp->multiline())
         postfix[index] = 'm';
 
-    return makeString("/", regExp->pattern(), postfix);
+    return makeUString("/", regExp->pattern(), postfix);
 }
 
 static CString regexpName(int re, RegExp* regexp)
 {
 }
 
 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)
 }
 
 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());
     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)
 }
 
 #if ENABLE(JIT)
@@ -223,32 +226,32 @@ static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instructio
 
 static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
 {
 
 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:
 }
 
 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:
         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:
         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:
         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:
         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:
         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:
         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");
         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();
 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
 }
 
 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)) {
         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)) {
         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)) {
         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)) {
         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("\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());
     }
             ++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 {
         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());
             ++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("\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());
     }
             ++i;
         } while (i < m_rareData->m_regexps.size());
     }
@@ -395,7 +398,8 @@ void CodeBlock::dump(ExecState* exec) const
              ++i;
         } while (i < m_structureStubInfos.size());
     }
              ++i;
         } while (i < m_structureStubInfos.size());
     }
-#else
+#endif
+#if ENABLE(INTERPRETER)
     if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
         printf("\nStructures:\n");
 
     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);
                     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;
         }
             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("  %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());
             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;
         }
             printf("[%4d] enter\n", location);
             break;
         }
-        case op_enter_with_activation: {
+        case op_create_activation: {
             int r0 = (++it)->u.operand;
             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: {
             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;
         }
             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: {
             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;
         }
             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());
         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;
         }
             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;
         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;
         }
             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;
         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;
         }
         case op_resolve_global: {
             int r0 = (++it)->u.operand;
-            JSValue scope = JSValue((++it)->u.jsCell);
             int id0 = (++it)->u.operand;
             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;
             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 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: {
             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;
         }
         case op_get_global_var: {
             int r0 = (++it)->u.operand;
-            JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
             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: {
             break;
         }
         case op_put_global_var: {
-            JSValue scope = JSValue((++it)->u.jsCell);
             int index = (++it)->u.operand;
             int r0 = (++it)->u.operand;
             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;
             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: {
             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;
         }
             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;
         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;
         }
             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;
         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;
         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: {
             break;
         }
         case op_new_func_exp: {
@@ -1026,27 +1077,24 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
             break;
         }
         case op_call: {
             break;
         }
         case op_call: {
-            int dst = (++it)->u.operand;
             int func = (++it)->u.operand;
             int argCount = (++it)->u.operand;
             int registerOffset = (++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: {
             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;
             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: {
             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;
             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: {
             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;
         }
         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: {
             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: {
             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;
         }
             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;
         }
             break;
         }
-        case op_construct_verify: {
+        case op_ret_object_or_this: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
             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: {
             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;
         }
         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;
         }
             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;
         }
             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;
             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: {
             break;
         }
         case op_jsr: {
@@ -1212,13 +1265,10 @@ static HashSet<CodeBlock*> liveCodeBlockSet;
     macro(immediateSwitchJumpTables) \
     macro(characterSwitchJumpTables) \
     macro(stringSwitchJumpTables) \
     macro(immediateSwitchJumpTables) \
     macro(characterSwitchJumpTables) \
     macro(stringSwitchJumpTables) \
-    macro(functionRegisterInfos)
-
-#define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \
+    macro(evalCodeCache) \
     macro(expressionInfo) \
     macro(lineInfo) \
     macro(expressionInfo) \
     macro(lineInfo) \
-    macro(getByIdExceptionInfo) \
-    macro(pcVector)
+    macro(callReturnIndexVector)
 
 template<typename T>
 static size_t sizeInBytes(const Vector<T>& vector)
 
 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)
     #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
     #undef DEFINE_VARS
 
     // Non-vector data members
@@ -1241,7 +1290,6 @@ void CodeBlock::dumpStatistics()
     size_t symbolTableIsNotEmpty = 0;
     size_t symbolTableTotalSize = 0;
 
     size_t symbolTableIsNotEmpty = 0;
     size_t symbolTableTotalSize = 0;
 
-    size_t hasExceptionInfo = 0;
     size_t hasRareData = 0;
 
     size_t isFunctionCode = 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)));
         }
 
             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); }
         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)
     #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;
     #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 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)
     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);
     #undef PRINT_STATS
 
     printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
@@ -1330,24 +1368,27 @@ void CodeBlock::dumpStatistics()
 #endif
 }
 
 #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_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_globalData(0)
 #ifndef NDEBUG
     , m_instructionCount(0)
 #endif
+    , m_argumentsRegister(-1)
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
     , m_needsFullScopeChain(ownerExecutable->needsActivation())
     , m_usesEval(ownerExecutable->usesEval())
-    , m_usesArguments(false)
     , m_isNumericCompareFunction(false)
     , m_isNumericCompareFunction(false)
+    , m_isStrictMode(ownerExecutable->isStrictMode())
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
     , m_symbolTable(symTab)
     , m_codeType(codeType)
     , m_source(sourceProvider)
     , m_sourceOffset(sourceOffset)
     , m_symbolTable(symTab)
-    , m_exceptionInfo(new ExceptionInfo)
 {
     ASSERT(m_source);
 
 {
     ASSERT(m_source);
 
@@ -1358,41 +1399,9 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassR
 
 CodeBlock::~CodeBlock()
 {
 
 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)
 #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_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
 #endif // ENABLE(JIT)
 
 #if DUMP_CODE_BLOCK_STATISTICS
@@ -1400,50 +1409,46 @@ CodeBlock::~CodeBlock()
 #endif
 }
 
 #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;
 
 {
     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)) {
     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)) {
         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)) {
         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)) {
         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)) {
         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)) {
         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))
         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;
         || (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;
     }
         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));
 }
 
     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)
     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)
     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)
 }
 
 HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
@@ -1544,122 +1543,66 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
     return 0;
 }
 
     return 0;
 }
 
-int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
+int CodeBlock::lineNumberForBytecodeOffset(unsigned bytecodeOffset)
 {
     ASSERT(bytecodeOffset < m_instructionCount);
 
 {
     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 low = 0;
-    int high = m_exceptionInfo->m_lineInfo.size();
+    int high = lineInfo.size();
     while (low < high) {
         int mid = low + (high - low) / 2;
     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;
     }
             low = mid + 1;
         else
             high = mid;
     }
-    
+
     if (!low)
         return m_ownerExecutable->source().firstLine();
     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);
 
 {
     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;
         startOffset = 0;
         endOffset = 0;
         divot = 0;
-        return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
+        return;
     }
 
     }
 
+    Vector<ExpressionRangeInfo>& expressionInfo = m_rareData->m_expressionInfo;
+
     int low = 0;
     int low = 0;
-    int high = m_exceptionInfo->m_expressionInfo.size();
+    int high = expressionInfo.size();
     while (low < high) {
         int mid = low + (high - low) / 2;
     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;
     }
             low = mid + 1;
         else
             high = mid;
     }
-    
+
     ASSERT(low);
     if (!low) {
         startOffset = 0;
         endOffset = 0;
         divot = 0;
     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)
 
 #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_structureStubInfos.shrinkToFit();
     m_globalResolveInfos.shrinkToFit();
     m_callLinkInfos.shrinkToFit();
-    m_linkedCallerList.shrinkToFit();
 #endif
 
     m_identifiers.shrinkToFit();
 #endif
 
     m_identifiers.shrinkToFit();
@@ -1724,22 +1666,49 @@ void CodeBlock::shrinkToFit()
     m_functionExprs.shrinkToFit();
     m_constantRegisters.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();
     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)
 #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
 
 } // 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
  * 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 "EvalCodeCache.h"
 #include "Instruction.h"
 #include "JITCode.h"
+#include "JITWriteBarrier.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Nodes.h"
 #include "JSGlobalObject.h"
 #include "JumpTable.h"
 #include "Nodes.h"
-#include "RegExp.h"
+#include "RegExpObject.h"
 #include "UString.h"
 #include <wtf/FastAllocBase.h>
 #include "UString.h"
 #include <wtf/FastAllocBase.h>
+#include <wtf/PassOwnPtr.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
 #include <wtf/RefPtr.h>
 #include <wtf/Vector.h>
 
@@ -46,8 +48,8 @@
 #include "StructureStubInfo.h"
 #endif
 
 #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;
 //      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 };
 
 
     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 {
     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
 
     struct HandlerInfo {
@@ -90,34 +94,27 @@ namespace JSC {
         int32_t lineNumber;
     };
 
         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()
 #if ENABLE(JIT)
     struct CallLinkInfo {
         CallLinkInfo()
-            : callee(0)
-            , position(0)
-            , hasSeenShouldRepatch(0)
+            : hasSeenShouldRepatch(false)
+            , isCall(false)
         {
         }
 
         {
         }
 
-        unsigned bytecodeIndex;
         CodeLocationNearCall callReturnLocation;
         CodeLocationDataLabelPtr hotPathBegin;
         CodeLocationNearCall hotPathOther;
         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; }
         bool isLinked() { return callee; }
+        void unlink()
+        {
+            hasSeenShouldRepatch = false;
+            callee.clear();
+        }
 
         bool seenOnce()
         {
 
         bool seenOnce()
         {
@@ -132,15 +129,13 @@ namespace JSC {
 
     struct MethodCallLinkInfo {
         MethodCallLinkInfo()
 
     struct MethodCallLinkInfo {
         MethodCallLinkInfo()
-            : cachedStructure(0)
-            , cachedPrototypeStructure(0)
         {
         }
 
         bool seenOnce()
         {
             ASSERT(!cachedStructure);
         {
         }
 
         bool seenOnce()
         {
             ASSERT(!cachedStructure);
-            return cachedPrototypeStructure;
+            return cachedPrototypeStructure.isFlagged();
         }
 
         void setSeen()
         }
 
         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.
             //     - 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;
         }
 
         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)
     };
 
     struct GlobalResolveInfo {
         GlobalResolveInfo(unsigned bytecodeOffset)
-            : structure(0)
-            , offset(0)
+            : offset(0)
             , bytecodeOffset(bytecodeOffset)
         {
         }
 
             , bytecodeOffset(bytecodeOffset)
         {
         }
 
-        Structure* structure;
+        WriteBarrier<Structure> structure;
         unsigned offset;
         unsigned bytecodeOffset;
     };
         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.
     // (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)
             : callReturnOffset(callReturnOffset)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
         {
         }
 
         unsigned callReturnOffset;
         {
         }
 
         unsigned callReturnOffset;
-        unsigned bytecodeIndex;
+        unsigned bytecodeOffset;
     };
 
     };
 
-    // valueAtPosition helpers for the binaryChop algorithm below.
+    // valueAtPosition helpers for the binarySearch algorithm.
 
     inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
     {
 
     inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
     {
@@ -217,71 +203,25 @@ namespace JSC {
         return methodCallLinkInfo->callReturnLocation.executableAddress();
     }
 
         return methodCallLinkInfo->callReturnLocation.executableAddress();
     }
 
-    inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex* pc)
+    inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeOffset* pc)
     {
         return pc->callReturnOffset;
     }
     {
         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
 #endif
-    };
 
 
-    class CodeBlock : public FastAllocBase {
+    class CodeBlock {
+        WTF_MAKE_FAST_ALLOCATED;
         friend class JIT;
     protected:
         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();
 
     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();
 
 
         static void dumpStatistics();
 
@@ -291,9 +231,11 @@ namespace JSC {
         void printStructure(const char* name, const Instruction*, int operand) const;
 #endif
 
         void printStructure(const char* name, const Instruction*, int operand) const;
 #endif
 
+        bool isStrictMode() const { return m_isStrictMode; }
+
         inline bool isKnownNotImmediate(int index)
         {
         inline bool isKnownNotImmediate(int index)
         {
-            if (index == m_thisRegister)
+            if (index == m_thisRegister && !m_isStrictMode)
                 return true;
 
             if (isConstantRegisterIndex(index))
                 return true;
 
             if (isConstantRegisterIndex(index))
@@ -308,55 +250,41 @@ namespace JSC {
         }
 
         HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
         }
 
         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)
 
 #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)
         {
 
         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)
         {
         }
 
         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)
         {
         }
 
         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
 #endif
+
 #if ENABLE(INTERPRETER)
 #if ENABLE(INTERPRETER)
-        unsigned bytecodeOffset(CallFrame*, Instruction* returnAddress)
+        unsigned bytecodeOffset(Instruction* returnAddress)
         {
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
         {
             return static_cast<Instruction*>(returnAddress) - instructions().begin();
         }
@@ -374,11 +302,11 @@ namespace JSC {
 #endif
 
 #if ENABLE(JIT)
 #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
 
 #endif
 
-        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable; }
+        ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
 
         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
 
 
         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; }
         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; }
 
 
         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(); }
 
         unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
         unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
 
+        void createActivation(CallFrame*);
+
+        void clearEvalCache();
+
 #if ENABLE(INTERPRETER)
 #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(); }
         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]; }
 
         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);
 
         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 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]; }
         MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
-
-        void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
 #endif
 #endif
+        unsigned globalResolveInfoCount() const
+        {
+#if ENABLE(JIT)    
+            if (m_globalData->canUseJIT())
+                return m_globalResolveInfos.size();
+#endif
+            return 0;
+        }
 
         // Exception handling support
 
 
         // 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]; }
 
         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)
 
 #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
 #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(); }
         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 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(); }
         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(); }
 
         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(); }
 
         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
 
 
         // Jump Tables
 
@@ -495,7 +525,9 @@ namespace JSC {
 
         int m_numCalleeRegisters;
         int m_numVars;
 
         int m_numCalleeRegisters;
         int m_numVars;
+        int m_numCapturedVars;
         int m_numParameters;
         int m_numParameters;
+        bool m_isConstructor;
 
     private:
 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
 
     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 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)
 
         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;
         JSGlobalData* m_globalData;
 
         Vector<Instruction> m_instructions;
@@ -526,11 +557,13 @@ namespace JSC {
 #endif
 
         int m_thisRegister;
 #endif
 
         int m_thisRegister;
+        int m_argumentsRegister;
+        int m_activationRegister;
 
         bool m_needsFullScopeChain;
         bool m_usesEval;
 
         bool m_needsFullScopeChain;
         bool m_usesEval;
-        bool m_usesArguments;
         bool m_isNumericCompareFunction;
         bool m_isNumericCompareFunction;
+        bool m_isStrictMode;
 
         CodeType m_codeType;
 
 
         CodeType m_codeType;
 
@@ -546,27 +579,30 @@ namespace JSC {
         Vector<GlobalResolveInfo> m_globalResolveInfos;
         Vector<CallLinkInfo> m_callLinkInfos;
         Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
         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;
 #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;
 
 
         SymbolTable* m_symbolTable;
 
-        OwnPtr<ExceptionInfo> m_exceptionInfo;
-
-        struct RareData : FastAllocBase {
+        struct RareData {
+           WTF_MAKE_FAST_ALLOCATED;
+        public:
             Vector<HandlerInfo> m_exceptionHandlers;
 
             // Rare Constants
             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;
             // Jump Tables
             Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
             Vector<SimpleJumpTable> m_characterSwitchJumpTables;
@@ -574,10 +610,17 @@ namespace JSC {
 
             EvalCodeCache m_evalCodeCache;
 
 
             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)
 #if ENABLE(JIT)
-            Vector<FunctionRegisterInfo> m_functionRegisterInfos;
+            Vector<CallReturnOffsetToBytecodeOffset> m_callReturnIndexVector;
 #endif
         };
 #endif
         };
+#if COMPILER(MSVC)
+        friend void WTF::deleteOwnedPtr<RareData>(RareData*);
+#endif
         OwnPtr<RareData> m_rareData;
     };
 
         OwnPtr<RareData> m_rareData;
     };
 
@@ -586,30 +629,19 @@ namespace JSC {
 
     class GlobalCodeBlock : public CodeBlock {
     public:
 
     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:
     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)
         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)
     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)
         {
         }
             , 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.
         // 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()
         {
         }
         ~FunctionCodeBlock()
@@ -657,10 +689,16 @@ namespace JSC {
     {
         CodeBlock* codeBlock = this->codeBlock();
         if (codeBlock->isConstantRegisterIndex(index))
     {
         CodeBlock* codeBlock = this->codeBlock();
         if (codeBlock->isConstantRegisterIndex(index))
-            return codeBlock->constantRegister(index);
+            return *reinterpret_cast<Register*>(&codeBlock->constantRegister(index));
         return this[index];
     }
 
         return this[index];
     }
 
+    inline Register& ExecState::uncheckedR(int index)
+    {
+        ASSERT(index < FirstConstantRegisterIndex);
+        return this[index];
+    }
+    
 } // namespace JSC
 
 #endif // CodeBlock_h
 } // namespace JSC
 
 #endif // CodeBlock_h
index 27c479d4e51c12fb3df93d671f5690a00bfaae39..1e181b9d7c359e9ef21d014c61fbea00670d1700 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class MarkStack;
+    typedef MarkStack SlotVisitor;
+
     class EvalCodeCache {
     public:
     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) {
 
             if (!evalExecutable) {
-                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource));
+                evalExecutable = EvalExecutable::create(exec, makeSource(evalSource), inStrictContext);
                 exceptionValue = evalExecutable->compile(exec, scopeChain);
                 if (exceptionValue)
                     return 0;
 
                 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(); }
 
         }
 
         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;
 
     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;
     };
 
         EvalCacheMap m_cacheMap;
     };
 
index c6468a5580423b7267466abe46f1be4d6407d328..b3bb5b711fe6a8a51ee9a4bbff2c46385964c170 100644 (file)
@@ -33,6 +33,7 @@
 #include "Opcode.h"
 #include "PropertySlot.h"
 #include "Structure.h"
 #include "Opcode.h"
 #include "PropertySlot.h"
 #include "Structure.h"
+#include "StructureChain.h"
 #include <wtf/VectorTraits.h>
 
 #define POLYMORPHIC_LIST_CACHE_SIZE 8
 #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.
     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;
         struct PolymorphicStubInfo {
             bool isChain;
             PolymorphicAccessStructureListStubRoutineType stubRoutine;
-            Structure* base;
+            WriteBarrier<Structure> base;
             union {
             union {
-                Structure* proto;
-                StructureChain* chain;
+                WriteBarrierBase<Structure> proto;
+                WriteBarrierBase<StructureChain> chain;
             } u;
 
             } u;
 
-            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
+            PolymorphicStubInfo()
+            {
+                u.proto.clear();
+            }
+
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
             {
                 stubRoutine = _stubRoutine;
             {
                 stubRoutine = _stubRoutine;
-                base = _base;
-                u.proto = 0;
+                base.set(globalData, owner, _base);
+                u.proto.clear();
                 isChain = false;
             }
             
                 isChain = false;
             }
             
-            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
             {
                 stubRoutine = _stubRoutine;
             {
                 stubRoutine = _stubRoutine;
-                base = _base;
-                u.proto = _proto;
+                base.set(globalData, owner, _base);
+                u.proto.set(globalData, owner, _proto);
                 isChain = false;
             }
             
                 isChain = false;
             }
             
-            void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
+            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
             {
                 stubRoutine = _stubRoutine;
             {
                 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];
         
                 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];
         {
             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.
 #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;
         }
 #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.
         {
             // 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;
         }
 
             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;
         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;
             PolymorphicAccessStructureList* polymorphicStructures;
             PropertySlot::GetValueFunc getterFunc;
         } u;
+        
+    private:
+        Instruction(StructureChain*);
+        Instruction(Structure*);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index b4f8e4401cb14af529e5eedcd87fdd2e060ed69b..5bbe047107f5b01c0289bea33186e1f84a3aafc7 100644 (file)
@@ -45,13 +45,13 @@ namespace JSC {
     };
 
     struct StringJumpTable {
     };
 
     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
 
         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);
         {
             StringOffsetTable::const_iterator end = offsetTable.end();
             StringOffsetTable::const_iterator loc = offsetTable.find(value);
@@ -61,7 +61,7 @@ namespace JSC {
         }
 
 #if ENABLE(JIT)
         }
 
 #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);
         {
             StringOffsetTable::const_iterator end = offsetTable.end();
             StringOffsetTable::const_iterator loc = offsetTable.find(value);
index bb7696dd8d6df5e84815c41184bddb9d485ff13d..0bb714bca2d14ed884574fb73c9cac8947faca4f 100644 (file)
 #include "config.h"
 #include "Opcode.h"
 
 #include "config.h"
 #include "Opcode.h"
 
+#if ENABLE(OPCODE_STATS)
+#include <stdio.h>
+#include <wtf/FixedArray.h>
+#endif
+
 using namespace std;
 
 namespace JSC {
 using namespace std;
 
 namespace JSC {
@@ -101,10 +106,10 @@ OpcodeStats::~OpcodeStats()
         for (int j = 0; j < numOpcodeIDs; ++j)
             totalInstructionPairs += opcodePairCounts[i][j];
 
         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;
     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;
     
     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) \
 
     #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, 2) \
+        macro(op_convert_this_strict, 2) \
         \
         macro(op_new_object, 2) \
         macro(op_new_array, 4) \
         \
         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) \
         \
         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_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) \
         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, 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_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) \
         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_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_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) \
         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_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_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_ret, 2) \
+        macro(op_call_put_result, 2) \
+        macro(op_ret_object_or_this, 3) \
         macro(op_method_check, 1) \
         \
         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) \
         \
         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_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) \
         \
         macro(op_jsr, 3) \
         macro(op_sret, 2) \
@@ -208,7 +217,7 @@ namespace JSC {
     #undef VERIFY_OPCODE_ID
 
 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
     #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;
     typedef void* Opcode;
 #else
     typedef const void* Opcode;
@@ -251,6 +260,17 @@ namespace JSC {
 
 #endif
 
 
 #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
 } // 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();
 
         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);
             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);
                     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);
                     }
                 }
                         lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count);
                     }
                 }
index 8e3ed9e5e0e762bf4e0d65a6aa92f34ec950f2b5..1d77b31d76e7af32b4a4f102257f66e0b95e1a61 100644 (file)
 #ifndef SamplingTool_h
 #define SamplingTool_h
 
 #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 <wtf/Assertions.h>
 #include <wtf/HashMap.h>
 #include <wtf/Threading.h>
 
-#include "Nodes.h"
-#include "Opcode.h"
-
 namespace JSC {
 
     class ScriptExecutable;
 
     class SamplingFlags {
 namespace JSC {
 
     class ScriptExecutable;
 
     class SamplingFlags {
-        friend class JIT;
     public:
         static void start();
         static void stop();
     public:
         static void start();
         static void stop();
@@ -80,6 +79,11 @@ namespace JSC {
             int m_flag;
         };
     
             int m_flag;
         };
     
+        static const void* addressOfFlags()
+        {
+            return &s_flags;
+        }
+
 #endif
     private:
         static uint32_t s_flags;
 #endif
     private:
         static uint32_t s_flags;
@@ -95,8 +99,8 @@ namespace JSC {
     struct Instruction;
 
     struct ScriptSampleRecord {
     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)
             , m_codeBlock(0)
             , m_sampleCount(0)
             , m_opcodeSampleCount(0)
@@ -113,7 +117,7 @@ namespace JSC {
         
         void sample(CodeBlock*, Instruction*);
 
         
         void sample(CodeBlock*, Instruction*);
 
-        RefPtr<ScriptExecutable> m_executable;
+        Strong<ScriptExecutable> m_executable;
         CodeBlock* m_codeBlock;
         int m_sampleCount;
         int m_opcodeSampleCount;
         CodeBlock* m_codeBlock;
         int m_sampleCount;
         int m_opcodeSampleCount;
@@ -142,7 +146,8 @@ namespace JSC {
         friend class HostCallRecord;
         
 #if ENABLE(OPCODE_SAMPLING)
         friend class HostCallRecord;
         
 #if ENABLE(OPCODE_SAMPLING)
-        class CallRecord : public Noncopyable {
+        class CallRecord {
+            WTF_MAKE_NONCOPYABLE(CallRecord);
         public:
             CallRecord(SamplingTool* samplingTool)
                 : m_samplingTool(samplingTool)
         public:
             CallRecord(SamplingTool* samplingTool)
                 : m_samplingTool(samplingTool)
@@ -172,7 +177,8 @@ namespace JSC {
             }
         };
 #else
             }
         };
 #else
-        class CallRecord : public Noncopyable {
+        class CallRecord {
+            WTF_MAKE_NONCOPYABLE(CallRecord);
         public:
             CallRecord(SamplingTool*)
             {
         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 {
     // 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)
         friend class DeletableSamplingCounter;
     public:
         void count(uint32_t count = 1)
@@ -288,6 +293,8 @@ namespace JSC {
 
         static void dump();
 
 
         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)
     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 "config.h"
 #include "StructureStubInfo.h"
 
+#include "JSObject.h"
+#include "ScopeChain.h"
+
 namespace JSC {
 
 #if ENABLE(JIT)
 void StructureStubInfo::deref()
 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:
 {
     switch (accessType) {
     case access_get_by_id_self:
-        u.getByIdSelf.baseObjectStructure->deref();
+        visitor.append(&u.getByIdSelf.baseObjectStructure);
         return;
     case access_get_by_id_proto:
         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:
         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;
         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;
         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:
         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:
         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:
         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:
     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();
         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;
 
         {
             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;
 
         {
             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;
 
         {
             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)
         }
 
         void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
@@ -106,29 +99,24 @@ namespace JSC {
 
         // PutById*
 
 
         // 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;
 
         {
             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;
     
         {
             accessType = access_put_by_id_replace;
     
-            u.putByIdReplace.baseObjectStructure = baseObjectStructure;
-            baseObjectStructure->ref();
+            u.putByIdReplace.baseObjectStructure.set(globalData, owner, baseObjectStructure);
         }
 
         void deref();
         }
 
         void deref();
+        void visitAggregate(SlotVisitor&);
 
         bool seenOnce()
         {
 
         bool seenOnce()
         {
@@ -145,15 +133,15 @@ namespace JSC {
 
         union {
             struct {
 
         union {
             struct {
-                Structure* baseObjectStructure;
+                WriteBarrierBase<Structure> baseObjectStructure;
             } getByIdSelf;
             struct {
             } getByIdSelf;
             struct {
-                Structure* baseObjectStructure;
-                Structure* prototypeStructure;
+                WriteBarrierBase<Structure> baseObjectStructure;
+                WriteBarrierBase<Structure> prototypeStructure;
             } getByIdProto;
             struct {
             } getByIdProto;
             struct {
-                Structure* baseObjectStructure;
-                StructureChain* chain;
+                WriteBarrierBase<Structure> baseObjectStructure;
+                WriteBarrierBase<StructureChain> chain;
             } getByIdChain;
             struct {
                 PolymorphicAccessStructureList* structureList;
             } getByIdChain;
             struct {
                 PolymorphicAccessStructureList* structureList;
@@ -164,12 +152,12 @@ namespace JSC {
                 int listSize;
             } getByIdProtoList;
             struct {
                 int listSize;
             } getByIdProtoList;
             struct {
-                Structure* previousStructure;
-                Structure* structure;
-                StructureChain* chain;
+                WriteBarrierBase<Structure> previousStructure;
+                WriteBarrierBase<Structure> structure;
+                WriteBarrierBase<StructureChain> chain;
             } putByIdTransition;
             struct {
             } putByIdTransition;
             struct {
-                Structure* baseObjectStructure;
+                WriteBarrierBase<Structure> baseObjectStructure;
             } putByIdReplace;
         } u;
 
             } putByIdReplace;
         } u;
 
index c4b3cab912b1b69897d4c886c45863048c50d999..c09a83766d6a9b406fb8aa6ee3491b9555e5aaaa 100644 (file)
@@ -31,9 +31,9 @@
 #include "BytecodeGenerator.h"
 
 #include "BatchedTransitionOptimizer.h"
 #include "BytecodeGenerator.h"
 
 #include "BatchedTransitionOptimizer.h"
-#include "PrototypeFunction.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
+#include "ScopeChain.h"
 #include "UString.h"
 
 using namespace std;
 #include "UString.h"
 
 using namespace std;
@@ -137,7 +137,7 @@ bool BytecodeGenerator::dumpsGeneratedCode()
 #endif
 }
 
 #endif
 }
 
-void BytecodeGenerator::generate()
+JSObject* BytecodeGenerator::generate()
 {
     m_codeBlock->setThisRegister(m_thisRegister.index());
 
 {
     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->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();
 #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();
 
     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);
 }
 
 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;
     }
 
 
     if (!result.second) {
         r0 = &registerFor(result.first->second.getIndex());
         return false;
     }
 
-    ++m_codeBlock->m_numVars;
-    r0 = newRegister();
+    r0 = addVar();
     return true;
 }
 
     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);
 {
     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();
 
     if (!result.second)
         index = result.first->second.getIndex();
@@ -202,10 +198,11 @@ void BytecodeGenerator::preserveLastVar()
         m_lastVar = &m_calleeRegisters.last();
 }
 
         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)
     , 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_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_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);
 {
     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"
 
     
     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();
     
     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);
     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();
 
     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();
 
         // 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];
         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();
 
         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];
     } 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) {
         }
         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)
                 continue;
             int attributes = DontDelete;
             if (varStack[i].second & DeclarationStacks::IsConstant)
@@ -286,94 +317,178 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
 
         preserveLastVar();
     }
 
         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_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_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_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);
 {
     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.
 
         // 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);
             emitOpcode(op_create_arguments);
+            instructions().append(argumentsRegister->index());
+        }
     }
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     }
 
     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();
     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();
 
     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_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;
     ++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)
     
     for (size_t i = 0; i < parameterCount; ++i)
-        addParameter(parameters[i]);
+        addParameter(parameters[i], ++nextParameterIndex);
 
     preserveLastVar();
 
     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)
     , 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_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_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);
 {
     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);
     for (size_t i = 0; i < numVariables; ++i)
         variables.append(*varStack[i].first);
     codeBlock->adoptVariables(variables);
-
+    codeBlock->m_numCapturedVars = codeBlock->m_numVars;
     preserveLastVar();
 }
 
     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.
 {
     // 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)) {
     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.
     }
 
     // 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;
     ++m_codeBlock->m_numParameters;
-    return result;
 }
 
 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
 }
 
 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
@@ -439,14 +563,14 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
     if (!shouldOptimizeLocals())
         return 0;
 
     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();
 
     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)
 }
 
 bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
@@ -457,7 +581,7 @@ bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
     if (!shouldOptimizeLocals())
         return false;
     
     if (!shouldOptimizeLocals())
         return false;
     
-    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+    SymbolTableEntry entry = symbolTable().get(ident.impl());
     if (entry.isNull())
         return false;
     
     if (entry.isNull())
         return false;
     
@@ -471,21 +595,29 @@ RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
 {
     ASSERT(willResolveToArguments(propertyNames().arguments));
 
 {
     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());
 }
 
     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;
 
 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;
 
     if (entry.isNull())
         return 0;
 
-    return &registerFor(entry.getIndex());
+    return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
 }
 
 bool BytecodeGenerator::isLocal(const Identifier& ident)
 }
 
 bool BytecodeGenerator::isLocal(const Identifier& ident)
@@ -493,12 +625,12 @@ bool BytecodeGenerator::isLocal(const Identifier& ident)
     if (ident == propertyNames().thisIdentifier)
         return true;
     
     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)
 {
 }
 
 bool BytecodeGenerator::isLocalConstant(const Identifier& ident)
 {
-    return symbolTable().get(ident.ustring().rep()).isReadOnly();
+    return symbolTable().get(ident.impl()).isReadOnly();
 }
 
 RegisterID* BytecodeGenerator::newRegister()
 }
 
 RegisterID* BytecodeGenerator::newRegister()
@@ -573,6 +705,11 @@ PassRefPtr<Label> BytecodeGenerator::emitLabel(Label* l0)
 
 void BytecodeGenerator::emitOpcode(OpcodeID opcodeID)
 {
 
 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;
 }
     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);
 {
     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);
 }
 
 void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
 {
     ASSERT(instructions().size() >= 3);
     instructions().shrink(instructions().size() - 3);
+    m_lastOpcodeID = op_end;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
@@ -786,7 +925,7 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond,
 
     emitOpcode(op_jneq_ptr);
     instructions().append(cond->index());
 
     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;
 }
     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());
 
     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)
 {
     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));
     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;
     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;
 
     } 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())
         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);
             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)
 {
 
 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)
     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)
 {
     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));
     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();
 
         if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
             ScopeChainIterator iter = m_scopeChain->begin();
-            globalObject = *iter;
+            globalObject = iter->get();
             ASSERT((++iter) == m_scopeChain->end());
         }
         return false;
             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) {
     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);
         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()) {
 
         // Found the property
         if (!entry.isNull()) {
@@ -1025,7 +1165,7 @@ bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& inde
                     globalObject = currentVariableObject;
                 return false;
             }
                     globalObject = currentVariableObject;
                 return false;
             }
-            stackDepth = depth;
+            stackDepth = depth + m_codeBlock->needsFullScopeChain();
             index = entry.getIndex();
             if (++iter == end)
                 globalObject = currentVariableObject;
             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.
         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();
     index = missingSymbolMarker();
-    JSObject* scope = *iter;
+    JSObject* scope = iter->get();
     if (++iter == end)
         globalObject = scope;
     return true;
 }
 
     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);
 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;
 }
 
     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;
 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;
     }
         instructions().append(addConstant(property));
         return dst;
     }
-
+    if (shouldAvoidResolveGlobal()) {
+        globalObject = 0;
+        requiresDynamicChecks = true;
+    }
+        
     if (globalObject) {
         bool forceGlobalResolve = false;
     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.
 
         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());
 
 #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());
         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);
         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());
     if (globalObject) {
         emitOpcode(op_get_global_var);
         instructions().append(dst->index());
-        instructions().append(asCell(globalObject));
         instructions().append(index);
         return dst;
     }
         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);
 {
     if (globalObject) {
         emitOpcode(op_put_global_var);
-        instructions().append(asCell(globalObject));
         instructions().append(index);
         instructions().append(value->index());
         return value;
         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));
         emitOpcode(op_resolve_base);
         instructions().append(dst->index());
         instructions().append(addConstant(property));
+        instructions().append(false);
         return dst;
     }
 
         return dst;
     }
 
@@ -1174,6 +1323,32 @@ RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier
     return emitLoad(dst, JSValue(globalObject));
 }
 
     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;
 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;
     }
 
     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));
 
     // 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;
     }
         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());
 #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());
     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);
     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));
 {
 #if ENABLE(JIT)
     m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
-#else
+#endif
+    
+#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 
@@ -1247,11 +1422,22 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
     return dst;
 }
 
     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));
 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
 
     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));
 {
 #if ENABLE(JIT)
     m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
-#else
+#endif
+#if ENABLE(INTERPRETER)
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
     
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
     
@@ -1314,6 +1501,16 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
     return dst;
 }
 
     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--) {
 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;
 }
 
     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())
     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)
 {
 
 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);
     emitOpcode(op_new_func);
     instructions().append(dst->index());
     instructions().append(index);
+    instructions().append(doNullCheck);
     return dst;
 }
 
     return dst;
 }
 
@@ -1406,64 +1668,68 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
     return dst;
 }
 
     return dst;
 }
 
-
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
     FunctionBodyNode* function = n->body();
     unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
 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;
 }
 
     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()
 {
 }
 
 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(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.
 
     // 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;
 
     // 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);
 
     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);
     }
 
     emitExpressionInfo(divot, startOffset, endOffset);
@@ -1487,30 +1749,29 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
 
     // Emit call.
     emitOpcode(opcodeID);
 
     // Emit call.
     emitOpcode(opcodeID);
-    instructions().append(dst->index()); // dst
     instructions().append(func->index()); // func
     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);
 
     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;
 }
 
     }
 
     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());
 {
     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;
 }
 
     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 (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);
     }
     
     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
     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());
     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);
 {
     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);
         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);
 }
 
     return emitUnaryNoDstOp(op_ret, src);
 }
 
@@ -1561,43 +1834,25 @@ RegisterID* BytecodeGenerator::emitUnaryNoDstOp(OpcodeID opcodeID, RegisterID* s
     return src;
 }
 
     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());
 
 {
     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.
 
     // 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);
     }
 
     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)
     // 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);
 #endif
 
     emitOpcode(op_construct);
-    instructions().append(dst->index()); // dst
     instructions().append(func->index()); // func
     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);
 
     if (m_shouldEmitProfileHooks) {
         emitOpcode(op_profile_did_call);
-        instructions().append(func->index());
-        
-        if (dst == originalFunc)
-            func->deref();
+        instructions().append(callArguments.profileHookRegister()->index());
     }
 
     return dst;
     }
 
     return dst;
@@ -1656,7 +1905,6 @@ RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
-    createArgumentsIfNecessary();
 
     return emitUnaryNoDstOp(op_push_scope, scope);
 }
 
     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)
 {
 
 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
 #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;
 }
 
     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)
 }
 
 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++;
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
-    
-    createArgumentsIfNecessary();
 
     emitOpcode(op_push_new_scope);
     instructions().append(dst->index());
 
     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());
 {
     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];
     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());
         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);
         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.
     // 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
 }
 
 } // namespace JSC
index 3667198dad5466e20548747449b5fa7925cc6c8c..bc297ee6d7fda2b78b8a57041e9b50c61703edf1 100644 (file)
@@ -40,7 +40,6 @@
 #include "SymbolTable.h"
 #include "Debugger.h"
 #include "Nodes.h"
 #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>
 #include <wtf/PassRefPtr.h>
 #include <wtf/SegmentedVector.h>
 #include <wtf/Vector.h>
 namespace JSC {
 
     class Identifier;
 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;
 
     struct FinallyContext {
         Label* finallyAddr;
@@ -68,7 +83,8 @@ namespace JSC {
         RefPtr<RegisterID> propertyRegister;
     };
 
         RefPtr<RegisterID> propertyRegister;
     };
 
-    class BytecodeGenerator : public FastAllocBase {
+    class BytecodeGenerator {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
     public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
@@ -76,20 +92,27 @@ namespace JSC {
         static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
         static bool dumpsGeneratedCode();
 
         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; }
 
 
         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 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();
 
         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.
         // 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"
         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();
         }
 
             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())
         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());
         {
             // 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)
         }
 
         RegisterID* emitNode(Node* n)
@@ -194,19 +219,18 @@ namespace JSC {
 
         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
         {
 
         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();
                 emitThrowExpressionTooDeepException();
-            ++m_emitNodeDepth;
-            n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
-            --m_emitNodeDepth;
         }
 
         void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
         }
 
         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
             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);
         }
 
             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;
         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* 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* 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* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
-        RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp);
+        RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
 
         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
 
 
         RegisterID* emitMove(RegisterID* dst, RegisterID* src);
 
@@ -286,6 +301,7 @@ namespace JSC {
         RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
         RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
 
         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()); }
         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* 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* 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* 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* 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* 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* 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);
 
         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);
         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);
         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; }
 
 
         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);
 
     private:
         void emitOpcode(OpcodeID);
@@ -397,23 +420,31 @@ namespace JSC {
             static const bool needsRef = false;
         };
 
             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<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();
 
         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;
         }
         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*&);
         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)
 
         // 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*&);
 
         // 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();
         
         void preserveLastVar();
+        bool shouldAvoidResolveGlobal();
 
         RegisterID& registerFor(int index)
         {
             if (index >= 0)
                 return m_calleeRegisters[index];
 
 
         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];
             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*);
 
         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; }
 
         Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
         SymbolTable& symbolTable() { return *m_symbolTable; }
 
@@ -468,11 +511,14 @@ namespace JSC {
         RegisterID* emitThrowExpressionTooDeepException();
 
         void createArgumentsIfNecessary();
         RegisterID* emitThrowExpressionTooDeepException();
 
         void createArgumentsIfNecessary();
+        void createActivationIfNecessary();
+        RegisterID* createLazyRegisterIfNecessary(RegisterID*);
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
 
         bool m_shouldEmitDebugHooks;
         bool m_shouldEmitProfileHooks;
+        bool m_shouldEmitRichSourceInfo;
 
 
-        const ScopeChain* m_scopeChain;
+        Strong<ScopeChainNode> m_scopeChain;
         SymbolTable* m_symbolTable;
 
         ScopeNode* m_scopeNode;
         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.
 
         // 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_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;
         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;
         Vector<ForInContext> m_forInContextStack;
 
         int m_nextGlobalIndex;
-        int m_nextParameterIndex;
         int m_firstConstantIndex;
         int m_nextConstantOffset;
         unsigned m_globalConstantIndex;
 
         int m_globalVarStorageOffset;
 
         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;
         // Constant pool
         IdentifierMap m_identifierMap;
         JSValueMap m_jsValueMap;
@@ -518,34 +569,14 @@ namespace JSC {
         JSGlobalData* m_globalData;
 
         OpcodeID m_lastOpcodeID;
         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 "RegExpCache.h"
 #include "RegExpObject.h"
 #include "SamplingTool.h"
+#include "UStringConcatenate.h"
 #include <wtf/Assertions.h>
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/Threading.h>
 #include <wtf/Assertions.h>
 #include <wtf/RefCountedLeakCounter.h>
 #include <wtf/Threading.h>
@@ -75,34 +76,11 @@ namespace JSC {
 
 // ------------------------------ ThrowableExpressionData --------------------------------
 
 
 // ------------------------------ 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());
     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 -------------------------------------
 }
 
 // ------------------------------ NullNode -------------------------------------
@@ -145,12 +123,9 @@ RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
 
 RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
 
 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;
     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 -------------------------------------
 }
 
 // ------------------------------ ThisNode -------------------------------------
@@ -177,7 +152,7 @@ RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
         return generator.moveToDestinationIfNeeded(dst, local);
     }
     
         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);
 }
 
     return generator.emitResolve(generator.finalDestination(dst), m_ident);
 }
 
@@ -196,9 +171,9 @@ RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds
     }
 
     if (!firstPutElement && !m_elision)
     }
 
     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());
 
     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) {
     }
 
     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);
     }
 
         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)
 {
 
 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());
     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)
 {
 
 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);
     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);
 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 ----------------------------------
 }
 
 // ------------------------------ EvalFunctionCallNode ----------------------------------
@@ -325,10 +333,10 @@ RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> func = generator.tempDestination(dst);
 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.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 ----------------------------------
 }
 
 // ------------------------------ 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);
 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 ----------------------------------
 }
 
 // ------------------------------ 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)) {
 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;
     }
 
     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);
     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> func = generator.newTemporary();
-    RefPtr<RegisterID> thisRegister = generator.newTemporary();
+    CallArguments callArguments(generator, m_args);
     int identifierStart = divot() - startOffset();
     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 ----------------------------------
 }
 
 // ------------------------------ 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);
     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 ----------------------------------
 }
 
 // ------------------------------ FunctionCallDotNode ----------------------------------
@@ -384,12 +396,12 @@ RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator,
 RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
     RefPtr<RegisterID> function = generator.tempDestination(dst);
 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.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)
 }
 
 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> 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());
     {
     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) {
         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;
             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());
     {
     }
     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());
     }
     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
 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> 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) {
     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) {
             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());
         } 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);
 
             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());
     {
         }
         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());
     }
     generator.emitLabel(end.get());
-    return finalDestination.get();
+    return finalDestinationOrIgnored.get();
 }
 
 // ------------------------------ PostfixResolveNode ----------------------------------
 }
 
 // ------------------------------ PostfixResolveNode ----------------------------------
@@ -605,7 +635,7 @@ RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterI
 
 RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
 {
 
 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.");
 }
         ? "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*)
 {
 
 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.");
 }
         ? "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());
 
     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
     // 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());
     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());
     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);
     }
 
     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);
     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;
     }
 
         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);
     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*)
 {
 
 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 -----------------------------------
 }
 
 // ------------------------------ AssignBracketNode -----------------------------------
@@ -1323,6 +1353,11 @@ inline StatementNode* BlockNode::lastStatement() const
     return m_statements ? m_statements->lastStatement() : 0;
 }
 
     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)
 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)
 {
 
 RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
-    IncreaseEmitNodeDepth stackGuard(generator);
-
     RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop);
 
     if (!m_lexpr->isLocation())
     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());
 
 
     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;
         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);
 
             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);
     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;
 
     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);
     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;
 
     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());
 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;
 
     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();
                 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)
                 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());
 
 {
     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);
 
     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.
 
     // 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();
     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());
 {
     generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine());
     emitStatementsBytecode(generator, generator.ignoredResult());
+
     StatementNode* singleStatement = this->singleStatement();
     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())
     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;
 }
 
     return 0;
 }
 
index 3532ad802cb220ae76a6230152080b999ceb8487..78d49d29086366fd7f9b7e9ae36cac736892cbce 100644 (file)
 #define RegisterID_h
 
 #include <wtf/Assertions.h>
 #define RegisterID_h
 
 #include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
 
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
 
-    class RegisterID : public Noncopyable {
+    class RegisterID {
+        WTF_MAKE_NONCOPYABLE(RegisterID);
     public:
         RegisterID()
             : m_refCount(0)
     public:
         RegisterID()
             : m_refCount(0)
index 9810885d73490b8f503221e29af9c776c059e5d7..394bba56a452ba761d05dc50f66ae35c056e5321 100644 (file)
--- a/config.h
+++ b/config.h
  */
 
 #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
  */
 
 #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
+#ifdef BUILDING_WITH_CMAKE
+#include "cmakeconfig.h"
+#else
 #include "autotoolsconfig.h"
 #endif
 #include "autotoolsconfig.h"
 #endif
+#endif
 
 #include <wtf/Platform.h>
 
 
 #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)
 #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 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. 
 #if OS(WINDOWS)
 
 // If we don't define these, they get defined in windef.h. 
 
 #endif
 
 
 #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
 #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 "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++;
     }
         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;
 
 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 $rtype_template = quotemeta("#rtype#");
-my $offset_template = quotemeta("#offset#");
 my $op_template = quotemeta("#op#");
 
 my $prefix;
 my $op_template = quotemeta("#op#");
 
 my $prefix;
-my $offset = 32;
 my $file;
 
 my $getOptionsResult = GetOptions(
 my $file;
 
 my $getOptionsResult = GetOptions(
-    'prefix=s' => \$prefix,
-    'offset=i' => \$offset
+    'prefix=s' => \$prefix
 );
 
 $file = $ARGV[0];
 );
 
 $file = $ARGV[0];
@@ -42,6 +39,7 @@ $file = $ARGV[0];
 die "$usage\n" unless ($prefix and $file);
 
 my $stub_template = "";
 die "$usage\n" unless ($prefix and $file);
 
 my $stub_template = "";
+my $output_end = "";
 my $stub = "";
 
 my $rtype = "";
 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> ) {
 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\((.*)\)/ ) {
         $stub_template .= $1 . "\n";
     }
+    if ( /^$prefix\_END\((.*)\)/ ) {
+        $output_end .= $1 . "\n";
+    }
     if ( /^DEFINE_STUB_FUNCTION\((.*), (.*)\)/ ) {
         $stub = $stub_template;
         $rtype = quotemeta($1);
         $op = quotemeta($2);
     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;
         $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);
 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. 
 
 # (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]},
 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 = "";
     "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 = [];
 
 for name, classes in types.items():
     ranges = [];
@@ -54,7 +57,7 @@ for name, classes in types.items():
             ranges.append((min,max))
     ranges.sort();
     
             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:
         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")
     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:
         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
 
     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 "config.h"
 #include "Debugger.h"
 
-#include "CollectorHeapIterator.h"
 #include "Error.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "Error.h"
 #include "Interpreter.h"
 #include "JSFunction.h"
 #include "Parser.h"
 #include "Protect.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()
 namespace JSC {
 
 Debugger::~Debugger()
@@ -61,52 +117,29 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
     if (globalData->dynamicGlobalObject)
         return;
 
     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();
 }
 
 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
 }
 
 } // namespace JSC
index 3b9bec4ac924f499155cc87836de142306c9cf0f..ec5cf37374e09b490ff96c10ff5ed4bdcedced79 100644 (file)
@@ -31,7 +31,7 @@ namespace JSC {
     class JSGlobalData;
     class JSGlobalObject;
     class JSValue;
     class JSGlobalData;
     class JSGlobalObject;
     class JSValue;
-    class SourceCode;
+    class SourceProvider;
     class UString;
 
     class Debugger {
     class UString;
 
     class Debugger {
@@ -41,7 +41,7 @@ namespace JSC {
         void attach(JSGlobalObject*);
         virtual void detach(JSGlobalObject*);
 
         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;
         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 {
 
 
 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());
 {
     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)
 
     if (m_activation)
-        markStack.append(m_activation);
+        visitor.append(&m_activation);
 }
 
 UString DebuggerActivation::className() const
 }
 
 UString DebuggerActivation::className() const
index 392701741ba764b3f44392da99c7006dcc5c4c5d..574986a0fd662f681f3a06eb4be20e7dc0aff3a9 100644 (file)
@@ -32,11 +32,11 @@ namespace JSC {
 
     class JSActivation;
 
 
     class JSActivation;
 
-    class DebuggerActivation : public JSObject {
+    class DebuggerActivation : public JSNonFinalObject {
     public:
     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&);
         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);
 
         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:
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
 
     private:
 
     private:
-        JSActivation* m_activation;
+        WriteBarrier<JSActivation> m_activation;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index a734b1d0e413db8c151ccefc745e920af9c6e630..08fba4a6b4cb8a00991d55749907f5e2f8076155 100644 (file)
@@ -44,10 +44,10 @@ const UString* DebuggerCallFrame::functionName() const
     if (!m_callFrame->callee())
         return 0;
 
     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 0;
-    return &function->name(m_callFrame);
+    return &asFunction(function)->name(m_callFrame);
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
 }
     
 UString DebuggerCallFrame::calculatedFunctionName() const
@@ -55,13 +55,11 @@ UString DebuggerCallFrame::calculatedFunctionName() const
     if (!m_callFrame->codeBlock())
         return UString();
 
     if (!m_callFrame->codeBlock())
         return UString();
 
-    if (!m_callFrame->callee())
+    JSObject* function = m_callFrame->callee();
+    if (!function || !function->inherits(&JSFunction::s_info))
         return UString();
 
         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
 }
 
 DebuggerCallFrame::Type DebuggerCallFrame::type() const
@@ -74,23 +72,36 @@ DebuggerCallFrame::Type DebuggerCallFrame::type() const
 
 JSObject* DebuggerCallFrame::thisObject() 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 0;
 
-    return asObject(m_callFrame->thisValue());
+    return asObject(thisValue);
 }
 
 JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) const
 {
     if (!m_callFrame->codeBlock())
         return JSValue();
 }
 
 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
 }
 
 } // namespace JSC
index 9d377ef97a0a2db3aaac32285ea6cf011d7e16b8..f6b415cecbd09462d3cd3a49c992dcb766b7ab30 100644 (file)
@@ -49,7 +49,7 @@ namespace JSC {
         }
 
         JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); }
         }
 
         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;
         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 = ();
 
 
 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>) {
 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 {
 #include "Interpreter.h"
 
 namespace JSC {
-    class CachedCall : public Noncopyable {
+    class CachedCall {
+        WTF_MAKE_NONCOPYABLE(CachedCall); WTF_MAKE_FAST_ALLOCATED;
     public:
     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_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());
         {
             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);
         }
         
         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); }
         }
         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;
     private:
         bool m_valid;
         Interpreter* m_interpreter;
-        JSValue* m_exception;
         DynamicGlobalObjectScope m_globalObjectScope;
         CallFrameClosure m_closure;
     };
         DynamicGlobalObjectScope m_globalObjectScope;
         CallFrameClosure m_closure;
     };
index 972487565f5aacacb25898c190e49a88fc32cedc..5819875150b0f8327a9f683e4927693eaba9392d 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-JSValue CallFrame::thisValue()
-{
-    return this[codeBlock()->thisRegister()].jsValue();
-}
-
 #ifndef NDEBUG
 void CallFrame::dumpCaller()
 {
 #ifndef NDEBUG
 void CallFrame::dumpCaller()
 {
@@ -45,8 +40,14 @@ void CallFrame::dumpCaller()
     JSValue function;
     
     interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function);
     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
 
 }
 #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) 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
  *
  *  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"
 #define CallFrame_h
 
 #include "JSGlobalData.h"
+#include "MacroAssemblerCodeRef.h"
 #include "RegisterFile.h"
 #include "RegisterFile.h"
-#include "ScopeChain.h"
 
 namespace JSC  {
 
     class Arguments;
     class JSActivation;
     class Interpreter;
 
 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:
 
     // 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();
         }
         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.
 
         // 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.
 
         // 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.
 
 
         // 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; }
         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; }
         bool hadException() const { return globalData().exception; }
 
         const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
@@ -92,14 +75,24 @@ namespace JSC  {
 #ifndef NDEBUG
         void dumpCaller();
 #endif
 #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* 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* 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* 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* 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; }
 
         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(); }
         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
 #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
 
         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,
         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); // 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);
 
             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 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); }
 
         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); }
 
 
         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 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;
         static const intptr_t HostCallFrameFlag = 1;
-
+#ifndef NDEBUG
+        RegisterFile* registerFile();
+#endif
         ExecState();
         ~ExecState();
     };
         ExecState();
         ~ExecState();
     };
index a301060d26b56d3aefaa3cad8e378a0c085013c0..b4b7efd45baa8019ff86ac2f62422716e60aa636 100644 (file)
@@ -46,10 +46,10 @@ struct CallFrameClosure {
         else
             newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams - providedParams] = value;
     }
         else
             newCallFrame[arg - RegisterFile::CallFrameHeaderSize - expectedParams - providedParams] = value;
     }
+
     void resetCallFrame()
     {
         newCallFrame->setScopeChain(scopeChain);
     void resetCallFrame()
     {
         newCallFrame->setScopeChain(scopeChain);
-        newCallFrame->setCalleeArguments(JSValue());
         for (int i = providedParams; i < expectedParams; ++i)
             newCallFrame[i - RegisterFile::CallFrameHeaderSize - expectedParams] = jsUndefined();
     }
         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 "CallFrame.h"
 #include "CallFrameClosure.h"
 #include "CodeBlock.h"
-#include "Collector.h"
+#include "Heap.h"
 #include "Debugger.h"
 #include "DebuggerCallFrame.h"
 #include "Debugger.h"
 #include "DebuggerCallFrame.h"
+#include "ErrorInstance.h"
 #include "EvalCodeCache.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
 #include "EvalCodeCache.h"
 #include "ExceptionHelpers.h"
 #include "GetterSetter.h"
-#include "GlobalEvalFunction.h"
 #include "JSActivation.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
 #include "JSActivation.h"
 #include "JSArray.h"
 #include "JSByteArray.h"
@@ -59,6 +59,8 @@
 #include "RegExpPrototype.h"
 #include "Register.h"
 #include "SamplingTool.h"
 #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>
 #include <limits.h>
 #include <stdio.h>
 #include <wtf/Threading.h>
 using namespace std;
 
 namespace JSC {
 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.
 
 // 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;
 {
     if (!codeBlock->needsFullScopeChain())
         return 0;
-    return sc.localDepth();
+    return sc->localDepth();
 }
 
 #if ENABLE(INTERPRETER) 
 }
 
 #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 {
     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;
         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);
             return true;
         }
     } while (++iter != end);
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
     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 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);
 
     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 {
     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;
         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);
             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;
     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());
     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()) {
 
     if (structure == globalObject->structure()) {
-        callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset));
+        callFrame->uncheckedR(dst) = JSValue(globalObject->getDirectOffset(offset));
         return true;
     }
 
         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) {
     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;
             return true;
         }
 
         exceptionValue = callFrame->globalData().exception;
         if (exceptionValue)
             return false;
-        callFrame->r(dst) = JSValue(result);
+        callFrame->uncheckedR(dst) = JSValue(result);
         return true;
     }
 
         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;
     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();
     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);
     
     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--) {
     while (skip--) {
-        JSObject* o = *iter;
+        JSObject* o = iter->get();
         if (o->hasCustomProperties()) {
             Identifier& ident = codeBlock->identifier(property);
             do {
         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;
                     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;
                     return true;
                 }
                 if (iter == end)
                     break;
-                o = *iter;
+                o = iter->get();
                 ++iter;
             } while (true);
                 ++iter;
             } while (true);
-            exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+            exceptionValue = createUndefinedVariableError(callFrame, ident);
             return false;
         }
         ++iter;
     }
     
     if (structure == globalObject->structure()) {
             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;
     }
 
         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 (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;
             return true;
         }
         
         exceptionValue = callFrame->globalData().exception;
         if (exceptionValue)
             return false;
-        callFrame->r(dst) = JSValue(result);
+        ASSERT(result);
+        callFrame->uncheckedR(dst) = JSValue(result);
         return true;
     }
     
         return true;
     }
     
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
     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;
 {
     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)
 }
 
 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 {
     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;
         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);
 
             return true;
         }
         ++iter;
     } while (iter != end);
 
-    exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionValue = createUndefinedVariableError(callFrame, ident);
     return false;
 }
 
     return false;
 }
 
@@ -355,24 +361,24 @@ ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newC
 }
 
 #if ENABLE(INTERPRETER)
 }
 
 #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;
 {
     if (value.isObject())
         return false;
-    exceptionData = createInvalidParamError(callFrame, "in" , value, vPC - codeBlock->instructions().begin(), codeBlock);
+    exceptionData = createInvalidParamError(callFrame, "in" , value);
     return true;
 }
 
     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;
 {
     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
 
     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();
 {
     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();
     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();
 
     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_sampleEntryDepth(0)
     , m_reentryDepth(0)
+    , m_registerFile(globalData)
 {
 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 {
 #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));
 
     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();
     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;
     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("[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("[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;
     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());
     }
 
             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()) {
     // 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();
             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 (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())
     if (callerFrame->globalData().canUseJIT())
-#endif
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, codeBlock, callFrame->returnPC());
-#if ENABLE(INTERPRETER)
+        bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
     else
     else
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, codeBlock, callFrame->returnVPC());
-#endif
+        bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
+#elif ENABLE(JIT)
+    bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnPC());
 #else
 #else
-    bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
+    bytecodeOffset = codeBlock->bytecodeOffset(callFrame->returnVPC()) - 1;
 #endif
 #endif
+
     callFrame = callerFrame;
     return true;
 }
 
     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();
     CodeBlock* codeBlock = callFrame->codeBlock();
+    bool isInterrupt = false;
+
+    // Set up the exception object
     if (exceptionValue.isObject()) {
         JSObject* exception = asObject(exceptionValue);
     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);
     }
 
     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.
     }
 
     // Calculate an exception handler vPC, unwinding call frames as necessary.
-
     HandlerInfo* handler = 0;
     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;
             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();
     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();
     ASSERT(scopeDelta >= 0);
     while (scopeDelta--)
         scopeChain = scopeChain->pop();
@@ -679,42 +721,139 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
     return handler;
 }
 
     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(!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;
 
     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);
 
     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** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, program->sourceURL(), program->lineNo());
+        (*profiler)->willExecute(callFrame, program->sourceURL(), program->lineNo());
 
     JSValue result;
     {
 
     JSValue result;
     {
@@ -722,17 +861,11 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
 
         m_reentryDepth++;  
 #if ENABLE(JIT)
 
         m_reentryDepth++;  
 #if ENABLE(JIT)
-#if ENABLE(INTERPRETER)
         if (callFrame->globalData().canUseJIT())
         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
         else
 #endif
-#endif
-#if ENABLE(INTERPRETER)
-            result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
-#endif
+            result = privateExecute(Normal, &m_registerFile, newCallFrame);
 
         m_reentryDepth--;
     }
 
         m_reentryDepth--;
     }
@@ -745,46 +878,84 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
 
     m_registerFile.shrink(oldEnd);
 
 
     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();
 
     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;
 
     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)
     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);
         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)
 
     Profiler** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
@@ -792,38 +963,124 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame*
 
     JSValue result;
     {
 
     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(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
 #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)
     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);
 
     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) {
 {
     ASSERT(!scopeChain->globalData->exception);
     
     if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
         if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
-            *exception = createStackOverflowError(callFrame);
+            throwStackOverflowError(callFrame);
             return CallFrameClosure();
         }
     }
             return CallFrameClosure();
         }
     }
@@ -832,36 +1089,40 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
     int argc = 1 + argCount; // implicit "this" parameter
     
     if (!m_registerFile.grow(oldEnd + argc)) {
     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);
         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)
     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)) {
     newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     if (UNLIKELY(!newCallFrame)) {
-        *exception = createStackOverflowError(callFrame);
+        throwStackOverflowError(callFrame);
         m_registerFile.shrink(oldEnd);
         return CallFrameClosure();
     }
         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;
 }
 
     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)
     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
 #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)
 #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);
 #endif
         m_reentryDepth--;
     }
     
     if (*profiler)
         (*profiler)->didExecute(closure.oldCallFrame, closure.function);
-    return result;
+    return checkedReturn(result);
 }
 
 void Interpreter::endRepeatCall(CallFrameClosure& closure)
 }
 
 void Interpreter::endRepeatCall(CallFrameClosure& closure)
@@ -897,40 +1158,51 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure)
     m_registerFile.shrink(closure.oldEnd);
 }
 
     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(!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()) {
         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();
             break;
         }
     }
 
     unsigned numVariables = codeBlock->numVariables();
     int numFunctions = codeBlock->numberOfFunctionDecls();
+    bool pushedScope = false;
     if (numVariables || numFunctions) {
     if (numVariables || numFunctions) {
+        if (codeBlock->isStrictMode()) {
+            variableObject = new (callFrame) StrictEvalActivation(callFrame);
+            scopeChain = scopeChain->push(variableObject);
+            pushedScope = true;
+        }
         // Scope for BatchedTransitionOptimizer
         // Scope for BatchedTransitionOptimizer
-        BatchedTransitionOptimizer optimizer(variableObject);
+        BatchedTransitionOptimizer optimizer(callFrame->globalData(), variableObject);
 
         for (unsigned i = 0; i < numVariables; ++i) {
             const Identifier& ident = codeBlock->variable(i);
 
         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)) {
     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);
 
     }
 
     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** profiler = Profiler::enabledProfilerReference();
     if (*profiler)
-        (*profiler)->willExecute(newCallFrame, eval->sourceURL(), eval->lineNo());
+        (*profiler)->willExecute(callFrame, eval->sourceURL(), eval->lineNo());
 
     JSValue result;
     {
 
     JSValue result;
     {
@@ -977,13 +1247,13 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
 #if ENABLE(INTERPRETER)
         if (callFrame->globalData().canUseJIT())
 #endif
 #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)
 #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--;
     }
 #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);
         (*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)
 }
 
 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);
     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);
 }
 
     return callFrame->scopeChain()->push(scope);
 }
@@ -1051,20 +1323,20 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock*
         return;
     }
     
         return;
     }
     
-    JSCell* baseCell = asCell(baseValue);
+    JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
 
     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.
         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) {
     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;
         }
 
             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);
 
         // 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[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();
         vPC[7] = slot.cachedOffset();
-        codeBlock->refStructures(vPC);
         return;
     }
 
     vPC[0] = getOpcode(op_put_by_id_replace);
     vPC[5] = slot.cachedOffset();
         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;
 }
     vPC[0] = getOpcode(op_put_by_id);
     vPC[4] = 0;
 }
@@ -1141,19 +1416,19 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         return;
     }
 
         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
         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) {
     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;
         }
 
             return;
         }
 
@@ -1179,8 +1454,6 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
             vPC[5] = slot.cachedOffset();
             break;
         }
             vPC[5] = slot.cachedOffset();
             break;
         }
-
-        codeBlock->refStructures(vPC);
         return;
     }
 
         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()) {
         // 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());
         }
 
         ASSERT(!baseObject->structure()->isUncacheableDictionary());
@@ -1218,9 +1491,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
             vPC[6] = offset;
             break;
         }
             vPC[6] = offset;
             break;
         }
-        vPC[5] = baseObject->structure();
-
-        codeBlock->refStructures(vPC);
+        vPC[5].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), baseObject->structure());
         return;
     }
 
         return;
     }
 
@@ -1246,22 +1517,20 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
         vPC[7] = offset;
         break;
     }
         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;
     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)
 
     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.
 {
     // 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) };
         #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)
                     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);
 #if !ENABLE(INTERPRETER)
     UNUSED_PARAM(registerFile);
     UNUSED_PARAM(callFrame);
-    UNUSED_PARAM(exception);
     return JSValue();
 #else
 
     return JSValue();
 #else
 
@@ -1295,9 +1563,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
     JSValue exceptionValue;
     HandlerInfo* handler = 0;
 
     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();
     Profiler** enabledProfilerReference = Profiler::enabledProfilerReference();
     unsigned tickCount = globalData->timeoutChecker.ticksUntilNextCheck();
+    JSValue functionReturnValue;
 
 #define CHECK_FOR_EXCEPTION() \
     do { \
 
 #define CHECK_FOR_EXCEPTION() \
     do { \
@@ -1327,7 +1597,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
 #endif
 
 #if ENABLE(COMPUTED_GOTO_INTERPRETER)
 #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
 #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
 #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
 #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;
            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();
 
         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);
         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();
     }
 
         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)
 
     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;
            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();
 
         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;
         */
         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();
 
         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())
         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();
         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);
         }
 
         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()) {
         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();
         }
         
             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();
     }
         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())
         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();
         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);
         }
 
         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()) {
         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();
         }
         
             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();
     }
         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();
         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();
 
         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();
         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();
 
         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();
         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();
 
         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();
         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();
 
         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)
         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 {
         else {
-            JSValue result = jsNumber(callFrame, v.toNumber(callFrame) + 1);
+            JSValue result = jsNumber(v.toNumber(callFrame) + 1);
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(srcDst) = result;
+            callFrame->uncheckedR(srcDst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_pre_inc);
         }
 
         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)
         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 {
         else {
-            JSValue result = jsNumber(callFrame, v.toNumber(callFrame) - 1);
+            JSValue result = jsNumber(v.toNumber(callFrame) - 1);
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(srcDst) = result;
+            callFrame->uncheckedR(srcDst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_pre_dec);
         }
 
         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) {
         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();
         } 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);
         }
 
         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) {
         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();
         } 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);
         }
 
         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()))
         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();
         else {
             JSValue result = srcVal.toJSNumber(callFrame);
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_to_jsnumber);
         }
 
         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
         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 {
         else {
-            JSValue result = jsNumber(callFrame, -src.toNumber(callFrame));
+            JSValue result = jsNumber(-src.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_negate);
         }
 
         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
         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();
         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();
         }
         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
         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 {
         else {
-            JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) * src2.toNumber(callFrame));
+            JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_mul);
         }
 
         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 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();
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
 
         vPC += OPCODE_LENGTH(op_div);
         NEXT_INSTRUCTION();
 
         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 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);
             ASSERT(result);
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
             vPC += OPCODE_LENGTH(op_mod);
             NEXT_INSTRUCTION();
         }
             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);
         // 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();
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_mod);
         NEXT_INSTRUCTION();
     }
         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
         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 {
         else {
-            JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame));
+            JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
         vPC += OPCODE_LENGTH(op_sub);
         NEXT_INSTRUCTION();
         }
         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())
         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 {
         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();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_lshift);
         }
 
         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())
         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 {
         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();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_rshift);
         }
 
         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())
         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 {
         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();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_urshift);
         }
 
         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())
         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 {
         else {
-            JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) & src2.toInt32(callFrame));
+            JSValue result = jsNumber(src1.toInt32(callFrame) & src2.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_bitand);
         }
 
         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())
         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 {
         else {
-            JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
+            JSValue result = jsNumber(src1.toInt32(callFrame) ^ src2.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_bitxor);
         }
 
         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())
         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 {
         else {
-            JSValue result = jsNumber(callFrame, src1.toInt32(callFrame) | src2.toInt32(callFrame));
+            JSValue result = jsNumber(src1.toInt32(callFrame) | src2.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
 
         vPC += OPCODE_LENGTH(op_bitor);
         }
 
         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())
         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 {
         else {
-            JSValue result = jsNumber(callFrame, ~src.toInt32(callFrame));
+            JSValue result = jsNumber(~src.toInt32(callFrame));
             CHECK_FOR_EXCEPTION();
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = result;
+            callFrame->uncheckedR(dst) = result;
         }
         vPC += OPCODE_LENGTH(op_bitnot);
         NEXT_INSTRUCTION();
         }
         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();
         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();
     }
 
         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)
 
     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();
 
 
         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();
 
         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();
 
         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;
         */
         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();
 
         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();
         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();
 
         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;
         */
         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();
 
         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;
         */
         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();
 
         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;
         */
         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();
 
         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;
         */
         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();
 
         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;
         */
         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();
 
         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();
         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);
             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))
 
         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();
         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);
         }
 
         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;
            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());
         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();
     }
         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.
          */
          
            Puts value into global slot index.
          */
-        JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[1].u.jsCell);
+        JSGlobalObject* scope = codeBlock->globalObject();
         ASSERT(scope->isGlobalObject());
         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();
     }
         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
         /* 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 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);
 
         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());
         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();
     }
         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 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();
         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);
         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());
         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) {
         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
 
            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);
         */
         resolveBase(callFrame, vPC);
+        CHECK_FOR_EXCEPTION();
 
         vPC += OPCODE_LENGTH(op_resolve_base);
         NEXT_INSTRUCTION();
     }
 
         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)
 
     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;
 
         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);
         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);
 
 
         tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot);
 
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_id);
         NEXT_INSTRUCTION();
     }
         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())) {
         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());
 
             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;
 
                 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();
             }
         }
 
 
                 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) {
         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())) {
         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));
 
             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;
 
 
                 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();
 
                     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)
         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())) {
         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));
             
             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;
                 
                 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();
                         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
                     } else
-                        callFrame->r(dst) = jsUndefined();
+                        callFrame->uncheckedR(dst) = jsUndefined();
                     vPC += OPCODE_LENGTH(op_get_by_id_getter_proto);
                     NEXT_INSTRUCTION();
                 }
             }
         }
                     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)
         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())) {
         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));
             
             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;
                 
                 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();
                     
                     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();
                 }
             }
         }
                     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)
         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();
     }
         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)
 
     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())) {
         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)) {
 
             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;
                 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));
 
                 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;
 
                         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();
 
                         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)
         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) {
     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())) {
         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());
             
             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();
                     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
                 } else
-                    callFrame->r(dst) = jsUndefined();
+                    callFrame->uncheckedR(dst) = jsUndefined();
 
                 vPC += OPCODE_LENGTH(op_get_by_id_getter_self);
                 NEXT_INSTRUCTION();
             }
         }
 
                 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)
         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())) {
         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;
             
             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();
 
                 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();
             }
         }
                 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)
         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;
 
         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();
 
         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();
     }
         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())) {
         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)) {
             
             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;
                 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));
                 
                 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();
                             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
                         } else
-                            callFrame->r(dst) = jsUndefined();
+                            callFrame->uncheckedR(dst) = jsUndefined();
                         vPC += OPCODE_LENGTH(op_get_by_id_getter_chain);
                         NEXT_INSTRUCTION();
                     }
                         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)
         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())) {
         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)) {
             
             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;
                 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));
                 
                 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;
                     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();
                         
                         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();
                     }
                         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:
         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)
 #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;
         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();
         }
 
             vPC += OPCODE_LENGTH(op_get_array_length);
             NEXT_INSTRUCTION();
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
         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)
 
     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;
         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();
         }
 
             vPC += OPCODE_LENGTH(op_get_string_length);
             NEXT_INSTRUCTION();
         }
 
-        uncacheGetByID(callFrame->codeBlock(), vPC);
+        uncacheGetByID(codeBlock, vPC);
         NEXT_INSTRUCTION();
     }
         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)
 
     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.
 
            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.
         */
            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;
 
         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);
         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);
         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();
     }
         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)
          
     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())) {
         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 (LIKELY(baseCell->structure() == oldStructure)) {
                 ASSERT(baseCell->isObject());
                 JSObject* baseObject = asObject(baseCell);
                 int direct = vPC[8].u.operand;
-
+                
                 if (!direct) {
                 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())) {
 
                     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);
                     }
                 }
                             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;
 
                 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();
             }
         }
         
 
                 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) {
         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())) {
         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());
 
             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;
                 
                 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();
             }
         }
 
 
                 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) {
         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();
         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);
         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);
         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();
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = jsBoolean(result);
         vPC += OPCODE_LENGTH(op_del_by_id);
         NEXT_INSTRUCTION();
     }
         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)) {
         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();
         }
             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();
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_pname);
         NEXT_INSTRUCTION();
     }
         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)
 
     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();
         }
 
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = result;
         vPC += OPCODE_LENGTH(op_get_by_val);
         NEXT_INSTRUCTION();
     }
         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))
             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)) {
                 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.
         } 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);
             }
         }
                 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();
         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))
         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();
         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();
         CHECK_FOR_EXCEPTION();
-        callFrame->r(dst) = result;
+        callFrame->uncheckedR(dst) = jsBoolean(result);
         vPC += OPCODE_LENGTH(op_del_by_val);
         NEXT_INSTRUCTION();
     }
         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;
            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();
         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();
         }
             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())
         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))
         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;
         }
             else
                 vPC += defaultOffset;
         }
@@ -3461,11 +3868,11 @@ skip_id_custom_self:
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else {
         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
             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();
     }
         }
         NEXT_INSTRUCTION();
     }
@@ -3484,7 +3891,7 @@ skip_id_custom_self:
         if (!scrutinee.isString())
             vPC += defaultOffset;
         else 
         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) {
         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;
         */
         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();
 
         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;
         */
         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());
 
         /* 
         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);
          */
         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) {
 
         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
 
            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.
          */
 
            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();
         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()) {
 
         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;
                 goto vm_throw;
-            callFrame->r(dst) = result;
+            functionReturnValue = result;
 
             vPC += OPCODE_LENGTH(op_call_eval);
             NEXT_INSTRUCTION();
 
             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) {
         // 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.
            
 
            Perform a function call.
            
@@ -3583,22 +3993,26 @@ skip_id_custom_self:
            dst is where op_ret should store its result.
          */
 
            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;
 
         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;
 
         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;
             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
             if (UNLIKELY(!callFrame)) {
                 callFrame = previousCallFrame;
@@ -3606,7 +4020,9 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
                 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)
             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);
         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());
 
             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();
 
             }
             CHECK_FOR_EXCEPTION();
 
-            callFrame->r(dst) = returnValue;
+            functionReturnValue = returnValue;
 
             vPC += OPCODE_LENGTH(op_call);
             NEXT_INSTRUCTION();
 
             vPC += OPCODE_LENGTH(op_call);
             NEXT_INSTRUCTION();
@@ -3644,7 +4057,7 @@ skip_id_custom_self:
 
         ASSERT(callType == CallTypeNone);
 
 
         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) {
         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) {
         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;
             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;
             }
                 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')
             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()) {
         } 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;
             }
                 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);
                 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);
                     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);
                 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 {
                     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();
                 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) {
         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.
          
          
          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.
          */
         
          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;
         
         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;
         
         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;
             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 = 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)
             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);
         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());
             
             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();
             
             }
             CHECK_FOR_EXCEPTION();
             
-            callFrame->r(dst) = returnValue;
+            functionReturnValue = returnValue;
             
             vPC += OPCODE_LENGTH(op_call_varargs);
             NEXT_INSTRUCTION();
             
             vPC += OPCODE_LENGTH(op_call_varargs);
             NEXT_INSTRUCTION();
@@ -3800,52 +4215,99 @@ skip_id_custom_self:
         
         ASSERT(callType == CallTypeNone);
         
         
         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) {
         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) {
 
         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) {
 
         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
         /* 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;
 
 
         int result = vPC[1].u.operand;
 
-        if (callFrame->codeBlock()->needsFullScopeChain())
-            callFrame->scopeChain()->deref();
-
         JSValue returnValue = callFrame->r(result).jsValue();
 
         JSValue returnValue = callFrame->r(result).jsValue();
 
+        if (UNLIKELY(!returnValue.isObject()))
+            returnValue = callFrame->r(vPC[2].u.operand).jsValue();
+
         vPC = callFrame->returnVPC();
         vPC = callFrame->returnVPC();
-        int dst = callFrame->returnValueRegister();
         callFrame = callFrame->callerFrame();
         callFrame = callFrame->callerFrame();
-        
+
         if (callFrame->hasHostCallFrameFlag())
             return returnValue;
 
         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
 
 
         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;
         */
 
         size_t i = 0;
-        CodeBlock* codeBlock = callFrame->codeBlock();
-        
         for (size_t count = codeBlock->m_numVars; i < count; ++i)
         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();
     }
 
         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.
         */
 
 
            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) {
         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())
         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();
     }
 
         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) {
         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.
          */
         
 
            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) {
         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
 
            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.
         */
 
            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;
 
         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;
 
         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;
 
             CallFrame* previousCallFrame = callFrame;
-
+            CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
             if (UNLIKELY(!callFrame)) {
                 callFrame = previousCallFrame;
             callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
             if (UNLIKELY(!callFrame)) {
                 callFrame = previousCallFrame;
@@ -4020,7 +4520,8 @@ skip_id_custom_self:
                 goto vm_throw;
             }
 
                 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();
             vPC = newCodeBlock->instructions().begin();
 #if ENABLE(OPCODE_STATS)
             OpcodeStats::resetLastInstruction();
@@ -4030,19 +4531,21 @@ skip_id_custom_self:
         }
 
         if (constructType == ConstructTypeHost) {
         }
 
         if (constructType == ConstructTypeHost) {
-            ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
-
             ScopeChainNode* scopeChain = callFrame->scopeChain();
             CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
             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());
 
             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();
             }
             CHECK_FOR_EXCEPTION();
-            callFrame->r(dst) = JSValue(returnValue);
+            functionReturnValue = returnValue;
 
             vPC += OPCODE_LENGTH(op_construct);
             NEXT_INSTRUCTION();
 
             vPC += OPCODE_LENGTH(op_construct);
             NEXT_INSTRUCTION();
@@ -4050,34 +4553,23 @@ skip_id_custom_self:
 
         ASSERT(constructType == ConstructTypeNone);
 
 
         ASSERT(constructType == ConstructTypeNone);
 
-        exceptionValue = createNotAConstructorError(callFrame, v, vPC - callFrame->codeBlock()->instructions().begin(), callFrame->codeBlock());
+        exceptionValue = createNotAConstructorError(callFrame, v);
         goto vm_throw;
     }
         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;
 
         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);
 
         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;
 
         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();
         vPC += OPCODE_LENGTH(op_to_primitive);
 
         NEXT_INSTRUCTION();
@@ -4104,7 +4596,7 @@ skip_id_custom_self:
         JSObject* o = v.toObject(callFrame);
         CHECK_FOR_EXCEPTION();
 
         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);
         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);
 
         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();
     }
         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());
         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();
             if (key) {
                 CHECK_FOR_TIMEOUT();
-                callFrame->r(dst) = key;
+                callFrame->uncheckedR(dst) = key;
                 vPC += target;
                 NEXT_INSTRUCTION();
             }
                 vPC += target;
                 NEXT_INSTRUCTION();
             }
@@ -4229,7 +4722,7 @@ skip_id_custom_self:
         ASSERT(exceptionValue);
         ASSERT(!globalData->exception);
         int ex = vPC[1].u.operand;
         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);
         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();
 
         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();
     }
         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)
     }
     DEFINE_OPCODE(op_end) {
         /* end result(r)
@@ -4283,11 +4768,6 @@ skip_id_custom_self:
            program. Return control to the calling native code.
         */
 
            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();
     }
         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());
 
         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()));
 
         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());
 
         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);
 
         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);
         }
             // 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) {
         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();
     }
     }
         NEXT_INSTRUCTION();
     }
     }
@@ -4446,27 +4929,22 @@ JSValue Interpreter::retrieveArguments(CallFrame* callFrame, JSFunction* functio
     CodeBlock* codeBlock = functionCallFrame->codeBlock();
     if (codeBlock->usesArguments()) {
         ASSERT(codeBlock->codeType() == FunctionCode);
     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;
 }
 
     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)
 {
     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())
     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
 #if ENABLE(JIT)
     else
-        bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
+        bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
 #endif
 #else
 #endif
 #else
-    bytecodeOffset = bytecodeOffsetForPC(callerFrame, callerCodeBlock, callFrame->returnPC());
+    bytecodeOffset = callerCodeBlock->bytecodeOffset(callFrame->returnPC());
 #endif
 #endif
-    lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(callerFrame, bytecodeOffset - 1);
+    lineNumber = callerCodeBlock->lineNumberForBytecodeOffset(bytecodeOffset - 1);
     sourceID = callerCodeBlock->ownerExecutable()->sourceID();
     sourceURL = callerCodeBlock->ownerExecutable()->sourceURL();
     function = callerFrame->callee();
 }
 
     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)
 {
     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"
 #define Interpreter_h
 
 #include "ArgList.h"
-#include "FastAllocBase.h"
 #include "JSCell.h"
 #include "JSValue.h"
 #include "JSObject.h"
 #include "JSCell.h"
 #include "JSValue.h"
 #include "JSObject.h"
@@ -44,7 +43,6 @@ namespace JSC {
     class CodeBlock;
     class EvalExecutable;
     class FunctionExecutable;
     class CodeBlock;
     class EvalExecutable;
     class FunctionExecutable;
-    class InternalFunction;
     class JSFunction;
     class JSGlobalObject;
     class ProgramExecutable;
     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.
 
     // 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:
         friend class JIT;
         friend class CachedCall;
     public:
-        Interpreter();
+        Interpreter(JSGlobalData&);
 
         RegisterFile& registerFile() { return m_registerFile; }
         
 
         RegisterFile& registerFile() { return m_registerFile; }
         
@@ -96,21 +95,22 @@ namespace JSC {
         }
 
         bool isOpcode(Opcode);
         }
 
         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 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(); }
 
         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);
         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 };
 
     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&);
         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);
 
 #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 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*);
 
         void dumpCallFrame(CallFrame*);
         void dumpRegisters(CallFrame*);
index ecd7403246a2eb3952071392623a18766ded561e..fb02c12089b21ad3dcc1a4e99d862865b74d5123 100644 (file)
 
 #include "JSValue.h"
 #include <wtf/Assertions.h>
 
 #include "JSValue.h"
 #include <wtf/Assertions.h>
-#include <wtf/FastAllocBase.h>
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
 
 #include <wtf/VectorTraits.h>
 
 namespace JSC {
 
-    class Arguments;
     class CodeBlock;
     class ExecState;
     class JSActivation;
     class CodeBlock;
     class ExecState;
     class JSActivation;
-    class JSFunction;
+    class JSObject;
     class JSPropertyNameIterator;
     class ScopeChainNode;
 
     class JSPropertyNameIterator;
     class ScopeChainNode;
 
@@ -48,50 +46,43 @@ namespace JSC {
 
     typedef ExecState CallFrame;
 
 
     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;
     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=(CallFrame*);
         Register& operator=(CodeBlock*);
-        Register& operator=(JSFunction*);
-        Register& operator=(JSPropertyNameIterator*);
         Register& operator=(ScopeChainNode*);
         Register& operator=(Instruction*);
 
         int32_t i() const;
         JSActivation* activation() const;
         Register& operator=(ScopeChainNode*);
         Register& operator=(Instruction*);
 
         int32_t i() const;
         JSActivation* activation() const;
-        Arguments* arguments() const;
         CallFrame* callFrame() const;
         CodeBlock* codeBlock() 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)
         {
         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;
         }
 
             return r;
         }
 
+        static inline Register withCallee(JSObject* callee);
+
     private:
         union {
     private:
         union {
-            int32_t i;
             EncodedJSValue value;
             EncodedJSValue value;
-
-            JSActivation* activation;
             CallFrame* callFrame;
             CodeBlock* codeBlock;
             CallFrame* callFrame;
             CodeBlock* codeBlock;
-            JSFunction* function;
-            JSPropertyNameIterator* propertyNameIterator;
-            ScopeChainNode* scopeChain;
             Instruction* vPC;
         } u;
     };
             Instruction* vPC;
         } u;
     };
@@ -125,14 +116,13 @@ namespace JSC {
         return JSValue::decode(u.value);
     }
 
         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;
     ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame)
     {
         u.callFrame = callFrame;
@@ -145,40 +135,17 @@ namespace JSC {
         return *this;
     }
 
         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=(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
     {
     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;
     ALWAYS_INLINE CallFrame* Register::callFrame() const
     {
         return u.callFrame;
@@ -188,22 +155,7 @@ namespace JSC {
     {
         return u.codeBlock;
     }
     {
         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;
     ALWAYS_INLINE Instruction* Register::vPC() const
     {
         return u.vPC;
index 63ea5b371c4e5af90743aa44eed59db63b0fc000..e3b34bb08a40c5b0692c3e23a6b7be0aff0c7f11 100644 (file)
 #include "config.h"
 #include "RegisterFile.h"
 
 #include "config.h"
 #include "RegisterFile.h"
 
+#include "ConservativeRoots.h"
+#include "Interpreter.h"
+#include "JSGlobalData.h"
 #include "JSGlobalObject.h"
 
 namespace JSC {
 
 #include "JSGlobalObject.h"
 
 namespace JSC {
 
+static size_t committedBytesCount = 0;
+
+static Mutex& registerFileStatisticsMutex()
+{
+    DEFINE_STATIC_LOCAL(Mutex, staticMutex, ());
+    return staticMutex;
+}    
+    
 RegisterFile::~RegisterFile()
 {
 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()
 {
 }
 
 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;
     m_commitEnd = m_start;
-#endif
     m_maxUsed = m_start;
 }
 
 void RegisterFile::setGlobalObject(JSGlobalObject* globalObject)
 {
     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
 }
 
 } // namespace JSC
index def9e2549195a0def3c7374cd490fc5984986485..f59c13a1b5327e7e4cf25f79c9c8b1cc1f6fed69 100644 (file)
 #ifndef RegisterFile_h
 #define RegisterFile_h
 
 #ifndef RegisterFile_h
 #define RegisterFile_h
 
-#include "Collector.h"
+#include "Heap.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
 #include "ExecutableAllocator.h"
 #include "Register.h"
-#include "WeakGCPtr.h"
+#include "Weak.h"
 #include <stdio.h>
 #include <wtf/Noncopyable.h>
 #include <stdio.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/PageReservation.h>
 #include <wtf/VMTags.h>
 
 #include <wtf/VMTags.h>
 
-#if HAVE(MMAP)
-#include <errno.h>
-#include <sys/mman.h>
-#endif
-
 namespace JSC {
 
 /*
 namespace JSC {
 
 /*
@@ -93,40 +89,38 @@ namespace JSC {
 
     class JSGlobalObject;
 
 
     class JSGlobalObject;
 
-    class RegisterFile : public Noncopyable {
-        friend class JIT;
+    class RegisterFile {
+        WTF_MAKE_NONCOPYABLE(RegisterFile);
     public:
         enum CallFrameHeaderEntry {
     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 { 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;
 
         // 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();
         ~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*);
 
         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);
         JSGlobalObject* globalObject();
 
         bool grow(Register* newEnd);
@@ -138,85 +132,53 @@ namespace JSC {
 
         Register* lastGlobal() const { return m_start - m_numGlobals; }
         
 
         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();
 
     private:
         void releaseExcessCapacity();
+        void addToCommittedByteCount(long);
         size_t m_numGlobals;
         const size_t m_maxGlobals;
         Register* m_start;
         Register* m_end;
         Register* m_max;
         size_t m_numGlobals;
         const size_t m_maxGlobals;
         Register* m_start;
         Register* m_end;
         Register* m_max;
-        Register* m_buffer;
         Register* m_maxUsed;
         Register* m_maxUsed;
-
-#if HAVE(VIRTUALALLOC)
         Register* m_commitEnd;
         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_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);
         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);
         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;
         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 (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 (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;
 
         if (newEnd > m_maxUsed)
             m_maxUsed = newEnd;
index 5e10e863d49f6ddd899a33709c0540dfa94aa125..35531d92ed08db71ee0bb6ff0cb005b4bbd089bf 100644 (file)
@@ -33,8 +33,59 @@ namespace JSC {
 
 size_t ExecutableAllocator::pageSize = 0;
 
 
 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)
 #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();
 {
     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);
 }
 
     mprotect(pageStart, size, (setting == Writable) ? PROTECTION_FLAGS_RW : PROTECTION_FLAGS_RX);
 }
+
 #endif
 
 #if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
 #endif
 
 #if CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT)
+
 __asm void ExecutableAllocator::cacheFlush(void* code, size_t size)
 {
     ARM
 __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
 }
     pop {r7}
     bx lr
 }
+
 #endif
 
 }
 #endif
 
 }
index 62d708d8e69d8c8b47099b1e83c9a36a14583372..be315c70e8162cdac730e39fa9eddd9d5ef71b02 100644 (file)
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
-
 #include <stddef.h> // for ptrdiff_t
 #include <limits>
 #include <wtf/Assertions.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>
 
 #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 <libkern/OSCacheControl.h>
 #include <sys/mman.h>
 #endif
 #include <sys/cachectl.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 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 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
 #else
-#define INITIAL_PROTECTION_FLAGS (PROT_READ | PROT_WRITE | PROT_EXEC)
+#define EXECUTABLE_POOL_WRITABLE true
 #endif
 
 namespace JSC {
 #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 {
 
 
 namespace JSC {
 
+class JSGlobalData;
+void releaseExecutableMemory(JSGlobalData&);
+
 class ExecutablePool : public RefCounted<ExecutablePool> {
 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;
 
     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);
 
     {
         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
 
         // 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)
     }
     
     void tryShrink(void* allocation, size_t oldSize, size_t newSize)
@@ -129,22 +156,20 @@ public:
 
     ~ExecutablePool()
     {
 
     ~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; }
 
             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);
 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;
 
     char* m_freePtr;
     char* m_end;
@@ -152,16 +177,16 @@ private:
 };
 
 class ExecutableAllocator {
 };
 
 class ExecutableAllocator {
-    enum ProtectionSeting { Writable, Executable };
+    enum ProtectionSetting { Writable, Executable };
 
 public:
     static size_t pageSize;
 
 public:
     static size_t pageSize;
-    ExecutableAllocator()
+    ExecutableAllocator(JSGlobalData& globalData)
     {
         if (!pageSize)
             intializePageSize();
         if (isValid())
     {
         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();
 #if !ENABLE(INTERPRETER)
         else
             CRASH();
@@ -169,8 +194,10 @@ public:
     }
 
     bool isValid() const;
     }
 
     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);
     {
         // 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)
 
         // 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
 
         // 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
 
         // 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)
     {
 #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));
         //
         int lineSize;
         asm("rdhwr %0, $1" : "=r" (lineSize));
         //
@@ -237,11 +264,10 @@ public:
         _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
 #endif
     }
         _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)
     {
     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)
     }
 #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);
     }
     {
         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
 #else
     #error "The cacheFlush support is missing on this platform."
 #endif
+    static size_t committedByteCount();
 
 private:
 
 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
 
 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();
 };
 
 #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);
 {
     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_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;
 }
 
     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);
 {
     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
     
     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);
     }
 
     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)
 
 #endif // !defined(ExecutableAllocator)
index 3048e20cdc8d5da0c4f1658a6680542c7e5e9fca..792e931497faaf73e1cee7e3077beaece67bd853 100644 (file)
 #include <sys/mman.h>
 #include <unistd.h>
 #include <wtf/AVLTree.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <wtf/AVLTree.h>
+#include <wtf/PageReservation.h>
 #include <wtf/VMTags.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 MMAP_FLAGS (MAP_PRIVATE | MAP_ANON | MAP_JIT)
 
 using namespace WTF;
 
 namespace JSC {
-
+    
 #define TwoPow(n) (1ull << n)
 
 class AllocationTableSizeClass {
 #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;
                     // Mirror the suballocation's full bit.
                     if (m_suballocations[i].isFull())
                         m_full |= bit;
-                    return (i * subregionSize) + location;
+                    return (i * subregionSize) | location;
                 }
             }
             return notFound;
                 }
             }
             return notFound;
@@ -381,6 +386,7 @@ private:
     BitField m_hasSuballocation;
 };
 
     BitField m_hasSuballocation;
 };
 
+
 typedef AllocationTableLeaf<6> PageTables256KB;
 typedef AllocationTableDirectory<PageTables256KB, 6> PageTables16MB;
 typedef AllocationTableDirectory<LazyAllocationTable<PageTables16MB>, 1> PageTables32MB;
 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;
 
 #if CPU(ARM)
 typedef PageTables16MB FixedVMPoolPageTables;
-#elif CPU(X86_64) && !OS(LINUX)
+#elif CPU(X86_64)
 typedef PageTables1GB FixedVMPoolPageTables;
 #else
 typedef PageTables32MB FixedVMPoolPageTables;
 #endif
 
 typedef PageTables1GB FixedVMPoolPageTables;
 #else
 typedef PageTables32MB FixedVMPoolPageTables;
 #endif
 
+
 class FixedVMPoolAllocator
 {
 public:
     FixedVMPoolAllocator()
     {
 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
             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);
         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())
         if (m_pages.isFull())
-            CRASH();
+            return ExecutablePool::Allocation(0, 0);
+
         size_t offset = m_pages.allocate(sizeClass);
         if (offset == notFound)
         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);
         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);
     AllocationTableSizeClass classForSize(size_t size)
     {
         return FixedVMPoolPageTables::classForSize(size);
@@ -492,27 +470,34 @@ private:
 
     void* offsetToPointer(size_t offset)
     {
 
     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)
     {
     }
 
     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;
 };
 
     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();
 }
 
 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);
 bool ExecutableAllocator::isValid() const
 {
     SpinLockHolder lock_holder(&spinlock);
@@ -521,34 +506,38 @@ bool ExecutableAllocator::isValid() const
     return allocator->isValid();
 }
 
     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);
 {
     SpinLockHolder lock_holder(&spinlock);
-
     ASSERT(allocator);
     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)
 #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"
  */
 
 #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.
 #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
 
 JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2;
 #endif
 
-#if ENABLE(JIT)
-
 #include "CodeBlock.h"
 #include "CodeBlock.h"
+#include "CryptographicallyRandomNumber.h"
 #include "Interpreter.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.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"
 #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;
 
 
 using namespace std;
 
@@ -71,17 +69,17 @@ void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAd
     repatchBuffer.relinkCallerToFunction(returnAddress, newCalleeFunction);
 }
 
     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_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)
 #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)
     , 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_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()
 {
 {
 }
 
 #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);
     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()
 {
 #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);
 
     JITStubCall(this, cti_timeout_check).call(timeoutCheckRegister);
     skipTimeout.link(this);
 
@@ -115,7 +117,7 @@ void JIT::emitTimeoutCheck()
 #endif
 
 #define NEXT_OPCODE(name) \
 #endif
 
 #define NEXT_OPCODE(name) \
-    m_bytecodeIndex += OPCODE_LENGTH(name); \
+    m_bytecodeOffset += OPCODE_LENGTH(name); \
     break;
 
 #if USE(JSVALUE32_64)
     break;
 
 #if USE(JSVALUE32_64)
@@ -177,27 +179,24 @@ void JIT::privateCompileMainPass()
     m_globalResolveInfoIndex = 0;
     m_callLinkInfoIndex = 0;
 
     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 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
 
             sampleInstruction(currentInstruction);
 #endif
 
-#if !USE(JSVALUE32_64)
-        if (m_labels[m_bytecodeIndex].isUsed())
+#if USE(JSVALUE64)
+        if (atJumpTarget())
             killLastResultRegister();
 #endif
 
             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)
 
         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)
         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)
         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)
         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_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_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)
         DEFINE_OP(op_create_arguments)
         DEFINE_OP(op_debug)
         DEFINE_OP(op_del_by_id)
-#if !USE(JSVALUE32)
         DEFINE_OP(op_div)
         DEFINE_OP(op_div)
-#endif
         DEFINE_OP(op_end)
         DEFINE_OP(op_enter)
         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_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_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_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)
         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_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)
         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_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_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)
         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_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)
 
         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.
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
-    m_bytecodeIndex = (unsigned)-1;
+    m_bytecodeOffset = (unsigned)-1;
 #endif
 }
 
 #endif
 }
 
@@ -357,7 +363,7 @@ void JIT::privateCompileLinkPass()
 {
     unsigned jmpTableCount = m_jmpTable.size();
     for (unsigned i = 0; i < jmpTableCount; ++i)
 {
     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();
 }
 
     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();) {
     m_callLinkInfoIndex = 0;
 
     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
-#if !USE(JSVALUE32_64)
+#if USE(JSVALUE64)
         killLastResultRegister();
 #endif
 
         killLastResultRegister();
 #endif
 
-        m_bytecodeIndex = iter->to;
+        m_bytecodeOffset = iter->to;
 #ifndef NDEBUG
 #ifndef NDEBUG
-        unsigned firstTo = m_bytecodeIndex;
+        unsigned firstTo = m_bytecodeOffset;
 #endif
 #endif
-        Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
+        Instruction* currentInstruction = instructionsBegin + m_bytecodeOffset;
 
         switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
         DEFINE_SLOWCASE_OP(op_add)
 
         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_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)
         DEFINE_SLOWCASE_OP(op_convert_this)
-#if !USE(JSVALUE32)
+        DEFINE_SLOWCASE_OP(op_convert_this_strict)
         DEFINE_SLOWCASE_OP(op_div)
         DEFINE_SLOWCASE_OP(op_div)
-#endif
         DEFINE_SLOWCASE_OP(op_eq)
         DEFINE_SLOWCASE_OP(op_get_by_id)
         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_by_val)
+        DEFINE_SLOWCASE_OP(op_get_argument_by_val)
         DEFINE_SLOWCASE_OP(op_get_by_pname)
         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)
         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_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)
         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.
 
 #ifndef NDEBUG
     // Reset this, in order to guard its use with ASSERTs.
-    m_bytecodeIndex = (unsigned)-1;
+    m_bytecodeOffset = (unsigned)-1;
 #endif
 }
 
 #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);
 
 
     // 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 (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);
 
         // 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);
         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();
 
     privateCompileMainPass();
     privateCompileLinkPass();
     privateCompileSlowCases();
 
+    Label arityCheck;
     if (m_codeBlock->codeType() == FunctionCode) {
     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
         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
 #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());
 
     }
 
     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];
 
     // 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());
 
 
         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];
 
             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);
 
             }
         } 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;
 
             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));
     }
 
             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().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
     }
 
     // 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);
 #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);
         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);
     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;
     }
 
         info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
     }
 
+    if (m_codeBlock->codeType() == FunctionCode && functionEntryArityCheck)
+        *functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
+
     return patchBuffer.finalizeCode();
 }
 
     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);
 
 {
     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 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.
     }
 
     // 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)
 
 }
 #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 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"
 
 #include "CodeBlock.h"
 #include "Interpreter.h"
@@ -66,16 +67,16 @@ namespace JSC {
 
     struct CallRecord {
         MacroAssembler::Call from;
 
     struct CallRecord {
         MacroAssembler::Call from;
-        unsigned bytecodeIndex;
+        unsigned bytecodeOffset;
         void* to;
 
         CallRecord()
         {
         }
 
         void* to;
 
         CallRecord()
         {
         }
 
-        CallRecord(MacroAssembler::Call from, unsigned bytecodeIndex, void* to = 0)
+        CallRecord(MacroAssembler::Call from, unsigned bytecodeOffset, void* to = 0)
             : from(from)
             : from(from)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
             , to(to)
         {
         }
             , to(to)
         {
         }
@@ -83,11 +84,11 @@ namespace JSC {
 
     struct JumpTable {
         MacroAssembler::Jump from;
 
     struct JumpTable {
         MacroAssembler::Jump from;
-        unsigned toBytecodeIndex;
+        unsigned toBytecodeOffset;
 
         JumpTable(MacroAssembler::Jump f, unsigned t)
             : from(f)
 
         JumpTable(MacroAssembler::Jump f, unsigned t)
             : from(f)
-            , toBytecodeIndex(t)
+            , toBytecodeOffset(t)
         {
         }
     };
         {
         }
     };
@@ -119,20 +120,20 @@ namespace JSC {
             StringJumpTable* stringJumpTable;
         } jumpTable;
 
             StringJumpTable* stringJumpTable;
         } jumpTable;
 
-        unsigned bytecodeIndex;
+        unsigned bytecodeOffset;
         unsigned defaultOffset;
 
         unsigned defaultOffset;
 
-        SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type)
+        SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeOffset, unsigned defaultOffset, Type type)
             : type(type)
             : type(type)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
             , defaultOffset(defaultOffset)
         {
             this->jumpTable.simpleJumpTable = jumpTable;
         }
 
             , defaultOffset(defaultOffset)
         {
             this->jumpTable.simpleJumpTable = jumpTable;
         }
 
-        SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset)
+        SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeOffset, unsigned defaultOffset)
             : type(String)
             : type(String)
-            , bytecodeIndex(bytecodeIndex)
+            , bytecodeOffset(bytecodeOffset)
             , defaultOffset(defaultOffset)
         {
             this->jumpTable.stringJumpTable = jumpTable;
             , defaultOffset(defaultOffset)
         {
             this->jumpTable.stringJumpTable = jumpTable;
@@ -148,6 +149,7 @@ namespace JSC {
         MacroAssembler::DataLabelPtr hotPathBegin;
         MacroAssembler::Call hotPathOther;
         MacroAssembler::Call callReturnLocation;
         MacroAssembler::DataLabelPtr hotPathBegin;
         MacroAssembler::Call hotPathOther;
         MacroAssembler::Call callReturnLocation;
+        bool isCall;
     };
 
     struct MethodCallCompilationInfo {
     };
 
     struct MethodCallCompilationInfo {
@@ -173,14 +175,15 @@ namespace JSC {
         using MacroAssembler::Label;
 
         static const int patchGetByIdDefaultStructure = -1;
         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.
         // 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:
 
     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)
         }
 
         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;
         {
             if (!globalData->canUseJIT())
                 return;
-            JIT jit(globalData, 0, 0);
+            JIT jit(globalData, 0);
             jit.privateCompileCTIMachineTrampolines(executablePool, globalData, trampolines);
         }
 
             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 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)
         {
 
         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
         {
@@ -235,8 +246,8 @@ namespace JSC {
             return jit.privateCompilePatchGetArrayLength(returnAddress);
         }
 
             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 {
 
     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();
 
         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);
         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);
         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);
         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 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 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);
 
         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 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);
 
 #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 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 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);
 
         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);
         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 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
         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;
 #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 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;
         static const int patchOffsetGetByIdSlowCaseCall = 37;
-#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
-        static const int patchOffsetGetByIdSlowCaseCall = 25;
 #else
         static const int patchOffsetGetByIdSlowCaseCall = 27;
 #endif
 #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;
 #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 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;
         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 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;
         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;
 #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;
         // 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
 #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;
         // 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
 #else
 #error "JSVALUE32_64 not supported on this platform."
 #endif
@@ -455,9 +529,6 @@ namespace JSC {
 
         int32_t getConstantOperandImmediateInt(unsigned src);
 
 
         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);
         void killLastResultRegister();
 
         Jump emitJumpIfJSCell(RegisterID);
@@ -466,8 +537,7 @@ namespace JSC {
         Jump emitJumpIfNotJSCell(RegisterID);
         void emitJumpSlowCaseIfNotJSCell(RegisterID);
         void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
         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);
         JIT::Jump emitJumpIfImmediateNumber(RegisterID reg)
         {
             return emitJumpIfImmediateInteger(reg);
@@ -485,7 +555,7 @@ namespace JSC {
         void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
         void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
-#if !USE(JSVALUE64)
+#if USE(JSVALUE32_64)
         void emitFastArithDeTagImmediate(RegisterID);
         Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
 #endif
         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 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;
         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 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
 #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;
 #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 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;
         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;
         static const int patchOffsetGetByIdSlowCaseCall = 33;
-#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
-        static const int patchOffsetGetByIdSlowCaseCall = 21;
 #else
         static const int patchOffsetGetByIdSlowCaseCall = 23;
 #endif
 #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;
 #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 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)
         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;
 #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 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)
         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;
 #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 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)
         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 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 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)
         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)
 #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 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)
 
 #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*);
 #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(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_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(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_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_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_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_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*);
         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_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*);
         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_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_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*);
         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_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*);
         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
 
         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_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(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_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_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_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&);
         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_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&);
         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);
 
         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 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);
         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 isOperandConstantImmediateInt(unsigned src);
         bool isOperandConstantImmediateChar(unsigned src);
 
+        bool atJumpTarget();
+
         Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
         {
             return iter++->from;
         Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
         {
             return iter++->from;
@@ -921,7 +973,7 @@ namespace JSC {
         Vector<MethodCallCompilationInfo> m_methodCallCompilationInfo;
         Vector<JumpTable> m_jmpTable;
 
         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;
         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;
 
 #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_mappedVirtualRegisterIndex;
         RegisterID m_mappedTag;
         RegisterID m_mappedPayload;
 #else
         int m_lastResultBytecodeRegister;
-        unsigned m_jumpTargetsPosition;
 #endif
 #endif
+        unsigned m_jumpTargetsPosition;
 
 #ifndef NDEBUG
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
 #ifndef NDEBUG
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
@@ -947,8 +999,8 @@ namespace JSC {
         int m_uninterruptedConstantSequenceBegin;
 #endif
 #endif
         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)
     } JIT_CLASS_ALIGNMENT;
 
     inline void JIT::emit_op_loop(Instruction* currentInstruction)
index cd39b3ad01c1ff45e15551efbbe01f0c12b633fc..c2a84c5a4a634e36b6b469da5088e01c6866cc9d 100644 (file)
  */
 
 #include "config.h"
  */
 
 #include "config.h"
-#include "JIT.h"
 
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
+#if USE(JSVALUE64)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
@@ -46,8 +47,6 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if !USE(JSVALUE32_64)
-
 void JIT::emit_op_lshift(Instruction* currentInstruction)
 {
     unsigned result = currentInstruction[1].u.operand;
 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);
     emitFastArithImmToInt(regT0);
     emitFastArithImmToInt(regT2);
     lshift32(regT2, regT0);
-#if USE(JSVALUE32)
-    addSlowCase(branchAdd32(Overflow, regT0, regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
     emitFastArithReTagImmediate(regT0, regT0);
     emitPutVirtualRegister(result);
 }
     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;
 
     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);
     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);
     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);
         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));
             // 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 {
             lhsIsInt.link(this);
             emitJumpSlowCaseIfNotImmediateInteger(regT2);
         } else {
@@ -134,15 +110,8 @@ void JIT::emit_op_rshift(Instruction* currentInstruction)
         }
         emitFastArithImmToInt(regT2);
         rshift32(regT2, regT0);
         }
         emitFastArithImmToInt(regT2);
         rshift32(regT2, regT0);
-#if USE(JSVALUE32)
-        signExtend32ToPtr(regT0, regT0);
-#endif
     }
     }
-#if USE(JSVALUE64)
     emitFastArithIntToImmNoCheck(regT0, regT0);
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    orPtr(Imm32(JSImmediate::TagTypeNumber), regT0);
-#endif
     emitPutVirtualRegister(result);
 }
 
     emitPutVirtualRegister(result);
 }
 
@@ -160,17 +129,9 @@ void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEnt
         stubCall.addArgument(op2, regT2);
     } else {
         if (supportsFloatingPointTruncate()) {
         stubCall.addArgument(op2, regT2);
     } else {
         if (supportsFloatingPointTruncate()) {
-#if USE(JSVALUE64)
             linkSlowCase(iter);
             linkSlowCase(iter);
             linkSlowCase(iter);
             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.
             // 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))
         // 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;
         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);
     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);
 }
     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
         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
         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))
             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);
         }
             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 (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
     } 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
             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(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);
             }
                 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
         }
         
         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);
     }
     
     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 (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
         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);
         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
         int32_t op1imm = getConstantOperandImmediateInt(op1);
         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);
         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()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
             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();;
 
 
             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));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -423,18 +343,9 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
             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();;
 
 
             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));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -464,7 +369,6 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
             Jump fail3 = emitJumpIfImmediateInteger(regT1);
             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);
             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));
 
 
             emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail2.link(this);
             fail3.link(this);
             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);
         }
 
         linkSlowCase(iter);
@@ -546,20 +427,12 @@ void JIT::emit_op_jless(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
         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);
         addJump(branch32(LessThan, regT0, Imm32(op2imm)), target);
     } else if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT1);
         emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
         int32_t op1imm = getConstantOperandImmediateInt(op1);
         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);
         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()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
             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();
 
 
             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));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -638,18 +496,9 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
             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();
 
 
             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));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jless);
         }
 
         JITStubCall stubCall(this, cti_op_jless);
@@ -679,7 +522,6 @@ void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntr
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
             Jump fail3 = emitJumpIfImmediateInteger(regT1);
             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);
             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));
 
 
             emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target);
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail2.link(this);
             fail3.link(this);
             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);
         }
 
         linkSlowCase(iter);
@@ -761,20 +580,12 @@ void JIT::emit_op_jlesseq(Instruction* currentInstruction, bool invert)
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
     if (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
         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);
         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);
         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);
         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()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             addPtr(tagTypeNumberRegister, regT0);
             movePtrToDouble(regT0, fpRegT0);
             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();;
 
 
             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));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op1))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jlesseq);
         }
 
         JITStubCall stubCall(this, cti_op_jlesseq);
@@ -854,18 +650,9 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT1);
             addPtr(tagTypeNumberRegister, regT1);
             movePtrToDouble(regT1, fpRegT1);
             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();;
 
 
             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));
 
 
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq));
 
-#if USE(JSVALUE64)
             fail1.link(this);
             fail1.link(this);
-#else
-            if (!m_codeBlock->isKnownNotImmediate(op2))
-                fail1.link(this);
-            fail2.link(this);
-#endif
         }
 
         JITStubCall stubCall(this, cti_op_jlesseq);
         }
 
         JITStubCall stubCall(this, cti_op_jlesseq);
@@ -895,7 +676,6 @@ void JIT::emitSlow_op_jlesseq(Instruction* currentInstruction, Vector<SlowCaseEn
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
         linkSlowCase(iter);
 
         if (supportsFloatingPoint()) {
-#if USE(JSVALUE64)
             Jump fail1 = emitJumpIfNotImmediateNumber(regT0);
             Jump fail2 = emitJumpIfNotImmediateNumber(regT1);
             Jump fail3 = emitJumpIfImmediateInteger(regT1);
             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);
             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));
 
 
             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);
             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);
         }
 
         linkSlowCase(iter);
@@ -964,25 +721,17 @@ void JIT::emit_op_bitand(Instruction* currentInstruction)
     if (isOperandConstantImmediateInt(op1)) {
         emitGetVirtualRegister(op2, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
     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);
         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);
     } 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);
         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);
     } 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);
     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);
     emitFastArithIntToImmNoCheck(regT1, regT1);
-#else
-    addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
-    signExtend32ToPtr(regT1, regT1);
-#endif
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
 }
     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);
     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);
     emitFastArithIntToImmNoCheck(regT1, regT1);
-#else
-    addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT1));
-    signExtend32ToPtr(regT1, regT1);
-#endif
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
 }
     emitPutVirtualRegister(srcDst, regT1);
     emitPutVirtualRegister(result);
 }
@@ -1086,13 +825,8 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction)
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-    addSlowCase(branchAdd32(Overflow, Imm32(1), regT0));
+    addSlowCase(branchAdd32(Overflow, TrustedImm32(1), regT0));
     emitFastArithIntToImmNoCheck(regT0, regT0);
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    addSlowCase(branchAdd32(Overflow, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
     emitPutVirtualRegister(srcDst);
 }
 
     emitPutVirtualRegister(srcDst);
 }
 
@@ -1115,13 +849,8 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction)
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
 
     emitGetVirtualRegister(srcDst, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
-    addSlowCase(branchSub32(Zero, Imm32(1), regT0));
+    addSlowCase(branchSub32(Zero, TrustedImm32(1), regT0));
     emitFastArithIntToImmNoCheck(regT0, regT0);
     emitFastArithIntToImmNoCheck(regT0, regT0);
-#else
-    addSlowCase(branchSub32(Zero, Imm32(1 << JSImmediate::IntegerPayloadShift), regT0));
-    signExtend32ToPtr(regT0, regT0);
-#endif
     emitPutVirtualRegister(srcDst);
 }
 
     emitPutVirtualRegister(srcDst);
 }
 
@@ -1140,7 +869,7 @@ void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEn
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if CPU(X86) || CPU(X86_64)
+#if CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 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;
 
     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
 #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);
 }
 
     emitPutVirtualRegister(result);
 }
 
@@ -1170,26 +899,16 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
 {
     unsigned result = currentInstruction[1].u.operand;
 
 {
     unsigned result = currentInstruction[1].u.operand;
 
-#if USE(JSVALUE64)
-    linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
     linkSlowCase(iter);
-#else
-    Jump notImm1 = getSlowCase(iter);
-    Jump notImm2 = getSlowCase(iter);
     linkSlowCase(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);
     JITStubCall stubCall(this, cti_op_mod);
-    stubCall.addArgument(X86Registers::eax);
-    stubCall.addArgument(X86Registers::ecx);
+    stubCall.addArgument(regT0);
+    stubCall.addArgument(regT2);
     stubCall.call(result);
 }
 
     stubCall.call(result);
 }
 
-#else // CPU(X86) || CPU(X86_64)
+#else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 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;
 
     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);
     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)
 {
 }
 
 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;
     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 ------------------------------ */
 
 
 /* ------------------------------ 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)
 /* ------------------------------ 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.
 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;
 
     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);
 
     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)
 }
 
 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;
 
     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)
 }
 
 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);
 }
 
     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 ------------------------------ */
 
 /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
 
-#endif // !USE(JSVALUE32_64)
-
 } // namespace JSC
 
 } // namespace JSC
 
+#endif // USE(JSVALUE64)
 #endif // ENABLE(JIT)
 #endif // ENABLE(JIT)
index 3e5adc955b94e730f2fa9646fcccdda309a5c35d..67946548dc14309a3fb6ab884d571edd0bc76985 100644 (file)
 */
 
 #include "config.h"
 */
 
 #include "config.h"
-#include "JIT.h"
 
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
+#if USE(JSVALUE32_64)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
@@ -46,8 +47,6 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if USE(JSVALUE32_64)
-
 void JIT::emit_op_negate(Instruction* currentInstruction)
 {
     unsigned dst = currentInstruction[1].u.operand;
 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);
 
 
     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);
     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));
     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);
     // 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);
         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);
     }
     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);
         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);
     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);
         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);
         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);
     }
 
         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);
     // 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);
         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);
     }
     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);
         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);
     } 
     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);
         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);
         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);
     }
 
         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);
     // 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);
         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);
     }
     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);
         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);
     }
     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);
         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);
         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);
     }
 
         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);
 
     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;
         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))
 
     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);
 }
     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);
     // 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)
         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))
             // 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);
         }
         } 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))
 
     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);
     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);
     } 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;
         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))
             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);
             } 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()) {
         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);
                 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);
                 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);
     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);
         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));
 }
     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);
     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);
         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));
 }
     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);
     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);
         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));
 }
     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);
     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));
 
     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);
     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);
 
 
     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);
 }
 
     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);
     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);
 
 
     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);
 }
 
     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);
 
     JITStubCall stubCall(this, cti_op_post_dec);
     stubCall.addArgument(srcDst);
-    stubCall.addArgument(Imm32(srcDst));
+    stubCall.addArgument(TrustedImm32(srcDst));
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
@@ -748,8 +747,8 @@ void JIT::emit_op_pre_inc(Instruction* currentInstruction)
 
     emitLoad(srcDst, regT1, regT0);
 
 
     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);
 }
 
     emitStoreInt32(srcDst, regT0, true);
 }
 
@@ -773,8 +772,8 @@ void JIT::emit_op_pre_dec(Instruction* currentInstruction)
 
     emitLoad(srcDst, regT1, regT0);
 
 
     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);
 }
 
     emitStoreInt32(srcDst, regT0, true);
 }
 
@@ -818,8 +817,8 @@ void JIT::emit_op_add(Instruction* currentInstruction)
     }
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
     }
 
     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));
 
     // 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);
 {
     // 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));
 
     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())
 
     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);
     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);
     }
 
     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));
 
     // 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);
 {
     // 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));
 
     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())
 
     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);
     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())
 
         // 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);
 
 
         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())
 
         if (!types.second().definitelyIsNumber())
-            addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+            addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
 
         convertInt32ToDouble(regT2, fpRegT0);
         Jump doTheMath = jump();
 
         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())
 
         // 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) {
 
         // 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);
     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);
 
     // 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);
     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));
 
 
     emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_mul));
 
@@ -1241,22 +1240,12 @@ void JIT::emit_op_div(Instruction* currentInstruction)
 
     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
 
 
     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);
 
     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());
 
     emitStoreDouble(dst, fpRegT0);
     end.append(jump());
 
@@ -1294,7 +1283,7 @@ void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
 
 /* ------------------------------ BEGIN: OP_MOD ------------------------------ */
 
-#if CPU(X86) || CPU(X86_64)
+#if CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 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;
 
     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) {
     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)
         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 {
     } 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.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.
 
     // 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);
     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);
 }
 
     end.link(this);
 }
 
@@ -1356,7 +1358,7 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>
     stubCall.call(dst);
 }
 
     stubCall.call(dst);
 }
 
-#else // CPU(X86) || CPU(X86_64)
+#else // CPU(X86) || CPU(X86_64) || CPU(MIPS)
 
 void JIT::emit_op_mod(Instruction* currentInstruction)
 {
 
 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;
 
     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);
     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
 
     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)
 {
 
 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;
     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 ------------------------------ */
 
 
 /* ------------------------------ END: OP_MOD ------------------------------ */
 
-#endif // USE(JSVALUE32_64)
-
-}
+} // namespace JSC
 
 
+#endif // USE(JSVALUE32_64)
 #endif // ENABLE(JIT)
 #endif // ENABLE(JIT)
index 625b40dbdf1dcafabdf0e51a143d4fb558684c09..d0c266836ea7a2fed215880a440f1dc5d3d6a2ef 100644 (file)
  */
 
 #include "config.h"
  */
 
 #include "config.h"
-#include "JIT.h"
 
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
+#if USE(JSVALUE64)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
@@ -45,455 +46,38 @@ using namespace std;
 
 namespace JSC {
 
 
 namespace JSC {
 
-#if USE(JSVALUE32_64)
-
 void JIT::compileOpCallInitializeCallFrame()
 {
     // regT0 holds callee, regT1 holds argCount
 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 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)
 {
 }
 
 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);
 
     emitGetVirtualRegister(argCountRegister, regT1);
+    emitFastArithImmToInt(regT1);
     emitGetVirtualRegister(callee, regT0);
     emitGetVirtualRegister(callee, regT0);
-    compileOpCallVarargsSetupArgs(instruction);
+    addPtr(Imm32(registerOffset), regT1, regT2);
 
     // Check for JSFunctions.
     emitJumpSlowCaseIfNotJSCell(regT0);
 
     // 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.
 
     // 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);
     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());
 
     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);
 }
 
     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);
     linkSlowCase(iter);
     linkSlowCase(iter);
+
     JITStubCall stubCall(this, cti_op_call_NotJSFunction);
     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);
 }
     
     sampleCodeBlock(m_codeBlock);
 }
@@ -525,10 +108,9 @@ void JIT::compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCase
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned)
 {
 
 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;
 
     // 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();
         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);
     }
 
     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);
 
     // 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);
 
 
     // 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);
 
 
     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)
 {
     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);
 
     linkSlowCase(iter);
     linkSlowCase(iter);
+
     JITStubCall stubCall(this, opcodeID == op_construct ? cti_op_construct_NotJSConstruct : cti_op_call_NotJSFunction);
     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);
 }
 
     sampleCodeBlock(m_codeBlock);
 }
@@ -592,10 +165,9 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
 {
 
 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;
 
     // 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();
         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.
     }
 
     // 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);
 
 
     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;
 
     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.
 
 
     // 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
     // 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(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);
 
     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);
 
     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)
 {
     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);
 
 
     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);
     // 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);
 
 
     // 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.
 
     // 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);
 
     // 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);
 }
 
     sampleCodeBlock(m_codeBlock);
 }
 
@@ -719,8 +259,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
 
 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
 
 
 #endif // !ENABLE(JIT_OPTIMIZE_CALL)
 
-#endif // USE(JSVALUE32_64)
-
 } // namespace JSC
 
 } // namespace JSC
 
+#endif // USE(JSVALUE64)
 #endif // ENABLE(JIT)
 #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!
         }
 
         // 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()
         }
 
         void* start()
@@ -100,6 +101,12 @@ namespace JSC {
             return JITCode(code.dataLocation(), 0, 0);
         }
 
             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)
     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. */
 
 
 /* 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;
 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)
 {
 
 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)
 {
 }
 
 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);
 }
 
 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)
 {
     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(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);
     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);
 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)
 {
     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();
 
     Call nakedCall = nearCall();
-    m_calls.append(CallRecord(nakedCall, m_bytecodeIndex, function.executableAddress()));
+    m_calls.append(CallRecord(nakedCall, m_bytecodeOffset, function.executableAddress()));
     return nakedCall;
 }
 
     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)
 {
 #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
 #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);
 
 
     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
 #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
 }
 
 #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
 #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
 #endif
+    JSInterfaceJIT::endUninterruptedSequence();
 }
 
 #endif
 }
 
 #endif
@@ -169,6 +194,22 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
     loadPtr(address, linkRegister);
 }
 {
     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)
 
 
 #elif CPU(MIPS)
 
@@ -206,33 +247,28 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 
 #endif
 
 
 #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);
 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.
 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(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
     // In the trampoline on x86-64, the first argument register is not overwritten.
 }
-#endif
 
 ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure)
 {
 
 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)
 }
 
 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)
 {
 
 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)
 {
 }
 
 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)
 
     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)
 {
 }
 
 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)
 {
 }
 
 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)
 }
 
 #if ENABLE(SAMPLING_FLAGS)
@@ -277,14 +313,14 @@ ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag)
 {
     ASSERT(flag >= 1);
     ASSERT(flag <= 32);
 {
     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);
 }
 
 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
 
 }
 #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.
 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.
 #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
 #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)
 {
 #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)
 {
 }
 #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
 }
 #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)
 {
 #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)
 {
 }
 #else
 ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock)
 {
-    storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
+    storePtr(TrustedImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
 }
 #endif
 #endif
 }
 #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)) {
 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);
         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)) {
 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
         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(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(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)
 }
 
 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)
     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)
 }
 
 inline void JIT::emitStoreDouble(unsigned index, FPRegisterID value)
@@ -485,24 +521,24 @@ ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
     emitStore(dst, jsUndefined());
 }
 
     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);
 {
     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;
             return true;
-        if (jumpTarget > bytecodeIndex)
+        if (jumpTarget > bytecodeOffset)
             return false;
     }
     return false;
 }
 
             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;
 
         return;
 
-    m_mappedBytecodeIndex = bytecodeIndex;
+    m_mappedBytecodeOffset = bytecodeOffset;
     m_mappedVirtualRegisterIndex = virtualRegisterIndex;
     m_mappedTag = tag;
     m_mappedPayload = payload;
     m_mappedVirtualRegisterIndex = virtualRegisterIndex;
     m_mappedTag = tag;
     m_mappedPayload = payload;
@@ -518,7 +554,7 @@ inline void JIT::unmap(RegisterID registerID)
 
 inline void JIT::unmap()
 {
 
 inline void JIT::unmap()
 {
-    m_mappedBytecodeIndex = (unsigned)-1;
+    m_mappedBytecodeOffset = (unsigned)-1;
     m_mappedVirtualRegisterIndex = (unsigned)-1;
     m_mappedTag = (RegisterID)-1;
     m_mappedPayload = (RegisterID)-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)
 {
 
 inline bool JIT::isMapped(unsigned virtualRegisterIndex)
 {
-    if (m_mappedBytecodeIndex != m_bytecodeIndex)
+    if (m_mappedBytecodeOffset != m_bytecodeOffset)
         return false;
     if (m_mappedVirtualRegisterIndex != virtualRegisterIndex)
         return false;
         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)
 {
 
 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;
         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)
 {
 
 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;
         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
         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;
 }
 
     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()
 #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)
 {
 // 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)) {
 
     // 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;
     }
 
         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);
     }
 
     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)));
 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)
 {
 }
 
 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)
 }
 
 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
 #if USE(JSVALUE64)
     return branchTestPtr(Zero, reg, tagMaskRegister);
 #else
-    return branchTest32(Zero, reg, Imm32(JSImmediate::TagMask));
+    return branchTest32(Zero, reg, TrustedImm32(TagMask));
 #endif
 }
 
 #endif
 }
 
@@ -729,7 +731,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotJSCell(RegisterID reg)
 #if USE(JSVALUE64)
     return branchTestPtr(NonZero, reg, tagMaskRegister);
 #else
 #if USE(JSVALUE64)
     return branchTestPtr(NonZero, reg, tagMaskRegister);
 #else
-    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagMask));
+    return branchTest32(NonZero, reg, TrustedImm32(TagMask));
 #endif
 }
 
 #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)) {
 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);
         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)) {
 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);
 }
     } 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
 #if USE(JSVALUE64)
     return branchPtr(AboveOrEqual, reg, tagTypeNumberRegister);
 #else
-    return branchTest32(NonZero, reg, Imm32(JSImmediate::TagTypeNumber));
+    return branchTest32(NonZero, reg, TrustedImm32(TagTypeNumber));
 #endif
 }
 
 #endif
 }
 
@@ -779,7 +781,7 @@ ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg)
 #if USE(JSVALUE64)
     return branchPtr(Below, reg, tagTypeNumberRegister);
 #else
 #if USE(JSVALUE64)
     return branchPtr(Below, reg, tagTypeNumberRegister);
 #else
-    return branchTest32(Zero, reg, Imm32(JSImmediate::TagTypeNumber));
+    return branchTest32(Zero, reg, TrustedImm32(TagTypeNumber));
 #endif
 }
 
 #endif
 }
 
@@ -805,15 +807,15 @@ ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg)
     addSlowCase(emitJumpIfNotImmediateNumber(reg));
 }
 
     addSlowCase(emitJumpIfNotImmediateNumber(reg));
 }
 
-#if !USE(JSVALUE64)
+#if USE(JSVALUE32_64)
 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
 {
 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
 {
-    subPtr(Imm32(JSImmediate::TagTypeNumber), reg);
+    subPtr(TrustedImm32(TagTypeNumber), reg);
 }
 
 ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
 {
 }
 
 ALWAYS_INLINE JIT::Jump JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
 {
-    return branchSubPtr(Zero, Imm32(JSImmediate::TagTypeNumber), reg);
+    return branchSubPtr(Zero, TrustedImm32(TagTypeNumber), reg);
 }
 #endif
 
 }
 #endif
 
@@ -824,7 +826,7 @@ ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID d
 #else
     if (src != dest)
         move(src, dest);
 #else
     if (src != dest)
         move(src, dest);
-    addPtr(Imm32(JSImmediate::TagTypeNumber), dest);
+    addPtr(TrustedImm32(TagTypeNumber), dest);
 #endif
 }
 
 #endif
 }
 
@@ -844,25 +846,7 @@ ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID src, RegisterID
 
 ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
 {
 
 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)
 }
 
 #endif // USE(JSVALUE32_64)
index 403a4546e400e0e5ac139c4d7466de071f14c062..4cdd35aa96f48ef84057ad301b7672438b53c9ff 100644 (file)
  */
 
 #include "config.h"
  */
 
 #include "config.h"
-#include "JIT.h"
-
 #if ENABLE(JIT)
 #if ENABLE(JIT)
+#include "JIT.h"
 
 
+#include "Arguments.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #include "JSArray.h"
 
 namespace JSC {
 
 
 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)
 {
 
 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);
 #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);
 
 
     // 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);
 
     // 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.
 
     // VirtualCallLink Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
+    JumpList callLinkFailures;
     Label virtualCallLinkBegin = align();
     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);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callArityCheck2 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callLazyLinkCall = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
     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);
     compileOpCallInitializeCallFrame();
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callLazyLinkCall = call();
+    Call callLazyLinkConstruct = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
 
     // VirtualCall Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
     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();
     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);
     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);
 
     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
 #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)
 
 #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)
 
 #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
-    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
 
     // 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
 
 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
+    UNUSED_PARAM(executableOffsetToFunction);
     breakpoint();
 #endif
 
     breakpoint();
 #endif
 
@@ -406,65 +277,31 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
     loadPtr(&(globalData->exception), regT2);
     Jump exceptionHandler = branchTestPtr(NonZero, regT2);
 
     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.
     // Return.
-    restoreReturnAddressBeforeReturn(regT1);
     ret();
 
     // Handle an exception
     exceptionHandler.link(this);
     ret();
 
     // Handle an exception
     exceptionHandler.link(this);
+
     // Grab the return address.
     // 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)
 }
 
 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)
 {
 
 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))));
     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);
 {
     unsigned target = currentInstruction[1].u.operand;
     addJump(jump(), target);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
 }
 
 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 (isOperandConstantImmediateInt(op2)) {
         emitGetVirtualRegister(op1, regT0);
         emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
         int32_t op2imm = getConstantOperandImmediateInt(op2);
         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);
         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);
 }
 
     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;
 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);
 
     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(regT2, value);
-    emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
     emitJumpSlowCaseIfNotJSCell(regT1, proto);
 
     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'.
     // 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.
 
     // 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.
     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.
     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);
 }
 
 
     // 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++);
 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++);
 }
 
     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_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)
 {
 
 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)
 {
     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)
 {
 }
 
 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);
 
     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);
     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)
 {
     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);
 
     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);
     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)
 {
 }
 
 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);
     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();
     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)
 {
 }
 
 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);
     ASSERT(callFrameRegister != regT1);
     ASSERT(regT1 != returnValueRegister);
     ASSERT(returnValueRegister != callFrameRegister);
@@ -694,31 +552,51 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
     ret();
 }
 
     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);
 }
 
 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);
 }
 
     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;
 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);
     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)
     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)
 {
 
 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.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
     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++;
     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
 
     // 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.
 
     // 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);
 }
     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 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);
     
     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(Imm32(currentIndex));
+    stubCall.addArgument(regT0);
     stubCall.call(dst);
 }
 
 void JIT::emit_op_not(Instruction* currentInstruction)
 {
     emitGetVirtualRegister(currentInstruction[2].u.operand, 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);
 }
 
     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);
 
     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);
 
     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);
 
     isNonZero.link(this);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
 }
 
 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.
     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);
     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);
 
     wasNotImmediate.link(this);
-    RECORD_JUMP_TARGET(target);
 };
 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 {
 };
 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.
     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);
     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);
 
     wasNotImmediate.link(this);
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
 {
     unsigned src = currentInstruction[1].u.operand;
 }
 
 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);
     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;
 }
 
 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();
     addJump(jump(), target);
     m_jsrSites.append(JSRInfo(storeLocation, label()));
     killLastResultRegister();
-    RECORD_JUMP_TARGET(target);
 }
 
 void JIT::emit_op_sret(Instruction* currentInstruction)
 }
 
 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);
 {
     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);
 }
     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);
 {
     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
     emitJumpSlowCaseIfNotImmediateInteger(regT0);
-#if USE(JSVALUE64)
     not32(regT0);
     emitFastArithIntToImmNoCheck(regT0, regT0);
     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);
     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);
 }
     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);
 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);
 }
 
     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);
 
     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(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);
 
     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);
 }
 
 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);
     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));
     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
     }
 
     // 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);
     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);
     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);
 
     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);
     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);
 
 
     // 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);
     loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2);
-#else
-    loadPtr(BaseIndex(regT2, regT0, TimesFour), regT2);
-#endif
 
     emitPutVirtualRegister(dst, regT2);
 
     // Increment i
 
     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
 
     // 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
     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);
     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));
     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)));
     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.
     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)
     addSlowCase(emitJumpIfImmediateNumber(regT2));
 
     if (type == OpStrictEq)
-        set32(Equal, regT1, regT0, regT0);
+        compare32(Equal, regT1, regT0, regT0);
     else
     else
-        set32(NotEqual, regT1, regT0, regT0);
+        compare32(NotEqual, regT1, regT0, regT0);
     emitTagAsBoolImmediate(regT0);
 
     emitPutVirtualRegister(dst);
     emitTagAsBoolImmediate(regT0);
 
     emitPutVirtualRegister(dst);
@@ -1149,8 +1025,8 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
     Jump wasImmediate = emitJumpIfImmediateInteger(regT0);
 
     emitJumpSlowCaseIfNotJSCell(regT0, srcVReg);
     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);
 
     
     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);
 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);
 }
     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.
 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);
 }
 
     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);
     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)
 }
 
 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);
 
     // 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);
     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);
 
     // 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);
     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);
 
     // 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);
 
     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);
 }
 
     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)
 }
 
 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);
 
     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);
 
 
     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);
 
 
     wasNotImmediate.link(this);
 
@@ -1290,21 +1166,20 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction)
     emitGetVirtualRegister(src1, regT0);
     Jump isImmediate = emitJumpIfNotJSCell(regT0);
 
     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);
 
 
     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);
 
     wasNotImmediate.link(this);
 
     emitTagAsBoolImmediate(regT0);
     emitPutVirtualRegister(dst);
-
 }
 
 void JIT::emit_op_enter(Instruction*)
 }
 
 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);
     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();
     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);
 }
     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)
 }
 
 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);
     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)
 {
 }
 
 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);
     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)
 {
 
 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);
     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);
 }
 
     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);
-    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)
 }
 
 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);
 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);
     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();
     stubCall.addArgument(regT0);
     stubCall.addArgument(regT1);
     stubCall.call();
-    xor32(Imm32(0x1), regT0);
+    xor32(TrustedImm32(0x1), regT0);
     emitTagAsBoolImmediate(regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
     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);
 }
 
     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;
 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);
     unsigned proto = currentInstruction[4].u.operand;
 
     linkSlowCaseIfNotJSCell(iter, value);
-    linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
+    linkSlowCase(iter);
     JITStubCall stubCall(this, cti_op_instanceof);
     stubCall.addArgument(value, regT2);
     stubCall.addArgument(baseVal, regT2);
     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);
 }
 
     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)
 {
 
 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);
     
     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()));
     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 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);
     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));
     
     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);
     
     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(Imm32(currentIndex));
+    stubCall.addArgument(regT0);
     stubCall.call(dst);
 }
 
 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
 {
     JITStubCall stubCall(this, cti_op_new_regexp);
     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);
 }
 
     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)
 #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
 #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
 #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)
 #if USE(JSVALUE32_64)
-    m_assembler.mov_r(regT0, regT2);
+        lazyJump = branch32(NotEqual, tagFor(dst), TrustedImm32(JSValue::EmptyValueTag));
 #else
 #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
 #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)
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index ccc0900326f1fa353ce4c5b2e5ddeca523d902da..4f4c5c0b186f7149e96a9368034a7fcab7f29803 100644 (file)
  */
 
 #include "config.h"
  */
 
 #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"
 
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
@@ -41,7 +42,7 @@ namespace JSC {
 
 void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, TrampolineStructure *trampolines)
 {
 
 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
     Label softModBegin = align();
     softModulo();
 #endif
@@ -51,370 +52,426 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable
 
     // regT0 holds payload, regT1 holds tag
 
 
     // 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);
 
 
     // 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(regT2, regT0);
-    move(Imm32(JSValue::Int32Tag), regT1);
+    move(TrustedImm32(JSValue::Int32Tag), regT1);
 
     ret();
 #endif
 
     ret();
 #endif
-
+    
+    JumpList callLinkFailures;
     // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
     // (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();
 #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);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callArityCheck2 = call();
-    move(regT1, callFrameRegister);
-    emitGetJITStubArg(2, regT1); // argCount
+    Call callLazyLinkCall = call();
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
     restoreReturnAddressBeforeReturn(regT3);
     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();
     compileOpCallInitializeCallFrame();
-
     preserveReturnAddressAfterCall(regT3);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
     restoreArgumentReference();
     restoreArgumentReference();
-    Call callLazyLinkCall = call();
+    Call callLazyLinkConstruct = call();
     restoreReturnAddressBeforeReturn(regT3);
     restoreReturnAddressBeforeReturn(regT3);
+    callLinkFailures.append(branchTestPtr(Zero, regT0));
+    emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT1);
     jump(regT0);
     jump(regT0);
+
 #endif // ENABLE(JIT_OPTIMIZE_CALL)
 
     // VirtualCall Trampoline
     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
     Label virtualCallBegin = align();
 #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();
     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);
 
     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);
     preserveReturnAddressAfterCall(regT3);
-    emitPutJITStubArg(regT3, 1); // return address
     restoreArgumentReference();
     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);
     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);
     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();
     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.
     // 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
 #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);
     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);
     ret();
 
     // Handle an exception
     sawException.link(this);
+
     // Grab the return address.
     // Grab the return address.
-    emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
-    move(ImmPtr(&globalData->exceptionLocation), regT2);
+    preserveReturnAddressAfterCall(regT1);
+
+    move(TrustedImmPtr(&globalData->exceptionLocation), regT2);
     storePtr(regT1, regT2);
     storePtr(regT1, regT2);
-    move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
-    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
     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.
 
     // 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)
 }
 
 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);
     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)
 {
     }
 }
 
 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))));
     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);
 
     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);
         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);
         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);
 }
 
     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);
 }
 
     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;
 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);
 
     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(value);
-    emitJumpSlowCaseIfNotJSCell(baseVal);
     emitJumpSlowCaseIfNotJSCell(proto);
     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'.
     // 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.
 
     // 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.
     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.
     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);
 }
 
 
     // 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;
 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);
     unsigned proto = currentInstruction[4].u.operand;
 
     linkSlowCaseIfNotJSCell(iter, value);
-    linkSlowCaseIfNotJSCell(iter, baseVal);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
     linkSlowCaseIfNotJSCell(iter, proto);
     linkSlowCase(iter);
+    linkSlowCase(iter);
 
     JITStubCall stubCall(this, cti_op_instanceof);
     stubCall.addArgument(value);
 
     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);
 }
 
     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;
 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());
     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);
 
     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)
 {
 }
 
 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());
     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);
 
 
     emitLoad(value, regT1, regT0);
 
-    loadPtr(&globalObject->d()->registers, regT2);
+    loadPtr(&globalObject->m_registers, regT2);
     emitStore(index, regT1, regT0, 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;
 }
 
 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);
 
     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);
     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);
 
     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;
 }
 
 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);
     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);
     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);
 
     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)
 {
 }
 
 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);
     JITStubCall stubCall(this, cti_op_tear_off_activation);
     stubCall.addArgument(currentInstruction[1].u.operand);
+    stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand));
     stubCall.call();
     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);
 }
 
 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);
 }
 
     stubCall.call(currentInstruction[1].u.operand);
 }
 
@@ -667,13 +766,13 @@ void JIT::emit_op_to_primitive(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
 
     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);
     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)
 }
 
 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)
 {
 
 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.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);
 }
 
     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;
     // 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++;
 
     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.
 
     // 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.
 
     // 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);
     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 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);
 
     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);
 }
     stubCall.addArgument(Imm32(currentIndex));
     stubCall.call(dst);
 }
@@ -758,9 +864,9 @@ void JIT::emit_op_not(Instruction* currentInstruction)
 
     emitLoadTag(src, regT0);
 
 
     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));
 }
 
     emitStoreBool(dst, regT0, (dst == src));
 }
@@ -784,25 +890,9 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction)
 
     emitLoad(cond, regT1, regT0);
 
 
     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)
 }
 
 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);
     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();
     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);
 
 
     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)
 }
 
 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);
     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();
     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);
 
 
     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.
 
     // 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);
 
 
     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);
 }
 
     wasNotImmediate.link(this);
 }
@@ -891,22 +987,20 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction)
 
     emitLoad(src, regT1, regT0);
 
 
     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.
 
     // 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);
 
 
     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);
 }
 
     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;
 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);
     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;
 }
 
 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()));
 }
     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));
 
     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);
 }
 
     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(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);
 
     // 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);
     stubCallEq.call(regT0);
 
     storeResult.link(this);
-    or32(Imm32(JSValue::FalseTag), regT0);
     emitStoreBool(dst, 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));
 
     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);
 }
 
     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(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);
 
     // 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);
     stubCallEq.call(regT0);
 
     storeResult.link(this);
-    xor32(Imm32(0x1), regT0);
-    or32(Imm32(JSValue::FalseTag), regT0);
+    xor32(TrustedImm32(0x1), regT0);
     emitStoreBool(dst, regT0);
 }
 
     emitStoreBool(dst, regT0);
 }
 
@@ -1052,15 +1142,13 @@ void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqTy
     // cells and/or Int32s.
     move(regT0, regT2);
     and32(regT1, regT2);
     // 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)
 
     if (type == OpStrictEq)
-        set8(Equal, regT0, regT1, regT0);
+        compare32(Equal, regT0, regT1, regT0);
     else
     else
-        set8(NotEqual, regT0, regT1, regT0);
-
-    or32(Imm32(JSValue::FalseTag), regT0);
+        compare32(NotEqual, regT0, regT1, regT0);
 
     emitStoreBool(dst, 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);
     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);
 
 
     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(regT2, regT1);
 
     wasNotImmediate.link(this);
 
-    or32(Imm32(JSValue::FalseTag), regT1);
-
     emitStoreBool(dst, 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);
     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);
 
 
     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);
 
     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);
     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);
 }
     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);
 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);
 }
 
     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))
 
     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
     }
 
     // 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);
     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);
     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);
     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);
     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
 
     // 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);
     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
     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:
 
     // Verify that i is valid:
-    loadPtr(addressFor(base), regT0);
+    loadPtr(payloadFor(base), regT0);
 
     // Test base's structure
 
     // 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
     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);
     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)));
     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.
     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);
 
 
     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);
     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)
 }
 
 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);
 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)
 {
     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.
 
     // 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);
     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)
 }
 
 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);
 
     // 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);
     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);
 
     // 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);
     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);
 
     // 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);
 
     JITStubCall stubCall(this, cti_op_switch_string);
     stubCall.addArgument(scrutinee);
@@ -1414,17 +1502,13 @@ void JIT::emit_op_switch_string(Instruction* currentInstruction)
     jump(regT0);
 }
 
     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(m_codeBlock->getConstant(message));
-    stubCall.addArgument(Imm32(m_bytecodeIndex));
-    stubCall.call(dst);
+    stubCall.call();
 }
 
 void JIT::emit_op_debug(Instruction* currentInstruction)
 }
 
 void JIT::emit_op_debug(Instruction* currentInstruction)
@@ -1451,29 +1535,53 @@ void JIT::emit_op_enter(Instruction*)
         emitStore(i, jsUndefined());
 }
 
         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();
 
     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);
 }
 
     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)
 }
 
 void JIT::emit_op_convert_this(Instruction* currentInstruction)
@@ -1482,12 +1590,32 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction)
 
     emitLoad(thisRegister, regT1, regT0);
 
 
     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)
 }
 
 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);
 }
 
     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*));
 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);
 }
 
     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"
 
 
 #include "config.h"
 
-#if !USE(JSVALUE32_64)
-
-#include "JIT.h"
-
 #if ENABLE(JIT)
 #if ENABLE(JIT)
+#include "JIT.h"
 
 #include "CodeBlock.h"
 #include "GetterSetter.h"
 
 #include "CodeBlock.h"
 #include "GetterSetter.h"
 using namespace std;
 
 namespace JSC {
 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;
 {
     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))));
     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);
     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);
     
     // 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.loadPtr(BaseIndex(regT1, regT0, ScalePtr, 0), regT0);
     jit.ret();
     
     failures.link(&jit);
-    jit.move(Imm32(0), regT0);
+    jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
     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)
 }
 
 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);
 
     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
     // 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);
     // 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);
     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));
 
     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
     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));
     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);
 }
 
     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);
     loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result);
-    finishedLoad.link(this);
 }
 
 void JIT::emit_op_get_by_pname(Instruction* currentInstruction)
 }
 
 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
     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);
     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))));
     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);
 }
 
     emitPutVirtualRegister(dst, regT0);
 }
@@ -211,18 +194,13 @@ void JIT::emit_op_put_by_val(Instruction* currentInstruction)
 
     emitGetVirtualRegisters(base, regT0, property, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
 
     emitGetVirtualRegisters(base, regT0, property, regT1);
     emitJumpSlowCaseIfNotImmediateInteger(regT1);
-#if USE(JSVALUE64)
     // See comment in op_get_by_val.
     zeroExtend32ToPtr(regT1, regT1);
     // See comment in op_get_by_val.
     zeroExtend32ToPtr(regT1, regT1);
-#else
-    emitFastArithImmToInt(regT1);
-#endif
     emitJumpSlowCaseIfNotJSCell(regT0, base);
     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);
     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);
     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);
     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);
 
     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);
 {
     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();
 }
     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);
 {
     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();
 }
     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);
 {
     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();
 }
     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);
 {
     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);
 }
 
     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);
     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++;
     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);
 
     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();
 
     stubCall.addArgument(regT1);
     stubCall.call();
 
@@ -358,20 +336,20 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
 
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
 
 
     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.
 
     // 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();
 
 
     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, 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);
 
     // 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.
     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)
 }
 
 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.
     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)
 }
 
 #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;
     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)
 
     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);
 
 
     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);
 #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);
     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;
 
     // 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);
 
     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);
 
 
     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)
 }
 
 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);
 
     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();
 
     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())
 {
     int offset = cachedOffset * sizeof(JSValue);
     if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage);
+        offset += JSObject::offsetOfInlineStorage();
     else
     else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     storePtr(value, Address(base, offset));
 }
 
     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);
 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)
 }
 
 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));
     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) {
 
     // 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;
     }
 
     Call callTarget;
@@ -626,19 +581,15 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
         stubCall.skipArgument(); // base
         stubCall.skipArgument(); // ident
         stubCall.skipArgument(); // value
         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);
     }
 
         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);
 
     // write the value
     compilePutDirectOffset(regT0, regT1, newStructure, cachedOffset);
@@ -650,7 +601,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
 
     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));
 
 
     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;
 
 
     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);
     // 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)
 }
 
 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;
 
 
     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);
     // 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
     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
 
     // 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();
 
 
     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);
 
     // 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.
     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;
 
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
     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);
 
     // 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;
     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);
         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.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();
 
         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) {
 
     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();
 
 
     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);
 
     // 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.
     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;
 
     // 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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
 
     Jump success = jump();
 
 
     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 (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();
     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);
 
     // 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;
     bucketsOfFail.append(baseObjectCheck);
 
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
         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;
     }
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
     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 (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.
     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);
 
     // 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;
     bucketsOfFail.append(checkStructure(regT0, structure));
 
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
         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;
     }
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     Jump success = jump();
 
     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 (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 // !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)
 } // namespace JSC
 
 #endif // ENABLE(JIT)
-
-#endif // !USE(JSVALUE32_64)
index 059c9c5c9382264503ef6ebd744e58e16787004b..3b3050e0bdd75b9c6c342fc54e38c4c185602e9d 100644 (file)
 
 #include "config.h"
 
 
 #include "config.h"
 
+#if ENABLE(JIT)
 #if USE(JSVALUE32_64)
 #if USE(JSVALUE32_64)
-
 #include "JIT.h"
 
 #include "JIT.h"
 
-#if ENABLE(JIT)
-
 #include "CodeBlock.h"
 #include "JITInlineMethods.h"
 #include "JITStubCall.h"
 #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);
     
     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();
 }
     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);
     
     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();
 }
     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);
     
     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);
 }
 
     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);
     
     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++;
     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);
     
     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();
     
     stubCall.addArgument(value);
     stubCall.call();
     
@@ -215,21 +213,21 @@ void JIT::emit_op_method_check(Instruction* currentInstruction)
     
     BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
     
     
     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.
     
     // 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);
     
     
     END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck);
     
-    move(Imm32(JSValue::CellTag), regT1);
+    move(TrustedImm32(JSValue::CellTag), regT1);
     Jump match = jump();
     
     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);
     
     // 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);
     
     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.
     
     // 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)
 }
 
 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.
     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)
 }
 
 #else //!ENABLE(JIT_OPTIMIZE_METHOD_CALLS)
@@ -269,11 +267,11 @@ void JIT::emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator
 
 #endif
 
 
 #endif
 
-PassRefPtr<NativeExecutable> JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
+JIT::CodePtr JIT::stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool)
 {
     JSInterfaceJIT jit;
     JumpList failures;
 {
     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
     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);
     
     // 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.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.ret();
 
     failures.link(&jit);
-    jit.move(Imm32(0), regT0);
+    jit.move(TrustedImm32(0), regT0);
     jit.ret();
     
     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)
 }
 
 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);
     
     
     emitLoad2(base, regT1, regT0, property, regT3, regT2);
     
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     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);
     
     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)
 }
 
 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 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));
     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);
     
     
     emitLoad2(base, regT1, regT0, property, regT3, regT2);
     
-    addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
     emitJumpSlowCaseIfNotJSCell(base, regT1);
     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);
     
     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);
     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);
     
     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);
     
     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);
     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()
 }
 
 void JIT::compileGetByIdHotPath()
@@ -431,23 +429,19 @@ void JIT::compileGetByIdHotPath()
     m_propertyAccessInstructionIndex++;
     
     DataLabelPtr structureToCompare;
     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);
     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);
     
     Label putResult(this);
-    ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);
+    ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult);
     
     END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath);
 }
     
     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);
 #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);
     
     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;
     
     // 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;
     
     // 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);
     
     
     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)
 }
 
 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);
     
     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();
     
     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())
 {
     int offset = cachedOffset;
     if (structure->isUsingInlineStorage())
-        offset += OBJECT_OFFSETOF(JSObject, m_inlineStorage) /  sizeof(Register);
+        offset += JSObject::offsetOfInlineStorage() /  sizeof(Register);
     else
     else
-        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base);
+        loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_propertyStorage)), base);
     emitStore(offset, valueTag, valuePayload, 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;
 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)
 {
 }
 
 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;
     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. 
     
     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.
     }
 
     // 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.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);
         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);
     // Write the value
     compilePutDirectOffset(regT0, regT2, regT3, newStructure, cachedOffset);
-    
+
     ret();
     
     ASSERT(!failureCases.empty());
     ret();
     
     ASSERT(!failureCases.empty());
@@ -646,7 +643,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     restoreArgumentReferenceForTrampoline();
     Call failureCall = tailRecursiveCall();
     
     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));
     
     
     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;
     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);
     // 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)
 }
 
 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;
     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);
     // 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)
 }
 
 void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
@@ -730,18 +697,18 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress)
     // regT0 holds a JSCell*
     
     // Check for array
     // 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
     
     // 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);
     
     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(regT2, regT0);
-    move(Imm32(JSValue::Int32Tag), regT1);
+    move(TrustedImm32(JSValue::Int32Tag), regT1);
     Jump success = jump();
     
     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);
     
     // 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.
     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;
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
     Jump success = jump();
     
     
     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);
     
     // 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;
     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);
         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.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();
     
         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)
     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();
     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);
     
     // 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.
     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;
     
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
     Jump success = jump();
     
     
     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)
     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();
     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);
     
     // 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;
     bucketsOfFail.append(checkStructure(regT0, structure));
     
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
         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;
     }
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
 
     Jump success = jump();
     
 
     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)
     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.
     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);
     
     // 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;
     bucketsOfFail.append(checkStructure(regT0, structure));
     
     Structure* currStructure = structure;
-    RefPtr<Structure>* chainEntries = chain->head();
+    WriteBarrier<Structure>* it = chain->head();
     JSObject* protoObject = 0;
     JSObject* protoObject = 0;
-    for (unsigned i = 0; i < count; ++i) {
+    for (unsigned i = 0; i < count; ++i, ++it) {
         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
         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;
     }
     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);
         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.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
         stubCall.call();
     } else
-        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
+        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     Jump success = jump();
     
     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)
     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)
 
 
 #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);
     
     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);
     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)
 }
 
 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
     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);
     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))));
     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);
     
     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)
 }
 
 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
 
 
 } // namespace JSC
 
+#endif // USE(JSVALUE32_64)
 #endif // ENABLE(JIT)
 #endif // ENABLE(JIT)
-
-#endif // ENABLE(JSVALUE32_64)
-
index 70d289350bd7674681c8331ed33b20a99f0625dc..a0341d6b44cb7c4228ce2b6c76fcd06ba16a1fae 100644 (file)
@@ -99,13 +99,13 @@ namespace JSC {
             m_stackIndex += stackIndexStep;
         }
 
             m_stackIndex += stackIndexStep;
         }
 
-        void addArgument(JIT::Imm32 argument)
+        void addArgument(JIT::TrustedImm32 argument)
         {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
         }
 
         {
             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;
         {
             m_jit->poke(argument, m_stackIndex);
             m_stackIndex += stackIndexStep;
@@ -167,17 +167,17 @@ namespace JSC {
         JIT::Call call()
         {
 #if ENABLE(OPCODE_SAMPLING)
         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();
 #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 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)
 #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) 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
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
  */
 
 #include "config.h"
-#include "JITStubs.h"
 
 #if ENABLE(JIT)
 
 #if ENABLE(JIT)
+#include "JITStubs.h"
 
 #include "Arguments.h"
 #include "CallFrame.h"
 #include "CodeBlock.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 "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 "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"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.h"
@@ -65,22 +67,26 @@ using namespace std;
 
 namespace JSC {
 
 
 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
 
 #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
 
 #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"
 #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
 #else
-#define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name)
+#define SYMBOL_STRING_RELOCATION(name) #name
 #endif
 
 #if OS(DARWIN)
 #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);
 
 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"
 ".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
@@ -135,23 +141,16 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ret" "\n"
 );
 
     "ret" "\n"
 );
 
-asm volatile (
+asm (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
-#if !USE(JIT_STUB_ARGUMENT_VA_LIST)
     "movl %esp, %ecx" "\n"
     "movl %esp, %ecx" "\n"
-#endif
     "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
     "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"
 ".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)
 
     
 #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);
 // 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);
 
 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"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
@@ -203,23 +198,16 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ret" "\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"
 ".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"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
@@ -233,33 +221,27 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\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)
 
 #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);
 // 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" {
 
 
 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;
     {
         __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"
 
 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"
 );
 
 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"
 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
 
 #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);
 
 // 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"
 ".text\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
@@ -429,23 +436,16 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "ret" "\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"
 ".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"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
 SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
@@ -459,34 +459,14 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
     "ret" "\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
 
 #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"
 ".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"
 ".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
 #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"
 #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"
     "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"
     "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"
 );
 
 ".set reorder" "\n"
 ".set macro" "\n"
 ".end " SYMBOL_STRING(ctiTrampoline) "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".set noreorder" "\n"
 ".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
 ".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"
 ".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
     "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"
     "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"
 );
 
 ".set reorder" "\n"
 ".set macro" "\n"
 ".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".set noreorder" "\n"
 ".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"
 ".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"
     "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"
 );
 ".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
 
-#endif // USE(JSVALUE32_64)
-
 #if COMPILER(GCC) && CPU(ARM_THUMB2)
 
 #if COMPILER(GCC) && CPU(ARM_THUMB2)
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
@@ -716,7 +586,7 @@ SYMBOL_STRING(ctiTrampoline) ":" "\n"
     "bx lr" "\n"
 );
 
     "bx lr" "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
@@ -734,7 +604,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
     "bx lr" "\n"
 );
 
     "bx lr" "\n"
 );
 
-asm volatile(
+asm (
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
 ".text" "\n"
 ".align 2" "\n"
 ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
@@ -752,7 +622,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 
 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
 
 
 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
 
-asm volatile(
+asm (
 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
 HIDE_SYMBOL(ctiTrampoline) "\n"
 SYMBOL_STRING(ctiTrampoline) ":" "\n"
 ".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"
 );
 
     "mov pc, lr" "\n"
 );
 
-asm volatile(
+asm (
 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
 HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
 ".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"
 );
 
     "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)
 #endif
 
 #if ENABLE(OPCODE_SAMPLING)
@@ -796,9 +752,13 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
 #endif
 
 JITThunks::JITThunks(JSGlobalData* globalData)
 #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
 #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, 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);
 
     // 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)
 
 
 #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
 }
 
 #endif
 }
@@ -857,10 +816,10 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co
         return;
     }
     
         return;
     }
     
-    JSCell* baseCell = asCell(baseValue);
+    JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
 
     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;
     }
         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);
         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;
     }
     
         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);
 }
 
     JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress, direct);
 }
@@ -925,10 +884,10 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co
         return;
     }
 
         return;
     }
 
-    JSCell* baseCell = asCell(baseValue);
+    JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
 
     Structure* structure = baseCell->structure();
 
-    if (structure->isUncacheableDictionary()) {
+    if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
         return;
     }
         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.
 
     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);
             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()) {
         // 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());
 
         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);
     }
 
     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)
 
     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" {
 #ifndef NDEBUG
 
 extern "C" {
@@ -1021,13 +974,13 @@ struct StackHack {
     ReturnAddressPtr savedReturnAddress;
 };
 
     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_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()
 
 #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() \
         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 { \
 
 #define CHECK_FOR_EXCEPTION() \
     do { \
@@ -1076,13 +1031,32 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
         } \
     } while (0)
 
         } \
     } 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); \
     }; \
 
 #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" \
         ".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); \
     }; \
     extern "C" { \
         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
     }; \
-    asm volatile( \
+    asm ( \
         ".text" "\n" \
         ".align 2" "\n" \
         ".set noreorder" "\n" \
         ".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" \
         ".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" \
         ".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" \
         "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); \
     }; \
     extern "C" { \
         rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
     }; \
-    asm volatile( \
+    asm ( \
         ".text" "\n" \
         ".align 2" "\n" \
         ".set noreorder" "\n" \
         ".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" \
         ".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" \
         "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" \
         "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); \
     }; \
     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" \
         ".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)
 
         ); \
     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)
 
 
 #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(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(    IMPORT JITStubThunked_#op#)
-RVCT(    str lr, [sp, ##offset#])
+RVCT(    str lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
 RVCT(    bl JITStubThunked_#op#)
 RVCT(    bl JITStubThunked_#op#)
-RVCT(    ldr lr, [sp, ##offset#])
+RVCT(    ldr lr, [sp, # THUNK_RETURN_ADDRESS_OFFSET])
 RVCT(    bx lr)
 RVCT(})
 RVCT()
 RVCT(    bx lr)
 RVCT(})
 RVCT()
@@ -1198,10 +1172,111 @@ RVCT()
 /* Include the generated file */
 #include "GeneratedJITStubs_RVCT.h"
 
 /* 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
 
 #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);
 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);
 }
 
     return JSValue::encode(result);
 }
 
-DEFINE_STUB_FUNCTION(void, op_end)
+DEFINE_STUB_FUNCTION(EncodedJSValue, op_convert_this_strict)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 {
     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)
 }
 
 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))
 
     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);
 
     // 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 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);
 }
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -1279,18 +1357,21 @@ DEFINE_STUB_FUNCTION(int, timeout_check)
     return timeoutChecker.ticksUntilNextCheck();
 }
 
     return timeoutChecker.ticksUntilNextCheck();
 }
 
-DEFINE_STUB_FUNCTION(void, register_file_check)
+DEFINE_STUB_FUNCTION(void*, register_file_check)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 {
     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)
 }
 
 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);
 
 {
     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();
 }
     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);
     
 {
     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();
 }
     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();
     
     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();
     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();
     
     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();
     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();
 
     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();
     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();
     
     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();
     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()
     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
         ) {
 
         && (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())
 
         // 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)) {
 
         // 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);
         }
 
             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) {
         // 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);
         }
     }
             return JSValue::encode(result);
         }
     }
@@ -1536,7 +1617,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail)
 
     if (baseValue.isCell()
         && slot.isCacheable()
 
     if (baseValue.isCell()
         && slot.isCacheable()
-        && !asCell(baseValue)->structure()->isUncacheableDictionary()
+        && !baseValue.asCell()->structure()->isUncacheableDictionary()
         && slot.slotBase() == baseValue) {
 
         CodeBlock* codeBlock = callFrame->codeBlock();
         && 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);
 
         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;
             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++;
         }
         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));
 
             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);
 }
 
     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:
 {
     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:
         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;
         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();
 
 
     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);
     }
 
         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);
 
     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));
 
     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()) {
         // 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;
         }
 
         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);
 
         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)) {
                 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;
         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);
         
         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)
 
 
 #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);
 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()) {
     // 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);
         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()) {
             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();
         }
     }
             VM_THROW_EXCEPTION();
         }
     }
@@ -1793,7 +1888,11 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_del_by_id)
     
     JSObject* baseObj = stackFrame.args[0].jsValue().toObject(callFrame);
 
     
     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);
 }
     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))
     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;
 
     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);
 }
     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);
 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());
 }
 
     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;
 {
     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
 
 #endif
 
-    JSFunction* function = asFunction(stackFrame.args[0].jsValue());
+    JSFunction* function = asFunction(stackFrame.callFrame->callee());
     ASSERT(!function->isHostFunction());
     FunctionExecutable* executable = function->jsExecutable();
     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;
 }
 
     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;
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
-    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
+    JSFunction* callee = asFunction(callFrame->callee());
     ASSERT(!callee->isHostFunction());
     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();
 
 
     ASSERT(argCount != newCodeBlock->m_numParameters);
 
     CallFrame* oldCallFrame = callFrame->callerFrame();
 
+    Register* r;
     if (argCount > newCodeBlock->m_numParameters) {
         size_t numParameters = newCodeBlock->m_numParameters;
     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.
         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];
         }
 
         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;
     } 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.
         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();
         }
 
         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());
     }
 
     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);
 }
 
 #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();
     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;
     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
 
     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)
 
 }
 #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()));
     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;
 }
 
     return activation;
 }
 
@@ -1935,7 +2170,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_NotJSFunction)
     JSValue funcVal = stackFrame.args[0].jsValue();
 
     CallData callData;
     JSValue funcVal = stackFrame.args[0].jsValue();
 
     CallData callData;
-    CallType callType = funcVal.getCallData(callData);
+    CallType callType = getCallData(funcVal, callData);
 
     ASSERT(callType != CallTypeJS);
 
 
     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);
         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);
         {
             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);
 
     }
 
     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();
 }
 
     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);
 {
     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);
 {
     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)
 }
 
 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());
     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)
 }
 
 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());
     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)
 }
 
 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());
 }
 
     (*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);
 
 {
     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);
 {
     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);
 }
 
     return constructArray(stackFrame.callFrame, argList);
 }
 
@@ -2057,7 +2292,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve)
 
     Identifier& ident = stackFrame.args[0].identifier();
     do {
 
     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);
         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);
 
         }
     } 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();
 }
 
     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);
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct)
 {
     STUB_INIT_STACK_FRAME(stackFrame);
 
-    CallFrame* callFrame = stackFrame.callFrame;
-
     JSValue constrVal = stackFrame.args[0].jsValue();
     JSValue constrVal = stackFrame.args[0].jsValue();
-    int argCount = stackFrame.args[2].int32();
-    int thisRegister = stackFrame.args[4].int32();
 
     ConstructData constructData;
 
     ConstructData constructData;
-    ConstructType constructType = constrVal.getConstructData(constructData);
+    ConstructType constructType = getConstructData(constrVal, constructData);
+
+    ASSERT(constructType != ConstructTypeJS);
 
     if (constructType == ConstructTypeHost) {
 
     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);
         {
             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);
 
     }
 
     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();
 }
 
     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));
 
     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.
         // 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);
             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))
     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;
 
     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);
 }
     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))
         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)) {
             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.
     } 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);
         }
     }
             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.
     } 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);
         }
     }
             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();
         }
             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;
         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()) {
 
     } 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();
         }
             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));
             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);
                 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));
             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 {
                 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();
         }
     }
             VM_THROW_EXCEPTION();
         }
     }
@@ -2459,10 +2667,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_negate)
 
     double v;
     if (src.getNumber(v))
 
     double v;
     if (src.getNumber(v))
-        return JSValue::encode(jsNumber(stackFrame.globalData, -v));
+        return JSValue::encode(jsNumber(-v));
 
     CallFrame* callFrame = stackFrame.callFrame;
 
     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);
 }
     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);
 
 {
     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);
 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);
     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 {
     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);
         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);
 
         }
     } 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();
 }
 
     VM_THROW_EXCEPTION();
 }
 
@@ -2512,20 +2751,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
     STUB_INIT_STACK_FRAME(stackFrame);
 
     CallFrame* callFrame = stackFrame.callFrame;
     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) {
     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);
         }
             globalResolveInfo.offset = slot.cachedOffset();
             return JSValue::encode(result);
         }
@@ -2534,8 +2771,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_resolve_global)
         return JSValue::encode(result);
     }
 
         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();
 }
 
     VM_THROW_EXCEPTION();
 }
 
@@ -2549,10 +2785,10 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_div)
     double left;
     double right;
     if (src1.getNumber(left) && src2.getNumber(right))
     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;
 
     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);
 }
     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 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);
 }
     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();
 
     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);
 }
 
     return JSValue::encode(number);
 }
 
@@ -2647,14 +2883,14 @@ DEFINE_STUB_FUNCTION(int, op_eq)
     start:
     if (src2.isUndefined()) {
         return src1.isNull() || 
     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() || 
     }
     
     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()) {
     }
 
     if (src1.isInt32()) {
@@ -2690,27 +2926,27 @@ DEFINE_STUB_FUNCTION(int, op_eq)
     }
     
     if (src1.isUndefined())
     }
     
     if (src1.isUndefined())
-        return src2.isCell() && asCell(src2)->structure()->typeInfo().masqueradesAsUndefined();
+        return src2.isCell() && src2.asCell()->structure()->typeInfo().masqueradesAsUndefined();
     
     if (src1.isNull())
     
     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())
 
     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())
             
         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())
 
         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())
 
         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);
 
         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 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);
 }
     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;
 
     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);
 }
     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 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);
 
     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;
 
     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);
 }
     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 {
     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);
         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);
 
         ++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());
 }
     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());
 
     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
 
     /* 
         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);
      */
     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;
     }
 
     return func;
@@ -2874,7 +3109,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_mod)
 
     CallFrame* callFrame = stackFrame.callFrame;
     double d = dividendValue.toNumber(callFrame);
 
     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);
 }
     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();
 
     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);
 }
 
     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 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);
 }
     CHECK_FOR_EXCEPTION_AT_END();
     return JSValue::encode(result);
 }
@@ -2926,7 +3161,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
 
     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);
 }
     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);
 
 {
     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)
 }
 
 DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
@@ -2947,7 +3190,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor)
 
     CallFrame* callFrame = stackFrame.callFrame;
 
 
     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);
 }
     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);
 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;
 
     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;
 
     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());
 }
 
         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);
 {
     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)
 }
 
 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()) {
     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();
     }
 
         VM_THROW_EXCEPTION();
     }
 
@@ -3247,7 +3465,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_char)
     void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress();
 
     if (scrutinee.isString()) {
     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();
     }
         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()) {
     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();
     }
 
         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();
     JSObject* baseObj = baseValue.toObject(callFrame); // may throw
 
     JSValue subscript = stackFrame.args[1].jsValue();
-    JSValue result;
+    bool result;
     uint32_t i;
     if (subscript.getUInt32(i))
     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();
     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();
     CHECK_FOR_EXCEPTION_AT_END();
-    return JSValue::encode(result);
+    return JSValue::encode(jsBoolean(result));
 }
 
 DEFINE_STUB_FUNCTION(void, op_put_getter)
 }
 
 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()));
 }
 
     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;
 {
     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)
 }
 
 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);
 }
 
     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);
 {
     STUB_INIT_STACK_FRAME(stackFrame);
-
-    CallFrame* callFrame = stackFrame.callFrame;
-    CodeBlock* codeBlock = callFrame->codeBlock();
     JSGlobalData* globalData = stackFrame.globalData;
     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)
 }
 
 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));
 }
 
     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();
 }
 
     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)
 } // namespace JSC
 
 #endif // ENABLE(JIT)
index 0ad9a99979a2be4d37a89af523efa2b9aff4cc39..75fbb089ec9388be1c2022208f3a517109a39011 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2008 Apple Inc. All rights reserved.
 /*
  * 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
  *
  * 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
 
 #ifndef JITStubs_h
 #define JITStubs_h
 
+#include "CallData.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Register.h"
 #include "ThunkGenerators.h"
 #include "MacroAssemblerCodeRef.h"
 #include "Register.h"
 #include "ThunkGenerators.h"
@@ -57,6 +59,8 @@ namespace JSC {
     class RegisterFile;
     class RegExp;
 
     class RegisterFile;
     class RegExp;
 
+    template <typename T> class Weak;
+
     union JITStubArg {
         void* asPointer;
         EncodedJSValue asEncodedJSValue;
     union JITStubArg {
         void* asPointer;
         EncodedJSValue asEncodedJSValue;
@@ -78,8 +82,11 @@ namespace JSC {
     struct TrampolineStructure {
         MacroAssemblerCodePtr ctiStringLengthTrampoline;
         MacroAssemblerCodePtr ctiVirtualCallLink;
     struct TrampolineStructure {
         MacroAssemblerCodePtr ctiStringLengthTrampoline;
         MacroAssemblerCodePtr ctiVirtualCallLink;
+        MacroAssemblerCodePtr ctiVirtualConstructLink;
         MacroAssemblerCodePtr ctiVirtualCall;
         MacroAssemblerCodePtr ctiVirtualCall;
-        RefPtr<NativeExecutable> ctiNativeCallThunk;
+        MacroAssemblerCodePtr ctiVirtualConstruct;
+        MacroAssemblerCodePtr ctiNativeCall;
+        MacroAssemblerCodePtr ctiNativeConstruct;
         MacroAssemblerCodePtr ctiSoftModulo;
     };
 
         MacroAssemblerCodePtr ctiSoftModulo;
     };
 
@@ -92,7 +99,7 @@ namespace JSC {
         void* code;
         RegisterFile* registerFile;
         CallFrame* callFrame;
         void* code;
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
 
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
 
@@ -128,7 +135,7 @@ namespace JSC {
         void* code;
         RegisterFile* registerFile;
         CallFrame* callFrame;
         void* code;
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
         
         Profiler** enabledProfilerReference;
         JSGlobalData* globalData;
         
@@ -140,10 +147,10 @@ namespace JSC {
 #endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC))
 #elif CPU(ARM_THUMB2)
     struct JITStackFrame {
 #endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC))
 #elif CPU(ARM_THUMB2)
     struct JITStackFrame {
-        void* reserved; // Unused
+        JITStubArg reserved; // Unused
         JITStubArg args[6];
         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;
 #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;
         // 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;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
@@ -167,6 +172,10 @@ namespace JSC {
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
 #elif CPU(ARM_TRADITIONAL)
         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];
     struct JITStackFrame {
         JITStubArg padding; // Unused
         JITStubArg args[7];
@@ -182,7 +191,7 @@ namespace JSC {
 
         RegisterFile* registerFile;
         CallFrame* callFrame;
 
         RegisterFile* registerFile;
         CallFrame* callFrame;
-        JSValue* exception;
+        void* unused1;
 
         // These arguments passed on the stack.
         Profiler** enabledProfilerReference;
 
         // 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; }
     };
         // 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 {
 #elif CPU(MIPS)
     struct JITStackFrame {
-        void* reserved; // Unused
+        JITStubArg reserved; // Unused
         JITStubArg args[6];
 
         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;
         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;
         // 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;
 
 
         // 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
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
 #else
@@ -221,48 +258,24 @@ namespace JSC {
 
 #define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*))
 
 
 #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)
     #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
     #define JIT_STUB __fastcall
-    #elif CPU(X86) && COMPILER(GCC)
+    #elif COMPILER(GCC)
     #define JIT_STUB  __attribute__ ((fastcall))
     #else
     #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
-#endif
-
-#if CPU(X86_64)
-    struct VoidPtrPair {
-        void* first;
-        void* second;
-    };
-    #define RETURN_POINTER_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair
 #else
 #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();
 #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:
 
     class JITThunks {
     public:
@@ -274,14 +287,25 @@ namespace JSC {
 
         MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; }
         MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; }
 
         MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; }
         MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; }
+        MacroAssemblerCodePtr ctiVirtualConstructLink() { return m_trampolineStructure.ctiVirtualConstructLink; }
         MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
         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; }
 
         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:
     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;
         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_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(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_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_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_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);
     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_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);
     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_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_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);
     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_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);
     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);
     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);
     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);
     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);
     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_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_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_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_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
 } // 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 "JITCode.h"
 #include "JITStubs.h"
-#include "JSImmediate.h"
+#include "JSValue.h"
 #include "MacroAssembler.h"
 #include "RegisterFile.h"
 #include <wtf/AlwaysInline.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 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
 
 #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 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);
 #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
 
 #endif
 
-#if USE(JSVALUE32) || USE(JSVALUE64)
+#if USE(JSVALUE64)
         Jump emitJumpIfImmediateNumber(RegisterID reg);
         Jump emitJumpIfNotImmediateNumber(RegisterID reg);
         void emitFastArithImmToInt(RegisterID reg);
 #endif
 
         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 {
     };
 
     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); }
     };
         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);
     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);
     }
     
     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);
     }
 
     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();
         loadPtr(payloadFor(virtualRegisterIndex), scratch);
         convertInt32ToDouble(scratch, dst);
         Jump done = jump();
@@ -273,46 +322,29 @@ namespace JSC {
     
 #endif
 
     
 #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
 
     }
 #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_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)
         }
         
         void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
@@ -61,7 +61,7 @@ namespace JSC {
         void loadJSStringArgument(int argument, RegisterID dst)
         {
             loadCellArgument(argument, dst);
         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))));
         }
         
             m_failures.append(branchTest32(NonZero, Address(dst, OBJECT_OFFSETOF(JSString, m_fiberCount))));
         }
         
@@ -87,7 +87,7 @@ namespace JSC {
         {
             if (src != regT0)
                 move(src, regT0);
         {
             if (src != regT0)
                 move(src, regT0);
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
         
             ret();
         }
         
@@ -96,16 +96,12 @@ namespace JSC {
 #if USE(JSVALUE64)
             moveDoubleToPtr(src, regT0);
             subPtr(tagTypeNumberRegister, regT0);
 #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);
             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
 #endif
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
 
             ret();
         }
 
@@ -114,7 +110,7 @@ namespace JSC {
             if (src != regT0)
                 move(src, regT0);
             tagReturnAsInt32();
             if (src != regT0)
                 move(src, regT0);
             tagReturnAsInt32();
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
 
             ret();
         }
 
@@ -123,15 +119,15 @@ namespace JSC {
             if (src != regT0)
                 move(src, regT0);
             tagReturnAsJSCell();
             if (src != regT0)
                 move(src, regT0);
             tagReturnAsJSCell();
-            loadPtr(Address(callFrameRegister, RegisterFile::CallerFrame * (int)sizeof(Register)), callFrameRegister);
+            loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
             ret();
         }
         
             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:
         }
         
     private:
@@ -144,20 +140,15 @@ namespace JSC {
         {
 #if USE(JSVALUE64)
             orPtr(tagTypeNumberRegister, regT0);
         {
 #if USE(JSVALUE64)
             orPtr(tagTypeNumberRegister, regT0);
-#elif USE(JSVALUE32_64)
-            move(Imm32(JSValue::Int32Tag), regT1);
 #else
 #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)
 #endif
         }
 
         void tagReturnAsJSCell()
         {
 #if USE(JSVALUE32_64)
-            move(Imm32(JSValue::CellTag), regT1);
+            move(TrustedImm32(JSValue::CellTag), regT1);
 #endif
         }
         
 #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)
 {
 
 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));
 }
 
     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);
 {
     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);
 {
     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);
 {
     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())
     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);
 
     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;
 
 }
 
 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())
     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.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 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.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.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);
 
     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);
         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);
 
         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)
 #define ThunkGenerators_h
 
 #if ENABLE(JIT)
-#include <wtf/PassRefPtr.h>
-
 namespace JSC {
     class ExecutablePool;
     class JSGlobalData;
     class NativeExecutable;
 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
 
 }
 #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 "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 "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>
 #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 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)
 
 #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 {
 #endif
 
 struct Script {
@@ -141,142 +144,155 @@ long StopWatch::getElapsedMS()
 
 class GlobalObject : public JSGlobalObject {
 public:
 
 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);
 
     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)
 
 #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]));
 #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(' ');
 
         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);
     }
 
     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();
 {
     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
 {
     // 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))
     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();
 
     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))
     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)
 
     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))
     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();
 
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+
+    StopWatch stopWatch;
+    stopWatch.start();
     Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
     Completion result = checkSyntax(globalObject->globalExec(), makeSource(script.data(), fileName));
+    stopWatch.stop();
+
     if (result.complType() == Throw)
     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)
 }
 
 #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);
     }
         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);
     }
         if ((flag >= 1) && (flag <= 32))
             SamplingFlags::clearFlag(flag);
     }
-    return jsNull();
+    return JSValue::encode(jsNull());
 }
 #endif
 
 }
 #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;
 {
     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');
         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
 {
     // 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.
 
 #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
 }
 
 #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.
 
 // 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
 #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)
 {
 
 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);
     _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
 
     _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
 #endif
 
-#if COMPILER(MSVC) && !OS(WINCE)
     timeBeginPeriod(1);
 #endif
 
     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;
     // 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)
     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);
 static void cleanupGlobalData(JSGlobalData* globalData)
 {
     JSLock lock(SilenceAssertionsOnly);
+    globalData->clearBuiltinStructures();
     globalData->heap.destroy();
     globalData->deref();
 }
     globalData->heap.destroy();
     globalData->deref();
 }
@@ -371,7 +395,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
     if (dump)
         BytecodeGenerator::setDumpsGeneratedCode(true);
 
     if (dump)
         BytecodeGenerator::setDumpsGeneratedCode(true);
 
-    JSGlobalData* globalData = globalObject->globalData();
+    JSGlobalData& globalData = globalObject->globalData();
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::start();
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::start();
@@ -389,27 +413,30 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
             fileName = "[Command Line]";
         }
 
             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)
 
         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
             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
         globalObject->globalExec()->clearException();
     }
 
 #if ENABLE(SAMPLING_FLAGS)
     SamplingFlags::stop();
 #endif
-    globalData->dumpSampleData(globalObject->globalExec());
+    globalData.dumpSampleData(globalObject->globalExec());
 #if ENABLE(SAMPLING_COUNTERS)
     AbstractSamplingCounter::dump();
 #if ENABLE(SAMPLING_COUNTERS)
     AbstractSamplingCounter::dump();
+#endif
+#if ENABLE(REGEXP_TRACING)
+    globalData.dumpRegExpTrace();
 #endif
     return success;
 }
 #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)
         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
         else
-            printf("%s\n", completion.value().toString(globalObject->globalExec()).UTF8String().data());
+            printf("%s\n", completion.value().toString(globalObject->globalExec()).utf8().data());
 
         globalObject->globalExec()->clearException();
     }
 
         globalObject->globalExec()->clearException();
     }
@@ -525,7 +552,7 @@ int jscmain(int argc, char** argv, JSGlobalData* globalData)
     Options options;
     parseArguments(argc, argv, options, 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);
     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)
 {
 
 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) {
     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;
     }
 
         return false;
     }
 
@@ -556,5 +583,8 @@ static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>&
     fclose(f);
     buffer[bufferSize] = '\0';
 
     fclose(f);
     buffer[bufferSize] = '\0';
 
+    if (buffer[0] == '#' && buffer[1] == '!')
+        buffer[0] = buffer[1] = '/';
+
     return true;
 }
     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)
 
 isEmpty(OUTPUT_DIR): OUTPUT_DIR= ..
 include($$PWD/../WebKit.pri)
 
-CONFIG += link_pkgconfig
+unix:!mac:!symbian:CONFIG += link_pkgconfig
 
 QMAKE_RPATHDIR += $$OUTPUT_DIR/lib
 
 
 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)
 OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP}
 include($$PWD/JavaScriptCore.pri)
-addJavaScriptCoreLib(.)
+prependJavaScriptCoreLib(.)
 
 symbian {
     TARGET.CAPABILITY = ReadUserData WriteUserData NetworkServices
 
 symbian {
     TARGET.CAPABILITY = ReadUserData WriteUserData NetworkServices
@@ -30,4 +25,16 @@ symbian {
 
 mac {
     LIBS_PRIVATE += -framework AppKit
 
 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 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
 
 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) 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
  *
  *  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 "Lexer.h"
 
 #include "JSFunction.h"
+
 #include "JSGlobalObjectFunctions.h"
 #include "JSGlobalObjectFunctions.h"
+#include "Identifier.h"
 #include "NodeInfo.h"
 #include "Nodes.h"
 #include "dtoa.h"
 #include "NodeInfo.h"
 #include "Nodes.h"
 #include "dtoa.h"
 using namespace WTF;
 using namespace Unicode;
 
 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 {
 
 #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)
 
 Lexer::Lexer(JSGlobalData* globalData)
     : m_isReparsing(false)
@@ -59,77 +234,17 @@ Lexer::~Lexer()
     m_keywordTable.deleteTable();
 }
 
     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;
 }
 
 {
     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();
 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);
 
     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());
 }
 
     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));
 
 }
 
 void Lexer::shiftLineTerminator()
 {
     ASSERT(isLineTerminator(m_current));
 
+    int m_prev = m_current;
+    shift();
+
     // Allow both CRLF and LFCR.
     // 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;
 }
 
 
     ++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;
 }
 {
     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)
 {
 
 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)
 }
 
 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);
 }
 
         | 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) {
 }
 
 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)));
 }
 
     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());
 
 {
     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))
     m_terminator = false;
 
 start:
     while (isWhiteSpace(m_current))
-        shift1();
+        shift();
 
     int startOffset = currentOffset();
 
 
     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;
 
     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;
                 }
                     token = URSHIFTEQUAL;
                     break;
                 }
-                shift3();
                 token = URSHIFT;
                 break;
             }
                 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;
             }
                 break;
             }
-            shift1();
-            token = '>';
+            token = RSHIFT;
             break;
             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;
             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;
             }
                 break;
             }
-            shift1();
-            token = '!';
+            token = EQEQ;
             break;
             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;
             }
                 break;
             }
-            shift1();
-            token = '<';
+            token = LSHIFT;
             break;
             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;
             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;
             }
                 break;
             }
-            shift1();
-            token = '-';
+            token = NE;
             break;
             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;
             break;
-        case '/':
-            if (m_next1 == '/') {
-                shift2();
+        }
+        token = PLUS;
+        break;
+    case CharacterSub:
+        shift();
+        if (m_current == '-') {
+            shift();
+            if (m_atLineStart && m_current == '>') {
+                shift();
                 goto inSingleLineComment;
             }
                 goto inSingleLineComment;
             }
-            if (m_next1 == '*')
-                goto inMultiLineComment;
-            if (m_next1 == '=') {
-                shift2();
-                token = DIVEQUAL;
-                break;
-            }
-            shift1();
-            token = '/';
+            token = (!m_terminator) ? MINUSMINUS : AUTOMINUSMINUS;
             break;
             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;
             break;
-        case '^':
-            if (m_next1 == '=') {
-                shift2();
-                token = XOREQUAL;
-                break;
-            }
-            shift1();
-            token = '^';
+        }
+        token = MINUS;
+        break;
+    case CharacterMultiply:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = MULTEQUAL;
             break;
             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;
             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;
             break;
-        case '.':
-            if (isASCIIDigit(m_next1)) {
-                record8('.');
-                shift1();
-                goto inNumberAfterDecimalPoint;
-            }
-            token = '.';
-            shift1();
+        }
+        if (m_current == '=') {
+            shift();
+            token = ANDEQUAL;
             break;
             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;
             break;
-        case ';':
-            shift1();
-            m_delimited = true;
-            token = ';';
+        }
+        token = BITXOR;
+        break;
+    case CharacterModulo:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = MODEQUAL;
             break;
             break;
-        case '{':
-            lvalp->intValue = currentOffset();
-            shift1();
-            token = OPENBRACE;
+        }
+        token = MOD;
+        break;
+    case CharacterOr:
+        shift();
+        if (m_current == '=') {
+            shift();
+            token = OREQUAL;
             break;
             break;
-        case '}':
-            lvalp->intValue = currentOffset();
-            shift1();
-            m_delimited = true;
-            token = CLOSEBRACE;
+        }
+        if (m_current == '|') {
+            shift();
+            token = OR;
             break;
             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;
             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();
         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;
         goto returnError;
-    token = convertUnicode(m_current, m_next1, m_next2, m_next3);
-    if (UNLIKELY(!isIdentStart(token)))
+    default:
+        ASSERT_NOT_REACHED();
         goto returnError;
         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))
 
 inSingleLineComment:
     while (!isLineTerminator(m_current)) {
         if (UNLIKELY(m_current == -1))
-            return 0;
-        shift1();
+            return EOFTOK;
+        shift();
     }
     shiftLineTerminator();
     m_atLineStart = true;
     m_terminator = true;
     }
     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;
     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.
 
     // 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;
     m_lastToken = token;
     return token;
-}
 
 returnError:
     m_error = true;
 
 returnError:
     m_error = true;
-    return -1;
+    return ERRORTOK;
 }
 
 bool Lexer::scanRegExp(const Identifier*& pattern, const Identifier*& flags, UChar patternPrefix)
 }
 
 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;
         }
 
             return false;
         }
 
-        shift1();
+        shift();
 
         if (current == '/' && !lastWasEscape && !inBrackets)
             break;
 
         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);
 
     while (isIdentPart(m_current)) {
         record16(m_current);
-        shift1();
+        shift();
     }
 
     flags = makeIdentifier(m_buffer16.data(), m_buffer16.size());
     }
 
     flags = makeIdentifier(m_buffer16.data(), m_buffer16.size());
@@ -975,7 +1206,7 @@ bool Lexer::skipRegExp()
         if (isLineTerminator(current) || current == -1)
             return false;
 
         if (isLineTerminator(current) || current == -1)
             return false;
 
-        shift1();
+        shift();
 
         if (current == '/' && !lastWasEscape && !inBrackets)
             break;
 
         if (current == '/' && !lastWasEscape && !inBrackets)
             break;
@@ -999,7 +1230,7 @@ bool Lexer::skipRegExp()
     }
 
     while (isIdentPart(m_current))
     }
 
     while (isIdentPart(m_current))
-        shift1();
+        shift();
 
     return true;
 }
 
     return true;
 }
@@ -1007,7 +1238,6 @@ bool Lexer::skipRegExp()
 void Lexer::clear()
 {
     m_arena = 0;
 void Lexer::clear()
 {
     m_arena = 0;
-    m_codeWithoutBOMs.clear();
 
     Vector<char> newBuffer8;
     m_buffer8.swap(newBuffer8);
 
     Vector<char> newBuffer8;
     m_buffer8.swap(newBuffer8);
@@ -1020,26 +1250,8 @@ void Lexer::clear()
 
 SourceCode Lexer::sourceCode(int openBrace, int closeBrace, int firstLine)
 {
 
 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);
 }
 
     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) 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
  *
  *  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
 
 #ifndef Lexer_h
 #define Lexer_h
 
+#include "JSParser.h"
 #include "Lookup.h"
 #include "ParserArena.h"
 #include "SourceCode.h"
 #include <wtf/ASCIICType.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>
 #include <wtf/SegmentedVector.h>
 #include <wtf/Vector.h>
 #include <wtf/unicode/Unicode.h>
@@ -34,7 +37,8 @@ namespace JSC {
 
     class RegExp;
 
 
     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);
     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; }
         // 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.
 
         // 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; }
         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);
         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();
         // 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;
 
     private:
         friend class JSGlobalData;
@@ -64,28 +99,40 @@ namespace JSC {
         Lexer(JSGlobalData*);
         ~Lexer();
 
         Lexer(JSGlobalData*);
         ~Lexer();
 
-        void shift1();
-        void shift2();
-        void shift3();
-        void shift4();
-        void shiftLineTerminator();
-
         void record8(int);
         void record16(int);
         void record16(UChar);
 
         void copyCodeWithoutBOMs();
 
         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;
 
         static const size_t initialReadBufferCapacity = 32;
 
         int m_lineNumber;
+        int m_lastLineNumber;
 
         Vector<char> m_buffer8;
         Vector<UChar> m_buffer16;
 
         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;
 
         // 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;
         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;
     }
     {
         return ch == '\r' || ch == '\n' || (ch & ~1) == 0x2028;
     }
@@ -135,11 +177,54 @@ namespace JSC {
     {
         return (convertHex(c1, c2) << 8) | convertHex(c3, c4);
     }
     {
         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
     }
 
 } // namespace JSC
index dd3b9816f657f77d8514c5096c28ecf8ed31ffd1..4e094b6e9b99693e8b49d1b29953d40c8a037d83 100644 (file)
@@ -43,7 +43,7 @@ namespace JSC {
     }
 
     inline Node::Node(JSGlobalData* globalData)
     }
 
     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);
 }
 
     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;
 {
     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::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)
 {
     : 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_varStack.swap(*varStack);
     if (funcStack)
         m_functionStack.swap(*funcStack);
+    m_capturedVariables.swap(capturedVariables);
 }
 
 // ------------------------------ ScopeNode -----------------------------
 
 }
 
 // ------------------------------ ScopeNode -----------------------------
 
-ScopeNode::ScopeNode(JSGlobalData* globalData)
+ScopeNode::ScopeNode(JSGlobalData* globalData, bool inStrictContext)
     : StatementNode(globalData)
     , ParserArenaRefCounted(globalData)
     : 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)
     : 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)
 {
     , m_features(features)
     , m_source(source)
 {
@@ -111,14 +112,14 @@ StatementNode* ScopeNode::singleStatement() const
 
 // ------------------------------ ProgramNode -----------------------------
 
 
 // ------------------------------ 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();
 
     ASSERT(node->data()->m_arena.last() == node);
     node->data()->m_arena.removeLast();
@@ -129,14 +130,14 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem
 
 // ------------------------------ EvalNode -----------------------------
 
 
 // ------------------------------ 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();
 
     ASSERT(node->data()->m_arena.last() == node);
     node->data()->m_arena.removeLast();
@@ -153,13 +154,13 @@ FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
         append(parameter->ident());
 }
 
         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;
 }
 
     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();
 
     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 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,
 
     enum Operator {
         OpEqual,
@@ -81,6 +85,8 @@ namespace JSC {
         OpLogicalOr
     };
 
         OpLogicalOr
     };
 
+    typedef HashSet<RefPtr<StringImpl>, IdentifierRepHash> IdentifierSet;
+
     namespace DeclarationStacks {
         enum VarAttrs { IsConstant = 1, HasInitializer = 2 };
         typedef Vector<std::pair<const Identifier*, unsigned> > VarStack;
     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 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(); }
         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:
         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;
 
     private:
         uint32_t m_divot;
@@ -404,12 +409,13 @@ namespace JSC {
 
     class PropertyNode : public ParserArenaFreeable {
     public:
 
     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; }
 
         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;
 
     private:
         friend class PropertyListNode;
@@ -805,6 +811,9 @@ namespace JSC {
 
         RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0);
 
 
         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);
 
     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);
     class SubNode : public BinaryOpNode {
     public:
         SubNode(JSGlobalData*, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments);
+
+        virtual bool isSubtract() const { return true; }
     };
 
     class LeftShiftNode : public BinaryOpNode {
     };
 
     class LeftShiftNode : public BinaryOpNode {
@@ -1142,6 +1153,7 @@ namespace JSC {
     public:
         BlockNode(JSGlobalData*, SourceElements* = 0);
 
     public:
         BlockNode(JSGlobalData*, SourceElements* = 0);
 
+        StatementNode* singleStatement() const;
         StatementNode* lastStatement() const;
 
     private:
         StatementNode* lastStatement() const;
 
     private:
@@ -1293,6 +1305,8 @@ namespace JSC {
     public:
         ReturnNode(JSGlobalData*, ExpressionNode* value);
 
     public:
         ReturnNode(JSGlobalData*, ExpressionNode* value);
 
+        ExpressionNode* value() { return m_value; }
+
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
     private:
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0);
 
@@ -1362,17 +1376,20 @@ namespace JSC {
         ParameterNode* m_next;
     };
 
         ParameterNode* m_next;
     };
 
-    struct ScopeNodeData : FastAllocBase {
+    struct ScopeNodeData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
         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;
 
         ParserArena m_arena;
         VarStack m_varStack;
         FunctionStack m_functionStack;
         int m_numConstants;
         SourceElements* m_statements;
+        IdentifierSet m_capturedVariables;
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
     };
 
     class ScopeNode : public StatementNode, public ParserArenaRefCounted {
@@ -1380,8 +1397,8 @@ namespace JSC {
         typedef DeclarationStacks::VarStack VarStack;
         typedef DeclarationStacks::FunctionStack FunctionStack;
 
         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;
 
 
         using ParserArenaRefCounted::operator new;
 
@@ -1396,10 +1413,15 @@ namespace JSC {
         CodeFeatures features() { return m_features; }
 
         bool usesEval() const { return m_features & EvalFeature; }
         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; }
         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; }
 
         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:
 
     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:
 
         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:
 
         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:
 
         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> {
 
         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)); }
 
     public:
         static PassRefPtr<FunctionParameters> create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); }
 
@@ -1459,8 +1484,9 @@ namespace JSC {
 
     class FunctionBodyNode : public ScopeNode {
     public:
 
     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(); }
 
         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:
         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;
 
         Identifier m_ident;
         RefPtr<FunctionParameters> m_parameters;
index 039fc46fec9a2f2ffae30ec2ad3f95d84d4fcb5e..fc1e986683ee6dce40932af61bbf93633b8e978b 100644 (file)
 #include "Parser.h"
 
 #include "Debugger.h"
 #include "Parser.h"
 
 #include "Debugger.h"
+#include "JSParser.h"
 #include "Lexer.h"
 #include "Lexer.h"
-#include <wtf/HashSet.h>
-#include <wtf/Vector.h>
-
-#ifndef yyparse
-extern int jscyyparse(void*);
-#endif
 
 namespace JSC {
 
 
 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;
     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);
 
     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();
     int lineNumber = lexer.lineNumber();
+    bool lexError = lexer.sawError();
     lexer.clear();
 
     if (parseError || lexError) {
         *errLine = lineNumber;
     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, 
         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_sourceElements = sourceElements;
     m_varDeclarations = varStack;
     m_funcDeclarations = funcStack;
+    m_capturedVariables.swap(capturedVars);
     m_features = features;
     m_lastLine = lastLine;
     m_numConstants = numConstants;
     m_features = features;
     m_lastLine = lastLine;
     m_numConstants = numConstants;
index 894f709828e50217d13be2134efeae0eb4fc660a..58398d1d3335f164b5225c0cce7c59dffe6e1982 100644 (file)
@@ -24,6 +24,7 @@
 #define Parser_h
 
 #include "Debugger.h"
 #define Parser_h
 
 #include "Debugger.h"
+#include "ExceptionHelpers.h"
 #include "Executable.h"
 #include "JSGlobalObject.h"
 #include "Lexer.h"
 #include "Executable.h"
 #include "JSGlobalObject.h"
 #include "Lexer.h"
 namespace JSC {
 
     class FunctionBodyNode;
 namespace JSC {
 
     class FunctionBodyNode;
+    
     class ProgramNode;
     class UString;
 
     template <typename T> struct ParserArenaData : ParserArenaDeletable { T data; };
 
     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:
     public:
+        Parser() { }
         template <class ParsedNode>
         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>*, 
 
         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:
 
         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;
 
         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>
         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)
         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) {
 
         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);
             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();
         }
 
         m_arena.reset();
@@ -94,7 +121,7 @@ namespace JSC {
         m_funcDeclarations = 0;
 
         if (debugger && !ParsedNode::scopeIsFunction)
         m_funcDeclarations = 0;
 
         if (debugger && !ParsedNode::scopeIsFunction)
-            debugger->sourceParsed(debuggerExecState, source, *errLine, *errMsg);
+            debugger->sourceParsed(debuggerExecState, source.provider(), errLine, errMsg);
         return result.release();
     }
 
         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
  *
  * 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 "ParserArena.h"
 
 #include "Nodes.h"
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
 ParserArena::ParserArena()
     : m_freeableMemory(0)
     , m_freeablePoolEnd(0)
 
 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 ParserArenaDeletable;
     class ParserArenaRefCounted;
 
-    class IdentifierArena : public FastAllocBase {
+    class IdentifierArena {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
     public:
+        IdentifierArena()
+        {
+            clear();
+        }
+
         ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length);
         const Identifier& makeNumericIdentifier(JSGlobalData*, double number);
 
         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:
         bool isEmpty() const { return m_identifiers.isEmpty(); }
 
     private:
+        static const int MaximumCachableCharacter = 128;
         typedef SegmentedVector<Identifier, 64> IdentifierVector;
         IdentifierVector m_identifiers;
         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)
     {
     };
 
     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, 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();
     }
 
         return m_identifiers.last();
     }
 
-    class ParserArena : Noncopyable {
+    class ParserArena {
+        WTF_MAKE_NONCOPYABLE(ParserArena);
     public:
         ParserArena();
         ~ParserArena();
     public:
         ParserArena();
         ~ParserArena();
index 1c59eeda406b1223be80588a5db635085d7cd6f5..e9b6b5614ed967e19d0f7f14d7307504ea43a2cd 100644 (file)
 #ifndef SourceProvider_h
 #define SourceProvider_h
 
 #ifndef SourceProvider_h
 #define SourceProvider_h
 
+#include "SourceProviderCache.h"
 #include "UString.h"
 #include "UString.h"
+#include <wtf/PassOwnPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefCounted.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/text/TextPosition.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-    enum SourceBOMPresence { SourceHasNoBOMs, SourceCouldHaveBOMs };
-
     class SourceProvider : public RefCounted<SourceProvider> {
     public:
     class SourceProvider : public RefCounted<SourceProvider> {
     public:
-        SourceProvider(const UString& url, SourceBOMPresence hasBOMs = SourceCouldHaveBOMs)
+        SourceProvider(const UString& url, SourceProviderCache* cache = 0)
             : m_url(url)
             : 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 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); }
 
         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:
     private:
+        virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); }
+
         UString m_url;
         UString m_url;
-        SourceBOMPresence m_hasBOMs;
+        bool m_validated;
+        SourceProviderCache* m_cache;
+        bool m_cacheOwned;
     };
 
     class UStringSourceProvider : public SourceProvider {
     };
 
     class UStringSourceProvider : public SourceProvider {
@@ -66,9 +83,12 @@ namespace JSC {
             return adoptRef(new UStringSourceProvider(source, url));
         }
 
             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)
 
     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>
 #define CallIdentifier_h
 
 #include <runtime/UString.h>
-#include "FastAllocBase.h"
+#include <wtf/text/CString.h>
+#include <wtf/text/StringHash.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
-    struct CallIdentifier : public FastAllocBase {
+    struct CallIdentifier {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         UString m_name;
         UString m_url;
         unsigned m_lineNumber;
         UString m_name;
         UString m_url;
         unsigned m_lineNumber;
@@ -56,11 +59,11 @@ namespace JSC {
             static unsigned hash(const CallIdentifier& key)
             {
                 unsigned hashCodes[3] = {
             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
                 };
                     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; }
             }
 
             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(); }
 
 #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
     };
 
 #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.
 {
     // 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()
 }
 
 Profile::~Profile()
@@ -106,7 +106,7 @@ void Profile::debugPrintData() const
     m_head->debugPrintData(0);
 }
 
     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)
 {
 
 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)
 
     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");
 }
 
     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)";
 
 
 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();
 {
     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)
 }
 
 void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
@@ -63,7 +63,7 @@ void ProfileGenerator::addParentForConsoleStart(ExecState* exec)
     JSValue function;
 
     exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function);
     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());
 }
 
     m_head->insertNode(m_currentNode.get());
 }
 
@@ -72,35 +72,35 @@ const UString& ProfileGenerator::title() const
     return m_profile->title();
 }
 
     return m_profile->title();
 }
 
-void ProfileGenerator::willExecute(const CallIdentifier& callIdentifier)
+void ProfileGenerator::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
 {
     if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) {
 {
     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);
     }
 
         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;
 
         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()) {
 {
     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);
     }
 
         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;
 
         return;
 
-    ASSERT_ARG(m_currentNode, m_currentNode);
+    ASSERT(m_currentNode);
     if (m_currentNode->callIdentifier() != callIdentifier) {
     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());
         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();
 }
 
     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);
 void ProfileGenerator::stopProfiling()
 {
     m_profile->forEach(&ProfileNode::stopProfiling);
@@ -117,14 +128,14 @@ void ProfileGenerator::stopProfiling()
     removeProfileStart();
     removeProfileEnd();
 
     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()) {
 
     // 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);
 
         idleNode->setTotalTime(headSelfTime);
         idleNode->setSelfTime(headSelfTime);
index 82149b33d61675d410ddb0ada5d1c142465fd907..8c8b81731535619d14233dff0fdb7d1b22880adf 100644 (file)
@@ -34,6 +34,7 @@
 namespace JSC {
 
     class ExecState;
 namespace JSC {
 
     class ExecState;
+    class JSGlobalObject;
     class Profile;
     class ProfileNode;
     class UString;
     class Profile;
     class ProfileNode;
     class UString;
@@ -41,32 +42,34 @@ namespace JSC {
 
     class ProfileGenerator : public RefCounted<ProfileGenerator>  {
     public:
 
     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; }
 
         // 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
         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();
 
 
         // Stopping Profiling
         void stopProfiling();
 
-        typedef void (ProfileGenerator::*ProfileFunction)(const CallIdentifier& callIdentifier);
+        typedef void (ProfileGenerator::*ProfileFunction)(ExecState* callerOrHandlerCallFrame, const CallIdentifier& callIdentifier);
 
     private:
 
     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;
         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;
         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 double getCount()
 {
 #if OS(WINDOWS)
-    static LARGE_INTEGER frequency = {0};
+    static LARGE_INTEGER frequency;
     if (!frequency.QuadPart)
         QueryPerformanceFrequency(&frequency);
     LARGE_INTEGER counter;
     if (!frequency.QuadPart)
         QueryPerformanceFrequency(&frequency);
     LARGE_INTEGER counter;
@@ -56,8 +56,9 @@ static double getCount()
 #endif
 }
 
 #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)
     , m_head(headNode)
     , m_parent(parentNode)
     , m_nextSibling(0)
@@ -72,8 +73,9 @@ ProfileNode::ProfileNode(const CallIdentifier& callIdentifier, ProfileNode* head
     startTimer();
 }
 
     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)
     , 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) {
 {
     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());
     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",
         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_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;
 
 
     ++indentLevel;
 
@@ -313,13 +315,13 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
     printf("    ");
 
     // Print function names
     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("  ");
 
     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
 
         printf("%.0f %s\n", sampleCount ? sampleCount : 1, name);
     } else
@@ -339,7 +341,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC
         while (indentLevel--)
             printf("  ");
 
         while (indentLevel--)
             printf("  ");
 
-        printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().UTF8String().data());
+        printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
     }
 
     return m_actualTotalTime;
     }
 
     return m_actualTotalTime;
index 2b5a93602f4318623e0f12efd7aeb7363e87b8b6..ffe7b6f9d0e34caf3d3cf282422f342b5c7d1e91 100644 (file)
 #define ProfileNode_h
 
 #include "CallIdentifier.h"
 #define ProfileNode_h
 
 #include "CallIdentifier.h"
-#include <wtf/Vector.h>
+#include <wtf/HashCountedSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
+    class ExecState;
     class ProfileNode;
 
     typedef Vector<RefPtr<ProfileNode> >::const_iterator StackIterator;
     class ProfileNode;
 
     typedef Vector<RefPtr<ProfileNode> >::const_iterator StackIterator;
-    typedef HashCountedSet<UString::Rep*> FunctionCallHashCount;
+    typedef HashCountedSet<StringImpl*> FunctionCallHashCount;
 
     class ProfileNode : public RefCounted<ProfileNode> {
     public:
 
     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(); }
 
         }
 
         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
         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; }
         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:
 #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();
 
         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(); }
 
         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;
         CallIdentifier m_callIdentifier;
         ProfileNode* m_head;
         ProfileNode* m_parent;
index fe8727a4bf3b9f29029c5c156fd6b5e95d144db6..bcaaaacbf217b08425f4327ca8bd37bf23a14a26 100644 (file)
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
 #include "CodeBlock.h"
 #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 "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 {
 #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.
 
     // 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();
 
     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;
             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)
 {
     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();
     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();
 
             profileGenerator->stopProfiling();
             RefPtr<Profile> returnProfile = profileGenerator->profile();
 
@@ -97,42 +99,62 @@ PassRefPtr<Profile> Profiler::stopProfiling(ExecState* exec, const UString& titl
     return 0;
 }
 
     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) {
 {
     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());
 
 {
     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());
 
 {
     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());
 
 {
     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());
 
 {
     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)
 }
 
 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);
         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);
     }
         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(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)
 }
 
 CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function)
index 4b8b4a019f0d0c0570c74e3b4b07b73e429f0a4b..86366c1c4f9198d3df116229e55c0c9935fdea1d 100644 (file)
@@ -38,13 +38,15 @@ namespace JSC {
 
     class ExecState;
     class JSGlobalData;
 
     class ExecState;
     class JSGlobalData;
+    class JSGlobalObject;
     class JSObject;
     class JSValue;
     class ProfileGenerator;
     class UString;
     struct CallIdentifier;    
 
     class JSObject;
     class JSValue;
     class ProfileGenerator;
     class UString;
     struct CallIdentifier;    
 
-    class Profiler : public FastAllocBase {
+    class Profiler {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
         static Profiler** enabledProfilerReference()
         {
     public:
         static Profiler** enabledProfilerReference()
         {
@@ -56,11 +58,14 @@ namespace JSC {
 
         void startProfiling(ExecState*, const UString& title);
         PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title);
 
         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; };
 
 
         const Vector<RefPtr<ProfileGenerator> >& currentProfiles() { return m_currentProfiles; };
 
index 29f075c421d2887f7c9c3b1e4eb6b1c7fc9daf9d..a2c5d9ec789ea5ca9518f6faa92ae7800d76e132 100644 (file)
@@ -30,7 +30,7 @@
 #import "JSRetainPtr.h"
 #import <Foundation/Foundation.h>
 
 #import "JSRetainPtr.h"
 #import <Foundation/Foundation.h>
 
-#if PLATFORM(IPHONE_SIMULATOR)
+#if PLATFORM(IOS_SIMULATOR)
 #import <Foundation/NSDistributedNotificationCenter.h>
 #endif
 
 #import <Foundation/NSDistributedNotificationCenter.h>
 #endif
 
@@ -65,7 +65,7 @@
     if ([defaults boolForKey:@"EnableJSProfiling"])
         [self startProfiling];
 
     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];
     // 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]];
 
     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];
     // 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 += 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)
 
 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 \
 
 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/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 \
 
 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/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
 
 
 !static: DEFINES += QT_MAKEDLL
 
index cd86e2074c7c2930001d7d728ea423d9895476c3..0c57d9554a1d6f1e3542cb7c744ac3994e34eb2f 100644 (file)
@@ -20,7 +20,9 @@
 #ifndef qscriptconverter_p_h
 #define qscriptconverter_p_h
 
 #ifndef qscriptconverter_p_h
 #define qscriptconverter_p_h
 
+#include "qscriptvalue.h"
 #include <JavaScriptCore/JavaScript.h>
 #include <JavaScriptCore/JavaScript.h>
+#include <QtCore/qglobal.h>
 #include <QtCore/qnumeric.h>
 #include <QtCore/qstring.h>
 #include <QtCore/qvarlengtharray.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());
     }
         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
 };
 
 #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 "qscriptprogram_p.h"
 #include "qscriptsyntaxcheckresult_p.h"
 #include "qscriptvalue_p.h"
+#include <QtCore/qdatetime.h>
+#include <QtCore/qnumeric.h>
 
 /*!
     Constructs a QScriptEngine object.
 
 /*!
     Constructs a QScriptEngine object.
@@ -95,6 +97,71 @@ QScriptValue QScriptEngine::evaluate(const QScriptProgram& program)
     return QScriptValuePrivate::get(d_ptr->evaluate(QScriptProgramPrivate::get(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.
 
 /*!
     Runs the garbage collector.
 
@@ -150,6 +217,28 @@ QScriptString QScriptEngine::toStringHandle(const QString& str)
     return QScriptStringPrivate::get(d_ptr->toStringHandle(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.
 
 /*!
   Returns a QScriptValue of the primitive type Null.
 
@@ -170,6 +259,137 @@ QScriptValue QScriptEngine::undefinedValue()
     return QScriptValue(this, QScriptValue::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.
 
 /*!
   Returns this engine's Global Object.
 
@@ -184,3 +404,23 @@ QScriptValue QScriptEngine::globalObject() const
 {
     return QScriptValuePrivate::get(d_ptr->globalObject());
 }
 {
     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 "qscriptprogram.h"
 #include "qscriptstring.h"
 #include "qscriptsyntaxcheckresult.h"
+#include "qscriptvalue.h"
 #include <QtCore/qobject.h>
 #include <QtCore/qshareddata.h>
 #include <QtCore/qstring.h>
 
 #include <QtCore/qobject.h>
 #include <QtCore/qshareddata.h>
 #include <QtCore/qstring.h>
 
-class QScriptValue;
+class QDateTime;
 class QScriptEnginePrivate;
 
 class QScriptEnginePrivate;
 
+// FIXME: Remove this once QScriptContext is properly defined.
+typedef void QScriptContext;
+
 // Internal typedef
 typedef QExplicitlySharedDataPointer<QScriptEnginePrivate> QScriptEnginePtr;
 
 // 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);
 
     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);
     void collectGarbage();
     void reportAdditionalMemoryCost(int cost);
 
     QScriptString toStringHandle(const QString& str);
+    QScriptValue toObject(const QScriptValue& value);
 
     QScriptValue nullValue();
     QScriptValue undefinedValue();
 
     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;
     QScriptValue globalObject() const;
 private:
     friend class QScriptEnginePrivate;
index 38185abd91e9eb02613a2552b55a58dc4dbd92d1..89054c085574a802e81f31063e52911ec644599d 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "qscriptengine_p.h"
 
 
 #include "qscriptengine_p.h"
 
+#include "qscriptfunction_p.h"
 #include "qscriptprogram_p.h"
 #include "qscriptvalue_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))
 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()
 {
 {
 }
 
 QScriptEnginePrivate::~QScriptEnginePrivate()
 {
+    JSClassRelease(m_nativeFunctionClass);
+    JSClassRelease(m_nativeFunctionWithArgClass);
+    if (m_exception)
+        JSValueUnprotect(m_context, m_exception);
     JSGlobalContextRelease(m_context);
 }
 
     JSGlobalContextRelease(m_context);
 }
 
@@ -74,11 +83,85 @@ QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QScriptProgramPrivate*
 {
     if (program->isNull())
         return new QScriptValuePrivate;
 {
     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
 {
 }
 
 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 "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 "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 <JSBasePrivate.h>
 #include <QtCore/qshareddata.h>
 #include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
 
 class QScriptEngine;
 class QScriptSyntaxCheckResultPrivate;
 
 class QScriptEngine;
 class QScriptSyntaxCheckResultPrivate;
@@ -41,11 +44,23 @@ public:
     QScriptEnginePrivate(const QScriptEngine*);
     ~QScriptEnginePrivate();
 
     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);
 
     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);
 
     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;
 
     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;
 
     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;
 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);
 {
     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
         return exception; // returns an exception
+    }
+    clearExceptions();
     return result;
 }
 
     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);
 void QScriptEnginePrivate::collectGarbage()
 {
     JSGarbageCollect(m_context);
@@ -132,9 +223,37 @@ QScriptStringPrivate* QScriptEnginePrivate::toStringHandle(const QString& str) c
     return new QScriptStringPrivate(str);
 }
 
     return new QScriptStringPrivate(str);
 }
 
-JSGlobalContextRef QScriptEnginePrivate::context() const
+QScriptEnginePrivate::operator JSGlobalContextRef() const
 {
 {
+    Q_ASSERT(this);
     return m_context;
 }
 
     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
 #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 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:
     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);
 }
 
             || !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; }
 
 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 quint64 id() const;
 
+    inline operator JSStringRef() const;
+
 private:
     JSStringRef m_string;
 };
 private:
     JSStringRef m_string;
 };
@@ -109,4 +111,14 @@ quint64 QScriptStringPrivate::id() const
     return reinterpret_cast<quint32>(m_string);
 }
 
     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
 #endif // qscriptstring_p_h
index 5cf02ef74ca942ded8e43a9cf5887db36fc05837..3948c5de37e8937c1c75749ce5f0d3df6329ddab 100644 (file)
@@ -119,7 +119,7 @@ QString QScriptSyntaxCheckResult::errorMessage() const
 QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate()
 {
     if (m_exception)
 QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate()
 {
     if (m_exception)
-        JSValueUnprotect(m_engine->context(), m_exception);
+        JSValueUnprotect(*m_engine, m_exception);
 }
 
 QString QScriptSyntaxCheckResultPrivate::errorMessage() const
 }
 
 QString QScriptSyntaxCheckResultPrivate::errorMessage() const
@@ -127,7 +127,7 @@ QString QScriptSyntaxCheckResultPrivate::errorMessage() const
     if (!m_exception)
         return QString();
 
     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;
     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");
         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);
                                           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();
 }
 
     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.
 /*!
   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();
 }
 
     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
 /*!
   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;
 }
 
     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.
 
 /*!
   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
 {
 */
 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
 {
 */
 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
 
 #ifndef qscriptvalue_h
 #define qscriptvalue_h
 
+#include "qscriptstring.h"
 #include <QtCore/qlist.h>
 #include <QtCore/qshareddata.h>
 
 class QScriptEngine;
 class QScriptValuePrivate;
 #include <QtCore/qlist.h>
 #include <QtCore/qshareddata.h>
 
 class QScriptEngine;
 class QScriptValuePrivate;
+class QDateTime;
 
 class QScriptValue;
 typedef QList<QScriptValue> QScriptValueList;
 
 class QScriptValue;
 typedef QList<QScriptValue> QScriptValueList;
@@ -32,7 +34,27 @@ typedef QList<QScriptValue> QScriptValueList;
 typedef double qsreal;
 
 class QScriptValue {
 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
     enum SpecialValue {
         NullValue,
         UndefinedValue
@@ -59,8 +81,24 @@ public:
     ~QScriptValue();
 
     QScriptValue& operator=(const QScriptValue& other);
     ~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 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;
 
 
     QScriptEngine* engine() const;
 
@@ -74,6 +112,8 @@ public:
     bool isUndefined() const;
     bool isObject() const;
     bool isError() const;
     bool isUndefined() const;
     bool isObject() const;
     bool isError() const;
+    bool isArray() const;
+    bool isDate() const;
 
     QString toString() const;
     qsreal toNumber() const;
 
     QString toString() const;
     qsreal toNumber() const;
@@ -83,10 +123,11 @@ public:
     qint32 toInt32() const;
     quint32 toUInt32() const;
     quint16 toUInt16() const;
     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());
 
     QScriptValue call(const QScriptValue& thisObject = QScriptValue(),
                       const QScriptValueList& args = QScriptValueList());
-
 private:
     QScriptValue(void*);
     QScriptValue(QScriptValuePrivate*);
 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 "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>
 #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
     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.
     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.
 
   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 {
 */
 
 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, 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();
 
     inline bool isValid() const;
     inline bool isBool();
@@ -96,6 +102,8 @@ public:
     inline bool isError();
     inline bool isObject();
     inline bool isFunction();
     inline bool isError();
     inline bool isObject();
     inline bool isFunction();
+    inline bool isArray();
+    inline bool isDate();
 
     inline QString toString() const;
     inline qsreal toNumber() const;
 
     inline QString toString() const;
     inline qsreal toNumber() const;
@@ -105,15 +113,46 @@ public:
     inline quint32 toUInt32() const;
     inline quint16 toUInt16() const;
 
     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 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 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 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:
     inline QScriptEnginePrivate* engine() const;
 
 private:
@@ -123,20 +162,31 @@ private:
         CString = 0x1000,
         CNumber,
         CBool,
         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;
         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;
     inline State refinedJSValue();
 
     inline bool isJSBased() const;
@@ -158,132 +208,124 @@ QScriptValue QScriptValuePrivate::get(QScriptValuePrivate* d)
 
 QScriptValuePrivate::~QScriptValuePrivate()
 {
 
 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)
 }
 
 QScriptValuePrivate::QScriptValuePrivate()
     : m_state(Invalid)
-    , m_value(0)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(const QString& string)
     : m_state(CString)
 {
 }
 
 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)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(bool value)
     : m_state(CBool)
-    , m_number(value)
-    , m_value(0)
+    , u(value)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(int number)
     : m_state(CNumber)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(int number)
     : m_state(CNumber)
-    , m_number(number)
-    , m_value(0)
+    , u(number)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(uint number)
     : m_state(CNumber)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(uint number)
     : m_state(CNumber)
-    , m_number(number)
-    , m_value(0)
+    , u(number)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(qsreal number)
     : m_state(CNumber)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(qsreal number)
     : m_state(CNumber)
-    , m_number(number)
-    , m_value(0)
+    , u(number)
 {
 }
 
 QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value)
 {
 }
 
 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))
 {
 }
 
 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);
 {
     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))
 }
 
 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);
 {
     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))
 }
 
 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);
 {
     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))
 }
 
 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);
 {
     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))
 }
 
 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);
 {
     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))
 }
 
 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);
 {
     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))
 }
 
 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);
 {
     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_state(JSObject)
     , m_engine(const_cast<QScriptEnginePrivate*>(engine))
-    , m_value(value)
-    , m_object(object)
+    , u(object)
 {
     Q_ASSERT(engine);
 {
     Q_ASSERT(engine);
-    Q_ASSERT(value);
     Q_ASSERT(object);
     Q_ASSERT(object);
-    JSValueProtect(context(), m_value);
+    JSValueProtect(*m_engine, object);
 }
 
 bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
 }
 
 bool QScriptValuePrivate::isValid() const { return m_state != Invalid; }
@@ -298,7 +340,7 @@ bool QScriptValuePrivate::isBool()
             return false;
         // Fall-through.
     case JSPrimitive:
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsBoolean(context(), value());
+        return JSValueIsBoolean(*m_engine, *this);
     default:
         return false;
     }
     default:
         return false;
     }
@@ -314,7 +356,7 @@ bool QScriptValuePrivate::isNumber()
             return false;
         // Fall-through.
     case JSPrimitive:
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsNumber(context(), value());
+        return JSValueIsNumber(*m_engine, *this);
     default:
         return false;
     }
     default:
         return false;
     }
@@ -323,14 +365,14 @@ bool QScriptValuePrivate::isNumber()
 bool QScriptValuePrivate::isNull()
 {
     switch (m_state) {
 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:
     case JSValue:
         if (refinedJSValue() != JSPrimitive)
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsNull(context(), value());
+        return JSValueIsNull(*m_engine, *this);
     default:
         return false;
     }
     default:
         return false;
     }
@@ -346,7 +388,7 @@ bool QScriptValuePrivate::isString()
             return false;
         // Fall-through.
     case JSPrimitive:
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsString(context(), value());
+        return JSValueIsString(*m_engine, *this);
     default:
         return false;
     }
     default:
         return false;
     }
@@ -355,14 +397,14 @@ bool QScriptValuePrivate::isString()
 bool QScriptValuePrivate::isUndefined()
 {
     switch (m_state) {
 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:
     case JSValue:
         if (refinedJSValue() != JSPrimitive)
             return false;
         // Fall-through.
     case JSPrimitive:
-        return JSValueIsUndefined(context(), value());
+        return JSValueIsUndefined(*m_engine, *this);
     default:
         return false;
     }
     default:
         return false;
     }
@@ -376,7 +418,7 @@ bool QScriptValuePrivate::isError()
             return false;
         // Fall-through.
     case JSObject:
             return false;
         // Fall-through.
     case JSObject:
-        return inherits("Error");
+        return m_engine->isError(*this);
     default:
         return false;
     }
     default:
         return false;
     }
@@ -403,7 +445,35 @@ bool QScriptValuePrivate::isFunction()
             return false;
         // Fall-through.
     case JSObject:
             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;
     }
     default:
         return false;
     }
@@ -415,17 +485,21 @@ QString QScriptValuePrivate::toString() const
     case Invalid:
         return QString();
     case CBool:
     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:
     case CString:
-        return m_string;
+        return *u.m_string;
     case CNumber:
     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:
     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());
     }
 
         return QScriptConverter::toString(ptr.get());
     }
 
@@ -439,26 +513,32 @@ qsreal QScriptValuePrivate::toNumber() const
     case JSValue:
     case JSPrimitive:
     case JSObject:
     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:
     case CNumber:
-        return m_number;
+        return u.m_number;
     case CBool:
     case CBool:
-        return m_number ? 1 : 0;
+        return u.m_bool ? 1 : 0;
+    case CNull:
     case Invalid:
         return 0;
     case Invalid:
         return 0;
-    case CSpecial:
-        return m_number == QScriptValue::NullValue ? 0 : qQNaN();
+    case CUndefined:
+        return qQNaN();
     case CString:
         bool ok;
     case CString:
         bool ok;
-        qsreal result = m_string.toDouble(&ok);
+        qsreal result = u.m_string->toDouble(&ok);
         if (ok)
             return result;
         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 (ok)
             return result;
-        if (m_string == "Infinity" || m_string == "-Infinity")
+        if (*u.m_string == "Infinity" || *u.m_string == "-Infinity")
             return qInf();
             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.");
     }
 
     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:
     switch (m_state) {
     case JSValue:
     case JSPrimitive:
-        return JSValueToBoolean(context(), value());
+        return JSValueToBoolean(*m_engine, *this);
     case JSObject:
         return true;
     case CNumber:
     case JSObject:
         return true;
     case CNumber:
-        return !(qIsNaN(m_number) || !m_number);
+        return !(qIsNaN(u.m_number) || !u.m_number);
     case CBool:
     case CBool:
-        return m_number;
+        return u.m_bool;
     case Invalid:
     case Invalid:
-    case CSpecial:
+    case CNull:
+    case CUndefined:
         return false;
     case CString:
         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.");
     }
 
     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();
 }
 
     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)
 {
 
 bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
 {
-    if (!isValid() || !other->isValid())
+    if (!isValid())
+        return !other->isValid();
+
+    if (!other->isValid())
         return false;
 
         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()) {
     }
 
     if (isJSBased() && !other->isJSBased()) {
@@ -541,32 +782,63 @@ bool QScriptValuePrivate::equals(QScriptValuePrivate* other)
             return false;
         }
     } else if (!isJSBased() && other->isJSBased()) {
             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;
         }
     }
 
             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()) {
     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;
         }
         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)
 {
 */
 bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
 {
+    Q_ASSERT(engine);
     JSValueRef value;
     switch (m_state) {
     case CBool:
     JSValueRef value;
     switch (m_state) {
     case CBool:
-        value = engine->makeJSValue(static_cast<bool>(m_number));
+        value = engine->makeJSValue(u.m_bool);
         break;
     case CString:
         break;
     case CString:
-        value = engine->makeJSValue(m_string);
+        value = engine->makeJSValue(*u.m_string);
+        delete u.m_string;
         break;
     case CNumber:
         break;
     case CNumber:
-        value = engine->makeJSValue(m_number);
+        value = engine->makeJSValue(u.m_number);
         break;
         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())
         break;
     default:
         if (!isJSBased())
@@ -597,10 +874,255 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine)
     }
     m_engine = engine;
     m_state = JSPrimitive;
     }
     m_engine = engine;
     m_state = JSPrimitive;
-    setValue(value);
+    u.m_value = value;
+    JSValueProtect(*m_engine, value);
     return true;
 }
 
     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) {
 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;
                 }
                     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;
             }
 
             // 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);
                 return new QScriptValuePrivate(engine(), exception);
+            }
             if (result && !exception)
                 return new QScriptValuePrivate(engine(), result);
         }
             if (result && !exception)
                 return new QScriptValuePrivate(engine(), result);
         }
@@ -644,46 +1168,18 @@ QScriptEnginePrivate* QScriptValuePrivate::engine() const
     return m_engine.data();
 }
 
     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());
 {
     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);
 {
     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);
 QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue()
 {
     Q_ASSERT(m_state == JSValue);
-    if (!JSValueIsObject(context(), value())) {
+    if (!JSValueIsObject(*m_engine, *this)) {
         m_state = JSPrimitive;
     } else {
         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;
         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;
 }
     }
     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.
 */
   \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
 
 /*!
   \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 "qscriptprogram.h"
 #include "qscriptsyntaxcheckresult.h"
 #include "qscriptvalue.h"
+#include <QtCore/qnumeric.h>
 #include <QtTest/qtest.h>
 
 class tst_QScriptEngine : public QObject {
 #include <QtTest/qtest.h>
 
 class tst_QScriptEngine : public QObject {
@@ -35,6 +36,8 @@ public slots:
     void cleanup() {}
 
 private slots:
     void cleanup() {}
 
 private slots:
+    void newFunction();
+    void newObject();
     void globalObject();
     void evaluate();
     void collectGarbage();
     void globalObject();
     void evaluate();
     void collectGarbage();
@@ -44,6 +47,11 @@ private slots:
     void evaluateProgram();
     void checkSyntax_data();
     void checkSyntax();
     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. */
 };
 
 /* 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");
 }
 
     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;
 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")));
     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));
 }
 
     QVERIFY(engine.globalObject().strictlyEquals(self));
 }
 
@@ -303,6 +462,273 @@ void tst_QScriptEngine::checkSyntax()
     QCOMPARE(result.errorMessage(), errorMessage);
 }
 
     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"
 
 QTEST_MAIN(tst_QScriptEngine)
 #include "tst_qscriptengine.moc"
index 35cc17da9083768a845bae214b5ba1ce926e8557..02e94ecdd2b1ab5fa28731b81831c0ffd0b4c49b 100644 (file)
@@ -6,7 +6,10 @@ include(../tests.pri)
 
 SOURCES += \
     tst_qscriptvalue.cpp \
 
 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
 
 HEADERS += \
     tst_qscriptvalue.h
index 82f09014fa81a9d7f3300205a1fc5eef1c6f781b..e04d3e91dcb35ed343ccaff56bd546349bb693ab 100644 (file)
 #include <QtCore/qnumeric.h>
 
 tst_QScriptValue::tst_QScriptValue()
 #include <QtCore/qnumeric.h>
 
 tst_QScriptValue::tst_QScriptValue()
-    : engine(0)
+    : m_engine(0)
 {
 }
 
 tst_QScriptValue::~tst_QScriptValue()
 {
 {
 }
 
 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;
 void tst_QScriptValue::ctor()
 {
     QScriptEngine eng;
@@ -274,6 +249,392 @@ void tst_QScriptValue::ctor()
     QVERIFY(QScriptValue(0, QString("ciao")).isString());
 }
 
     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");
 void tst_QScriptValue::toStringSimple_data()
 {
     QTest::addColumn<QString>("code");
@@ -431,5 +792,505 @@ void tst_QScriptValue::call()
     QVERIFY(incr.call().isValid()); // Exception.
 }
 
     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)
 
 QTEST_MAIN(tst_QScriptValue)
index 28154a98238472b4cb51b0594d3839a9ec104059..7b7d9bcecfd2e5ad606944c58af7a1313b096b47 100644 (file)
 #include <QtCore/qnumeric.h>
 #include <QtTest/qtest.h>
 
 #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);
 Q_DECLARE_METATYPE(QScriptValue*);
 Q_DECLARE_METATYPE(QScriptValue);
+typedef QPair<QString, QScriptValue> QPairQStringAndQScriptValue;
+Q_DECLARE_METATYPE(QPairQStringAndQScriptValue);
 
 class tst_QScriptValue : public QObject {
     Q_OBJECT
 
 class tst_QScriptValue : public QObject {
     Q_OBJECT
@@ -45,16 +49,36 @@ private slots:
     void dataSharing();
     void constructors_data();
     void constructors();
     void dataSharing();
     void constructors_data();
     void constructors();
+    void getSetPrototype();
     void call();
     void ctor();
     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.
 
     // Generated test functions.
+    void isArray_data();
+    void isArray();
+
     void isBool_data();
     void isBool();
 
     void isBoolean_data();
     void isBoolean();
 
     void isBool_data();
     void isBool();
 
     void isBoolean_data();
     void isBoolean();
 
+    void isError_data();
+    void isError();
+
     void isNumber_data();
     void isNumber();
 
     void isNumber_data();
     void isNumber();
 
@@ -100,97 +124,20 @@ private slots:
     void toUInt16_data();
     void toUInt16();
 
     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:
 
 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
 
 #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 \
 TEMPLATE = subdirs
 SUBDIRS =   qscriptengine \
             qscriptvalue \
+            qscriptvalueiterator \
             qscriptstring
             qscriptstring
index ab2b5d7dae7143c5166aa943cb8abce37e4ba67e..c1aa9dd7a6935e6b98059c043bb3c4c80b4f46fb 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "JSValue.h"
 #include "JSCell.h"
 
 #include "JSValue.h"
 #include "JSCell.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 
 using std::min;
 
 
 using std::min;
 
@@ -37,12 +39,12 @@ void ArgList::getSlice(int startIndex, ArgList& result) const
     result = ArgList(m_args + startIndex, m_argCount - startIndex);
 }
 
     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;
 {
     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) {
     // 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);
         if (Heap* heap = Heap::heap(v)) {
             ListSet& markSet = heap->markListSet();
             markSet.add(this);
index 8e1fdbe4b89af9084b631ae851c3304c1c45ad6c..ef7809fe8fc5682162e22cfb3e213aa86c230033 100644 (file)
 #ifndef ArgList_h
 #define ArgList_h
 
 #ifndef ArgList_h
 #define ArgList_h
 
+#include "CallFrame.h"
 #include "Register.h"
 #include "Register.h"
+#include "WriteBarrier.h"
 #include <wtf/HashSet.h>
 #include <wtf/HashSet.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
     class MarkStack;
 #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;
     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());
 
         {
             ASSERT(!m_markSet);
             ASSERT(isEmpty());
 
-            m_buffer = buffer;
+            m_buffer = reinterpret_cast<Register*>(buffer);
             m_size = size;
 #ifndef NDEBUG
             m_isReadOnly = true;
             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; }
 
         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);
 
     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)
         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);
 
 
 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()
 {
 
 Arguments::~Arguments()
 {
@@ -43,22 +43,25 @@ Arguments::~Arguments()
         delete [] d->extraArguments;
 }
 
         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)
 
     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;
 
     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)
 
     if (d->activation)
-        markStack.append(d->activation);
+        visitor.append(&d->activation);
 }
 
 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
 }
 
 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)
         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)
         for (; i < d->numArguments; ++i)
-            buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
+            buffer[i] = d->extraArguments[i - d->numParameters].get();
         return;
     }
     
         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])
     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])
         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);
     }
         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)
         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)
         for (; i < d->numArguments; ++i)
-            args.append(d->extraArguments[i - d->numParameters].jsValue());
+            args.append(d->extraArguments[i - d->numParameters].get());
         return;
     }
 
         return;
     }
 
@@ -129,13 +132,13 @@ void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
     unsigned i = 0;
     for (; i < parametersLength; ++i) {
         if (!d->deletedArguments[i])
     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])
         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));
     }
         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) {
 {
     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
         } else
-            slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
+            slot.setValue(d->extraArguments[i - d->numParameters].get());
         return true;
     }
 
         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;
 }
 
 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) {
     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
         } 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)) {
         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)) {
         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;
     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) {
     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
         } 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)) {
         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)) {
         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);
 }
     
     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])
     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);
         }
         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);
 }
 
     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)
 {
     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
         else
-            d->extraArguments[i - d->numParameters] = JSValue(value);
+            d->extraArguments[i - d->numParameters].set(exec->globalData(), this, value);
         return;
     }
 
         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;
 }
 
 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)
     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
         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;
         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) {
         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);
 }
 
     JSObject::put(exec, propertyName, value, slot);
 }
 
@@ -261,7 +307,7 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i)
 {
     if (i < d->numArguments) {
         if (!d->deletedArguments) {
 {
     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]) {
             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;
 }
 
 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) {
     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]) {
             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) {
     }
 
     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);
 }
 
     return JSObject::deleteProperty(exec, propertyName);
 }
index cca3cf21d019236f4f6651d19cd2719c48472001..9686d8b6cfea2054c37bac95b2311278f2363a75 100644 (file)
 #include "JSGlobalObject.h"
 #include "Interpreter.h"
 #include "ObjectConstructor.h"
 #include "JSGlobalObject.h"
 #include "Interpreter.h"
 #include "ObjectConstructor.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 
 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;
 
 
         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;
         OwnArrayPtr<bool> deletedArguments;
-        Register extraArgumentsFixedBuffer[4];
+        WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
 
 
-        JSFunction* callee;
+        WriteBarrier<JSFunction> callee;
         bool overrodeLength : 1;
         bool overrodeCallee : 1;
         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.
     public:
         // Use an enum because otherwise gcc insists on doing a memory
         // read.
@@ -65,9 +69,9 @@ namespace JSC {
         Arguments(CallFrame*, NoParametersType);
         virtual ~Arguments();
 
         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&);
 
 
         void fillArgList(ExecState*, MarkedArgumentBuffer&);
 
@@ -79,21 +83,22 @@ namespace JSC {
         }
         
         void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
         }
         
         void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
-        void copyRegisters();
+        void copyRegisters(JSGlobalData&);
         bool isTornOff() const { return d->registerArray; }
         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);
         }
 
             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:
         }
 
     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);
 
     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 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 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*);
 
 
         void init(CallFrame*);
 
@@ -117,16 +122,16 @@ namespace JSC {
 
     inline Arguments* asArguments(JSValue value)
     {
 
     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)
     {
         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();
 
         int numParameters = function->jsExecutable()->parameterCount();
-        argc = callFrame->argumentCount();
+        argc = callFrame->argumentCountIncludingThis();
 
         if (argc <= numParameters)
             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
 
         if (argc <= numParameters)
             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
@@ -138,9 +143,11 @@ namespace JSC {
     }
 
     inline Arguments::Arguments(CallFrame* callFrame)
     }
 
     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;
         JSFunction* callee;
         ptrdiff_t firstParameterIndex;
         Register* argv;
@@ -151,59 +158,66 @@ namespace JSC {
         d->firstParameterIndex = firstParameterIndex;
         d->numArguments = numArguments;
 
         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 (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)
             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->extraArguments = extraArguments;
 
-        d->callee = callee;
+        d->callee.set(callFrame->globalData(), this, callee);
         d->overrodeLength = false;
         d->overrodeCallee = false;
         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)
     }
 
     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->numParameters = 0;
         d->numArguments = numArguments;
-        d->activation = 0;
 
 
-        Register* extraArguments;
+        WriteBarrier<Unknown>* extraArguments;
         if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
         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)
         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->extraArguments = extraArguments;
 
-        d->callee = callFrame->callee();
+        d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
         d->overrodeLength = false;
         d->overrodeCallee = false;
         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());
 
     {
         ASSERT(!isTornOff());
 
@@ -213,40 +227,30 @@ namespace JSC {
         int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
         size_t registerArraySize = d->numParameters;
 
         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.
     }
 
     // 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;
 
 
         if (!numLocals)
             return;
 
-        int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
+        int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
         size_t registerArraySize = numLocals + 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
 
 
 } // namespace JSC
 
index fb4449405130bd557d93cf576d57cb376b8d568a..a4df41193d25e25f88a47ec602f7cc6e2605a5de 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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)
  *
  *  Copyright (C) 2003 Peter Kelly (pmk@post.com)
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
  *
 
 #include "ArrayPrototype.h"
 #include "Error.h"
 
 #include "ArrayPrototype.h"
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Lookup.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Lookup.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 
 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);
 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)
 {
 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))
     // 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
     }
 
     // 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;
 }
 
 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(....)'
 CallType ArrayConstructor::getCallData(CallData& callData)
 {
     // equivalent to 'new Array(....)'
@@ -89,9 +111,9 @@ CallType ArrayConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     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
 }
 
 } // namespace JSC
index 6d25400145acfdec411427d699b46d404fbdf99f..dc0df2455e05a8d3f532318af6a005e12e8db818 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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:
 
     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&);
 
         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) 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)
  *
  *  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 "Lookup.h"
 #include "ObjectPrototype.h"
 #include "Operations.h"
+#include "StringRecursionChecker.h"
 #include <algorithm>
 #include <wtf/Assertions.h>
 #include <wtf/HashSet.h>
 #include <algorithm>
 #include <wtf/Assertions.h>
 #include <wtf/HashSet.h>
@@ -40,27 +41,27 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ArrayPrototype);
 
 
 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 (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 ----------------------------
 
 }
 
 // ------------------------------ 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
 
 /* 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
   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
 */
 
 // 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)
 {
 }
 
 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)
 {
 }
 
 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 ----------------------------
 }
 
 // ------------------------------ Array Functions ----------------------------
@@ -156,26 +148,46 @@ static void putProperty(ExecState* exec, JSObject* obj, const Identifier& proper
     obj->put(exec, propertyName, value, slot);
 }
 
     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);
     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);
     
     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;
     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))
     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);
             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);
         
         if (!strBuffer.data()) {
             throwOutOfMemoryError(exec);
@@ -197,42 +209,40 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue
         if (exec->hadException())
             break;
     }
         if (exec->hadException())
             break;
     }
-    arrayVisitedElements.remove(thisObj);
     if (!totalSize)
     if (!totalSize)
-        return jsEmptyString(exec);
+        return JSValue::encode(jsEmptyString(exec));
     Vector<UChar> buffer;
     buffer.reserveCapacity(totalSize);
     if (!buffer.data())
     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(',');
         
     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);
             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);
 
     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;
 
     JSStringBuilder strBuffer;
-    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     for (unsigned k = 0; k < length; k++) {
         if (k >= 1)
             strBuffer.append(',');
     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;
             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
             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);
         }
     }
             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;
 
     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);
     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));
             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())
     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));
     }
         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);
     JSArray* arr = constructEmptyArray(exec);
-    int n = 0;
+    unsigned n = 0;
     JSValue curArg = thisValue.toThisObject(exec);
     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) {
     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) {
             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++;
         }
             arr->put(exec, n, curArg);
             n++;
         }
-        if (it == end)
+        if (i == argCount)
             break;
             break;
-        curArg = (*it);
-        ++it;
+        curArg = (exec->argument(i));
+        ++i;
     }
     arr->setLength(n);
     }
     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))
     if (isJSArray(&exec->globalData(), thisValue))
-        return asArray(thisValue)->pop();
+        return JSValue::encode(asArray(thisValue)->pop());
 
     JSObject* thisObj = thisValue.toThisObject(exec);
 
     JSObject* thisObj = thisValue.toThisObject(exec);
-    JSValue result;
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue result;
     if (length == 0) {
     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);
         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);
         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);
     }
 
     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 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);
     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);
     }
         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);
     JSValue result;
 
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsUndefined());
+
     if (length == 0) {
     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);
         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
 {
     // 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;
 
     // 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);
     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);
         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;
     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);
         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);
     // "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);
         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)
             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);
         }
     }
             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
     // 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);
     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);
 
     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) {
     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 {
         } 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)
             }
         }
     }
     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
     // 15.4.4.13
+
+    JSObject* thisObj = exec->hostThisValue().toThisObject(exec);
     unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(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)
         }
     }
     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);
     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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     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;
     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);
     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);
         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();
             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)
                 resultArray->put(exec, filterIndex++, v);
         }
         if (k == length)
-            return resultArray;
+            return JSValue::encode(resultArray);
     }
     for (; k < length && !exec->hadException(); ++k) {
         PropertySlot slot(thisObj);
     }
     for (; k < length && !exec->hadException(); ++k) {
         PropertySlot slot(thisObj);
-
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
-
         JSValue v = slot.getValue(exec, k);
 
         JSValue v = slot.getValue(exec, k);
 
-        MarkedArgumentBuffer eachArguments;
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
 
+        MarkedArgumentBuffer eachArguments;
         eachArguments.append(v);
         eachArguments.append(v);
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
         eachArguments.append(thisObj);
 
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
-
         if (result.toBoolean(exec))
             resultArray->put(exec, filterIndex++, v);
     }
         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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     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);
 
     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));
         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());
             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;
         PropertySlot slot(thisObj);
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
-
         JSValue v = slot.getValue(exec, k);
 
         JSValue v = slot.getValue(exec, k);
 
-        MarkedArgumentBuffer eachArguments;
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
 
 
+        MarkedArgumentBuffer eachArguments;
         eachArguments.append(v);
         eachArguments.append(v);
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
         eachArguments.append(thisObj);
 
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
         JSValue result = call(exec, function, callType, callData, applyThis, eachArguments);
         resultArray->put(exec, k, result);
     }
 
         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:
 }
 
 // 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
 
 // 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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     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);
 
 
     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);
     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));
         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)))
             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);
         }
     }
     for (; k < length && !exec->hadException(); ++k) {
         PropertySlot slot(thisObj);
-
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
 
         MarkedArgumentBuffer eachArguments;
         if (!thisObj->getPropertySlot(exec, k, slot))
             continue;
 
         MarkedArgumentBuffer eachArguments;
-
         eachArguments.append(slot.getValue(exec, k));
         eachArguments.append(slot.getValue(exec, k));
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
         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;
         }
     }
 
         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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     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);
     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));
         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();
             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));
 
         MarkedArgumentBuffer eachArguments;
         eachArguments.append(slot.getValue(exec, k));
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
         eachArguments.append(thisObj);
 
+        if (exec->hadException())
+            return JSValue::encode(jsUndefined());
+
         call(exec, function, callType, callData, applyThis, eachArguments);
     }
         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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     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);
 
 
     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);
     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));
         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)))
             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) {
         }
     }
     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));
 
         MarkedArgumentBuffer eachArguments;
         eachArguments.append(slot.getValue(exec, k));
-        eachArguments.append(jsNumber(exec, k));
+        eachArguments.append(jsNumber(k));
         eachArguments.append(thisObj);
 
         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;
         }
     }
         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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
     unsigned i = 0;
     JSValue rv;
 
     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);
 
     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;
     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)
                 break;
         }
         if (!rv)
-            return throwError(exec, TypeError);
+            return throwVMTypeError(exec);
         i++;
     }
 
     if (callType == CallTypeJS && array) {
         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);
         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);
             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
             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);
     }
 
     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);
         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);
     }
         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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
     
     unsigned i = 0;
     JSValue rv;
     
     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);
     
     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;
     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)
                 break;
         }
         if (!rv)
-            return throwError(exec, TypeError);
+            return throwVMTypeError(exec);
         i++;
     }
     
     if (callType == CallTypeJS && array) {
         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());
         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));
             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
             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);
     }
     
     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);
         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);
     }
         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);
     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))
     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);
     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))
         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
 }
 
 } // namespace JSC
index e52914c2f2aa9132d5d7ef8b4fda318439016672..bbc170ca76af4ba94d9c75e2cc3950606aa28db8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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:
 
     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&);
 
 
         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
     };
 
 } // namespace JSC
index 74089a53b9129c186839abb9625092c7215c7d99..610b8d16cb8a89cdb874cb39972663df63f3d0a8 100644 (file)
 #ifndef BatchedTransitionOptimizer_h
 #define BatchedTransitionOptimizer_h
 
 #ifndef BatchedTransitionOptimizer_h
 #define BatchedTransitionOptimizer_h
 
-#include <wtf/Noncopyable.h>
 #include "JSObject.h"
 
 namespace JSC {
 
 #include "JSObject.h"
 
 namespace JSC {
 
-    class BatchedTransitionOptimizer : public Noncopyable {
+    class BatchedTransitionOptimizer {
+        WTF_MAKE_NONCOPYABLE(BatchedTransitionOptimizer);
     public:
     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()
         {
         }
 
         ~BatchedTransitionOptimizer()
         {
-            m_object->flattenDictionaryObject();
+            if (m_object->structure()->isDictionary())
+                m_object->flattenDictionaryObject(*m_globalData);
         }
 
     private:
         }
 
     private:
+        JSGlobalData* m_globalData;
         JSObject* m_object;
     };
 
         JSObject* m_object;
     };
 
index b0d8df38ea5dfecd9f0e04aa4ca498e3057e91b9..a1a4ed48bfb2c8ddb6ea881cbe79157bb8025b0e 100644 (file)
@@ -28,26 +28,27 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor);
 
 
 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
 
     // 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)
 {
 }
 
 // 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;
 }
 
     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)
 }
 
 ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
@@ -57,9 +58,9 @@ ConstructType BooleanConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.6.1
 }
 
 // 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)
 }
 
 CallType BooleanConstructor::getCallData(CallData& callData)
@@ -68,10 +69,10 @@ CallType BooleanConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     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;
 }
 
     return obj;
 }
 
index 1d8a26a57009b5bcaecd094ccd2bd31f4ab3acb5..fa0d05e5887f10126961f13ac2e811153884222f 100644 (file)
@@ -29,14 +29,14 @@ namespace JSC {
 
     class BooleanConstructor : public InternalFunction {
     public:
 
     class BooleanConstructor : public InternalFunction {
     public:
-        BooleanConstructor(ExecState*, NonNullPassRefPtr<Structure>, BooleanPrototype*);
+        BooleanConstructor(ExecState*, JSGlobalObject*, Structure*, BooleanPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
 
     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
     JSObject* constructBoolean(ExecState*, const ArgList&);
 
 } // namespace JSC
index c9b3846597e68a1824f197577807a7772edad283..e24a30a4bb54ae500ed0e9d7165fc9ce7a5d9a63 100644 (file)
@@ -25,11 +25,12 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(BooleanObject);
 
 
 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
 }
 
 } // namespace JSC
index 4b02acb1dc9503d9b0b77be650187eabb131c702..def44b44dcd84fce03269190ff67cabb500272b2 100644 (file)
@@ -27,14 +27,13 @@ namespace JSC {
 
     class BooleanObject : public JSWrapperObject {
     public:
 
     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)
     {
 
     inline BooleanObject* asBooleanObject(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&BooleanObject::info));
+        ASSERT(asObject(value)->inherits(&BooleanObject::s_info));
         return static_cast<BooleanObject*>(asObject(value));
     }
 
         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) 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
  *
  *  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 "BooleanPrototype.h"
 
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "ObjectPrototype.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 
 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))
     if (thisValue == jsBoolean(false))
-        return jsNontrivialString(exec, "false");
+        return JSValue::encode(jsNontrivialString(exec, "false"));
 
     if (thisValue == jsBoolean(true))
 
     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))
 
     if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
-        return jsNontrivialString(exec, "false");
+        return JSValue::encode(jsNontrivialString(exec, "false"));
 
     ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
 
     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())
     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
 }
 
 } // namespace JSC
index cc69b3f00c699d99075232172c5a87914298d6de..2341c1147a4384d6ae8ab5d2b3a0fe56639ce009 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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:
 
     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
     };
 
 } // namespace JSC
index 04f7f62af06805d706be003762152f20c0e4c49e..67c7af8b9405df1435bc7ee45db737932eb8249d 100644 (file)
@@ -56,18 +56,18 @@ public:
             fastFree(m_cache);
     }
 
             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)
     {
         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;
         double result = orignalFunction(operand);
         entry->operand = operand;
         entry->result = result;
-        return jsDoubleNumber(exec, result);
+        return jsDoubleNumber(result);
     }
 
 private:
     }
 
 private:
index 62e42fef5ca59d78190167382c42109179b26900..018e2ca34b516be6bc691d31fac9a91f17c707e1 100644 (file)
 #include "config.h"
 #include "CallData.h"
 
 #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)
 {
 #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
 }
 
 } // namespace JSC
index 24c19f91dbdf7f4c216ef71fe3a665f4a8d403d7..b138f548405c24fa3c59f15838f90864f6b53fe7 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef CallData_h
 #define CallData_h
 
 #ifndef CallData_h
 #define CallData_h
 
-#include "NativeFunctionWrapper.h"
+#include "JSValue.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -37,7 +37,6 @@ namespace JSC {
     class ExecState;
     class FunctionExecutable;
     class JSObject;
     class ExecState;
     class FunctionExecutable;
     class JSObject;
-    class JSValue;
     class ScopeChainNode;
 
     enum CallType {
     class ScopeChainNode;
 
     enum CallType {
@@ -46,7 +45,7 @@ namespace JSC {
         CallTypeJS
     };
 
         CallTypeJS
     };
 
-    typedef JSValue (JSC_HOST_CALL *NativeFunction)(ExecState*, JSObject*, JSValue thisValue, const ArgList&);
+    typedef EncodedJSValue (JSC_HOST_CALL *NativeFunction)(ExecState*);
 
     union CallData {
         struct {
 
     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)
 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")
 
 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)
 {
 }
     JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME)
 {
 }
index de24f4a0d4847b5a2a89896e964d034bad717f6a..f74a84344a0a9167b0877f9c20d6007f590d1996 100644 (file)
     macro(compile) \
     macro(configurable) \
     macro(constructor) \
     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(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(hasOwnProperty) \
     macro(ignoreCase) \
     macro(index) \
     macro(input) \
     macro(isArray) \
     macro(isPrototypeOf) \
-    macro(keys) \
     macro(length) \
     macro(message) \
     macro(multiline) \
     macro(length) \
     macro(message) \
     macro(multiline) \
     macro(writable) \
     macro(displayName)
 
     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 {
 
 namespace JSC {
 
-    class CommonIdentifiers : public Noncopyable {
+    class CommonIdentifiers {
+        WTF_MAKE_NONCOPYABLE(CommonIdentifiers); WTF_MAKE_FAST_ALLOCATED;
     private:
         CommonIdentifiers(JSGlobalData*);
         friend class JSGlobalData;
     private:
         CommonIdentifiers(JSGlobalData*);
         friend class JSGlobalData;
@@ -94,7 +126,13 @@ namespace JSC {
         const Identifier emptyIdentifier;
         const Identifier underscoreProto;
         const Identifier thisIdentifier;
         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
 #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());
 
     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);
     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);
 }
 
     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());
 
 {
     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);
 
 
     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();
         ComplType exceptionType = Throw;
         if (exception.isObject())
             exceptionType = asObject(exception)->exceptionType();
index 63b315e18f639dd84f5ebca8a5dea077f432e320..1dd25fd11ae3fdc2e85783ad1524c6f2b0acb66a 100644 (file)
@@ -28,7 +28,7 @@
 namespace JSC {
 
     class ExecState;
 namespace JSC {
 
     class ExecState;
-    class ScopeChain;
+    class ScopeChainNode;
     class SourceCode;
 
     enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted, Terminated };
     class SourceCode;
 
     enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted, Terminated };
@@ -56,7 +56,7 @@ namespace JSC {
     };
 
     Completion checkSyntax(ExecState*, const SourceCode&);
     };
 
     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
 
 
 } // namespace JSC
 
index 7ee59d7ef77bf261c18c16c8190be56aff60957e..5da2a911cc5177a0d9bda27ebb5be8d6ef8d2de2 100644 (file)
 #include "config.h"
 #include "ConstructData.h"
 
 #include "config.h"
 #include "ConstructData.h"
 
+#include "Executable.h"
+#include "Interpreter.h"
 #include "JSFunction.h"
 #include "JSFunction.h"
+#include "JSGlobalObject.h"
 
 namespace JSC {
 
 
 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
 }
 
 } // namespace JSC
index 6b954a629e518b28e4783c817f86cc32b9431603..3d5f732a2210cfe2622ddaa22016053dc53f2ffe 100644 (file)
 #ifndef ConstructData_h
 #define ConstructData_h
 
 #ifndef ConstructData_h
 #define ConstructData_h
 
+#include "JSValue.h"
+
 namespace JSC {
 
     class ArgList;
     class ExecState;
     class FunctionExecutable;
     class JSObject;
 namespace JSC {
 
     class ArgList;
     class ExecState;
     class FunctionExecutable;
     class JSObject;
-    class JSValue;
     class ScopeChainNode;
 
     enum ConstructType {
     class ScopeChainNode;
 
     enum ConstructType {
@@ -44,7 +45,7 @@ namespace JSC {
         ConstructTypeJS
     };
 
         ConstructTypeJS
     };
 
-    typedef JSObject* (*NativeConstructor)(ExecState*, JSObject*, const ArgList&);
+    typedef EncodedJSValue (JSC_HOST_CALL *NativeConstructor)(ExecState*);
 
     union ConstructData {
         struct {
 
     union ConstructData {
         struct {
index ab95d0668d16f75afababea2872f155fbaeef276..8fb5aef44abc83d1c021c760a854dfb3e1b57bc6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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 "JSString.h"
 #include "JSStringBuilder.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
 #include <math.h>
 #include <time.h>
 #include <wtf/DateMath.h>
 #include <math.h>
 #include <time.h>
 #include <wtf/DateMath.h>
@@ -52,26 +51,47 @@ using namespace WTF;
 
 namespace JSC {
 
 
 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
 }
 
 // ECMA 15.9.3
-JSObject* constructDate(ExecState* exec, const ArgList& args)
+JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args)
 {
     int numArgs = args.size();
 
 {
     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 (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);
             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 {
                 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;
             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.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;
             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);
         }
     }
 
             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)
 }
 
 ConstructType DateConstructor::getConstructData(ConstructData& constructData)
@@ -128,7 +158,7 @@ ConstructType DateConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.9.2
 }
 
 // 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;
 {
     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);
     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)
 }
 
 CallType DateConstructor::getCallData(CallData& callData)
@@ -147,38 +177,47 @@ CallType DateConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     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;
 
     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.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
 }
 
 } // namespace JSC
index 10e450e7cd2b59d2acc3b5526e03a0f8fc2d5906..63e78cf9a1d02974cb5c57275008edb3f9223ecf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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:
 
     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&);
 
     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
 
 
 } // namespace JSC
 
index 70dbaa0306362cbb5d698336be7877f7f189ce48..1418876ed1492c1dce52ad9d7a80936a6ca8bc1e 100644 (file)
 #include "DateConversion.h"
 
 #include "CallFrame.h"
 #include "DateConversion.h"
 
 #include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 #include "UString.h"
 #include <wtf/DateMath.h>
 #include <wtf/StringExtras.h>
 #include "UString.h"
 #include <wtf/DateMath.h>
 #include <wtf/StringExtras.h>
+#include <wtf/text/CString.h>
 
 using namespace WTF;
 
 
 using namespace WTF;
 
@@ -56,7 +59,9 @@ double parseDate(ExecState* exec, const UString &date)
 {
     if (date == exec->globalData().cachedDateString)
         return exec->globalData().cachedDateStringValue;
 {
     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;
     exec->globalData().cachedDateString = date;
     exec->globalData().cachedDateStringValue = value;
     return value;
index b43b183e27ea3974066e1e2d3fab74d16e84d55c..d8ca072491b8583dfc81e1295a2d8b392a6447df 100644 (file)
@@ -32,24 +32,20 @@ using namespace WTF;
 
 namespace JSC {
 
 
 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
 }
 
 const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const
index 77d46de5df7d5e155e7e513359e38e02f149a0df..6195c8549f5534c575fe880ebfc1c7fdc2a93669 100644 (file)
@@ -31,13 +31,12 @@ namespace JSC {
 
     class DateInstance : public JSWrapperObject {
     public:
 
     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(); }
 
 
         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
         {
 
         const GregorianDateTime* gregorianDateTime(ExecState* exec) const
         {
@@ -53,18 +52,14 @@ namespace JSC {
             return calculateGregorianDateTimeUTC(exec);
         }
 
             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;
     private:
         const GregorianDateTime* calculateGregorianDateTime(ExecState*) const;
         const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const;
-        virtual const ClassInfo* classInfo() const { return &info; }
 
         mutable RefPtr<DateInstanceData> m_data;
     };
 
         mutable RefPtr<DateInstanceData> m_data;
     };
@@ -73,7 +68,7 @@ namespace JSC {
 
     inline DateInstance* asDateInstance(JSValue value)
     {
 
     inline DateInstance* asDateInstance(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&DateInstance::info));
+        ASSERT(asObject(value)->inherits(&DateInstance::s_info));
         return static_cast<DateInstance*>(asObject(value));
     }
 
         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& lookup(double d) { return m_cache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; }
 
-        CacheEntry m_cache[cacheSize];
+        FixedArray<CacheEntry, cacheSize> m_cache;
     };
 
 } // namespace JSC
     };
 
 } // 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) 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
  *
  *  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 <limits.h>
 #include <locale.h>
 #include <math.h>
+#include <stdlib.h>
 #include <time.h>
 #include <wtf/Assertions.h>
 #include <wtf/DateMath.h>
 #include <time.h>
 #include <wtf/Assertions.h>
 #include <wtf/DateMath.h>
@@ -69,52 +71,51 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(DatePrototype);
 
 
 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)?
  
 
 // 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)
 {
 
 static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateFormatterStyle defaultStyle)
 {
@@ -141,7 +142,7 @@ static CFDateFormatterStyle styleFromArgString(const UString& string, CFDateForm
     return defaultStyle;
 }
 
     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);
 {
     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;
 
     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;
         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);
         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);
         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();
         timeStyle = styleFromArgString(arg0String, timeStyle);
 
     CFLocaleRef locale = CFLocaleCopyCurrent();
@@ -166,7 +167,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     CFRelease(locale);
 
     if (useCustomFormat) {
     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);
     }
         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];
     // 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)
     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])
 // 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;
 {
     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)
     
     // 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;
     // 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;
     }
 
     // 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;
     }
     
     // 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)
     }
     
     if (!ok)
@@ -229,7 +236,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, const ArgList& args, in
         
     // milliseconds
     if (idx < numArgs) {
         
     // milliseconds
     if (idx < numArgs) {
-        double millis = args.at(idx).toNumber(exec);
+        double millis = exec->argument(idx).toIntegerPreserveNaN(exec);
         ok = isfinite(millis);
         milliseconds += millis;
     } else
         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])
 // 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 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
   
     // 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
     // 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
     // days
-    if (idx < numArgs && ok) {   
+    if (idx < numArgs && ok) {
+        double days = exec->argument(idx++).toIntegerPreserveNaN(exec);
+        ok = isfinite(days);
         t->monthDay = 0;
         t->monthDay = 0;
-        *ms += args.at(idx).toInt32(exec, ok) * msPerDay;
+        *ms += days * msPerDay;
     }
     
     return ok;
 }
 
     }
     
     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
 
 /* 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
   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
 
 @end
 */
 
 // ECMA 15.9.4
 
-DatePrototype::DatePrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+DatePrototype::DatePrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
     : DateInstance(exec, structure)
 {
     : DateInstance(exec, structure)
 {
+    ASSERT(inherits(&s_info));
+
     // The constructor will be added later, after DateConstructor has been built.
     // 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)
 }
 
 bool DatePrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -344,390 +360,419 @@ bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier&
 
 // Functions
 
 
 // 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)
 
     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);
     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)
 
     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);
     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)
     
     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;
     // 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)
 
     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);
     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)
 
     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);
     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); 
 
     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); 
 
     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); 
 
     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)
 
     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)
 
     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)
 
     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);
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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)
 
     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))
 
     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;
 
     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))
 
     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;
 
     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)
 
     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); 
 
 
     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();
     
 
     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);
     }
      
     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)
         ? thisDateObj->gregorianDateTimeUTC(exec)
         : thisDateObj->gregorianDateTime(exec);
     if (!other)
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
 
     GregorianDateTime gregorianDateTime;
     gregorianDateTime.copyFrom(*other);
 
     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);
 
     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();
     }      
     
     double milli = thisDateObj->internalNumber();
@@ -776,115 +822,116 @@ static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const
             ? thisDateObj->gregorianDateTimeUTC(exec)
             : thisDateObj->gregorianDateTime(exec);
         if (!other)
             ? thisDateObj->gregorianDateTimeUTC(exec)
             : thisDateObj->gregorianDateTime(exec);
         if (!other)
-            return jsNaN(exec);
+            return JSValue::encode(jsNaN());
         gregorianDateTime.copyFrom(*other);
     }
     
         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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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;
 {
     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);     
 
     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();
     }
     
     double milli = thisDateObj->internalNumber();
@@ -902,56 +949,57 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t
             gregorianDateTime.copyFrom(*other);
     }
     
             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)
 
     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.
 
     // 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())
     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())
     
     JSValue toISOValue = object->get(exec, exec->globalData().propertyNames->toISOString);
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
 
     CallData callData;
 
     CallData callData;
-    CallType callType = toISOValue.getCallData(callData);
+    CallType callType = getCallData(toISOValue, callData);
     if (callType == CallTypeNone)
     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())
 
     JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
     if (result.isObject())
     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
 }
 
 } // namespace JSC
index 612ca06a4e9ca871906c3646bab6b44d26a2a9ab..2e1030dffbd186973e2bb9d9406d4f04cd304312 100644 (file)
@@ -29,22 +29,23 @@ namespace JSC {
 
     class DatePrototype : public DateInstance {
     public:
 
     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 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;
 
         }
 
     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
     };
 
 } // namespace JSC
index 69464b75fd5fc552987b84e34859d6c9301b8460..7eda19f54bc650f021b760a641a9f216bead74f8 100644 (file)
 #include "JSObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
 #include "JSObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
+#include "SourceCode.h"
 
 namespace JSC {
 
 
 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)
     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())
     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;
 }
 
 
     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;
 }
 
     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;
 }
 
     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
 }
 
 } // namespace JSC
index e959cff6a573b2cd5bfd79fbd8fec99bfda7a3ab..c0f9d32098b1666adf39bdb40d3f84bf100f7d8c 100644 (file)
 #ifndef Error_h
 #define Error_h
 
 #ifndef Error_h
 #define Error_h
 
+#include "JSObject.h"
 #include <stdint.h>
 
 namespace JSC {
 
     class ExecState;
 #include <stdint.h>
 
 namespace JSC {
 
     class ExecState;
+    class JSGlobalData;
+    class JSGlobalObject;
     class JSObject;
     class JSObject;
+    class SourceCode;
+    class Structure;
     class UString;
 
     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*);
 
     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
 } // namespace JSC
 
 #endif // Error_h
index b9c3f586c298e4bb6af60ba0c24cf237c6241e61..df112dd2221f9c98f7bde90bc0bc8e913024be11 100644 (file)
@@ -29,26 +29,21 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor);
 
 
 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
 {
     // 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
 }
 
 // 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)
 }
 
 ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
@@ -57,11 +52,11 @@ ConstructType ErrorConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
     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)
 }
 
 CallType ErrorConstructor::getCallData(CallData& callData)
index e3d789b0d60864544ef5b4029fdf9418f06a452c..ceec005be802fd3529141146072bf21c537eaf82 100644 (file)
@@ -30,15 +30,13 @@ namespace JSC {
 
     class ErrorConstructor : public InternalFunction {
     public:
 
     class ErrorConstructor : public InternalFunction {
     public:
-        ErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, ErrorPrototype*);
+        ErrorConstructor(ExecState*, JSGlobalObject*, Structure*, ErrorPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
-    ErrorInstance* constructError(ExecState*, const ArgList&);
-
 } // namespace JSC
 
 #endif // ErrorConstructor_h
 } // namespace JSC
 
 #endif // ErrorConstructor_h
index 1cdb87a5a9169c925ffc67e4b47efa50184351aa..ed95ba4a1778def2a4aae986e40e2b0f82154791 100644 (file)
 
 namespace JSC {
 
 
 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
 }
 
 } // namespace JSC
index 9f53b5154a345d923a430a944ee901a5e23d33bf..afcf158ad3ae7e70ce384dca44c54e574ef9e85d 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class ErrorInstance : public JSObject {
+    class ErrorInstance : public JSNonFinalObject {
     public:
     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
     };
 
 } // namespace JSC
index eb357337ce22e2a7ca4f73e6b29810f443e52151..2a513d59c7ae9ff12695098d08f77fc4916656e1 100644 (file)
 #include "JSString.h"
 #include "JSStringBuilder.h"
 #include "ObjectPrototype.h"
 #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);
 
 #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);
 
     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())
 
     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())
     }
     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
 }
 
 } // namespace JSC
index a5615902d30142b953a8af2275162cd6ea957747..a5c88634fb7cfa1dcc18538641779654aefd577b 100644 (file)
@@ -29,7 +29,22 @@ namespace JSC {
 
     class ErrorPrototype : public ErrorInstance {
     public:
 
     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
     };
 
 } // namespace JSC
index aee6f31255c734c36be9b83556319f2740f09386..1d743153ca176ae51513aacdffdb2d62887bc736 100644 (file)
 
 #include "CodeBlock.h"
 #include "CallFrame.h"
 
 #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 "JSGlobalObjectFunctions.h"
 #include "JSObject.h"
 #include "JSNotAnObject.h"
 #include "Interpreter.h"
 #include "Nodes.h"
+#include "UStringConcatenate.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-class InterruptedExecutionError : public JSObject {
+class InterruptedExecutionError : public JSNonFinalObject {
 public:
     InterruptedExecutionError(JSGlobalData* globalData)
 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."; }
 };
 
     virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; }
 };
 
-JSValue createInterruptedExecutionException(JSGlobalData* globalData)
+JSObject* createInterruptedExecutionException(JSGlobalData* globalData)
 {
     return new (globalData) InterruptedExecutionError(globalData);
 }
 
 {
     return new (globalData) InterruptedExecutionError(globalData);
 }
 
-class TerminatedExecutionError : public JSObject {
+class TerminatedExecutionError : public JSNonFinalObject {
 public:
     TerminatedExecutionError(JSGlobalData* globalData)
 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."; }
 };
 
     virtual UString toString(ExecState*) const { return "JavaScript execution terminated."; }
 };
 
-JSValue createTerminatedExecutionException(JSGlobalData* globalData)
+JSObject* createTerminatedExecutionException(JSGlobalData* globalData)
 {
     return new (globalData) TerminatedExecutionError(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;
 }
 
     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;
 }
 
     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;
 }
 
     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
 }
 
 } // namespace JSC
index b15243922c543b142a712bbd0962cf121f9b3c32..5f1ec6f1c24443558239ff69e804a5f7249c1480 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef ExceptionHelpers_h
 #define ExceptionHelpers_h
 
 #ifndef ExceptionHelpers_h
 #define ExceptionHelpers_h
 
+#include "JSValue.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -36,23 +37,26 @@ namespace JSC {
     class ExecState;
     class Identifier;
     class JSGlobalData;
     class ExecState;
     class Identifier;
     class JSGlobalData;
+    class JSGlobalObject;
     class JSNotAnObjectErrorStub;
     class JSObject;
     class JSNotAnObjectErrorStub;
     class JSObject;
-    class JSValue;
     class Node;
     struct Instruction;
     
     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
 
 
 } // 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
  *
  * 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 "CodeBlock.h"
 #include "JIT.h"
 #include "Parser.h"
-#include "StringBuilder.h"
+#include "UStringBuilder.h"
 #include "Vector.h"
 
 #include "Vector.h"
 
+#if ENABLE(DFG_JIT)
+#include "DFGByteCodeParser.h"
+#include "DFGJITCompiler.h"
+#endif
+
 namespace JSC {
 
 namespace JSC {
 
+const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 };
+
 #if ENABLE(JIT)
 #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
 }
 #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()
 {
 {
 }
 
 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()
 {
 }
 
 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);
 
     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();
     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;
 }
 
     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 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)
 #if ENABLE(INTERPRETER)
-    ASSERT(scopeChainNode->globalData->canUseJIT());
+    if (!m_jitCodeForCall)
+        Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_programCodeBlock));
+    else
 #endif
 #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
 #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
 }
 
 #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
 #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
 }
-
 #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)
     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(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
 #endif
-    {
-        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), generatedJITCode().start());
-        ASSERT(newJITCode.size() == generatedJITCode().size());
     }
 #endif
 
     }
 #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(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
 #endif
-    {
-        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), generatedJITCode().start());
-        ASSERT(newJITCode.size() == generatedJITCode().size());
     }
 #endif
 
     }
 #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)
 #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
 #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;
         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());
     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());
     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);
     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;
 }
 
 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());
     }
     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
  *
  * 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
 
 #ifndef Executable_h
 #define Executable_h
 
+#include "CallData.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "Nodes.h"
 #include "SamplingTool.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;
 
 namespace JSC {
 
     class CodeBlock;
     class Debugger;
     class EvalCodeBlock;
+    class FunctionCodeBlock;
     class ProgramCodeBlock;
     class ScopeChainNode;
 
     struct ExceptionInfo;
 
     class ProgramCodeBlock;
     class ScopeChainNode;
 
     struct ExceptionInfo;
 
-    class ExecutableBase : public RefCounted<ExecutableBase> {
+    class ExecutableBase : public JSCell {
         friend class JIT;
 
     protected:
         friend class JIT;
 
     protected:
@@ -49,67 +52,124 @@ namespace JSC {
         static const int NUM_PARAMETERS_NOT_COMPILED = -1;
     
     public:
         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:
 
     protected:
-        int m_numParameters;
+        static const unsigned StructureFlags = 0;
+        int m_numParametersForCall;
+        int m_numParametersForConstruct;
 
 #if ENABLE(JIT)
     public:
 
 #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:
         }
 
     protected:
-        JITCode m_jitCode;
+        JITCode m_jitCodeForCall;
+        JITCode m_jitCodeForConstruct;
+        MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
+        MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
+        
+    private:
+        static WeakHandleOwner* executableFinalizer();
 #endif
     };
 
 #endif
     };
 
-#if ENABLE(JIT)
     class NativeExecutable : public ExecutableBase {
     class NativeExecutable : public ExecutableBase {
+        friend class JIT;
     public:
     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();
 
         ~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:
     };
 
     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_source(source)
-            , m_features(0)
+            , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
 #if ENABLE(CODEBLOCK_SAMPLING)
         {
 #if ENABLE(CODEBLOCK_SAMPLING)
+            relaxAdoptionRequirement();
             if (SamplingTool* sampler = globalData->interpreter->sampler())
                 sampler->notifyOfScope(this);
 #else
             if (SamplingTool* sampler = globalData->interpreter->sampler())
                 sampler->notifyOfScope(this);
 #else
@@ -117,12 +177,13 @@ namespace JSC {
 #endif
         }
 
 #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_source(source)
-            , m_features(0)
+            , m_features(isInStrictContext ? StrictModeFeature : 0)
         {
 #if ENABLE(CODEBLOCK_SAMPLING)
         {
 #if ENABLE(CODEBLOCK_SAMPLING)
+            relaxAdoptionRequirement();
             if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
                 sampler->notifyOfScope(this);
 #else
             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 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:
     protected:
-        void recordParse(CodeFeatures features, int firstLine, int lastLine)
+        void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine)
         {
             m_features = features;
         {
             m_features = features;
+            m_hasCapturedVariables = hasCapturedVariables;
             m_firstLine = firstLine;
             m_lastLine = lastLine;
         }
 
         SourceCode m_source;
         CodeFeatures m_features;
             m_firstLine = firstLine;
             m_lastLine = lastLine;
         }
 
         SourceCode m_source;
         CodeFeatures m_features;
+        bool m_hasCapturedVariables;
         int m_firstLine;
         int m_lastLine;
     };
         int m_firstLine;
         int m_lastLine;
     };
@@ -161,182 +226,219 @@ namespace JSC {
 
         ~EvalExecutable();
 
 
         ~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)
 
 #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
 #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:
     };
 
     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();
 
         }
 
         ~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*);
             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:
 
     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:
     };
 
     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);
         }
         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;
         bool m_forceUsesArguments : 1;
+        void unlinkCalls();
 
         RefPtr<FunctionParameters> m_parameters;
 
         RefPtr<FunctionParameters> m_parameters;
-        CodeBlock* m_codeBlock;
+        OwnPtr<FunctionCodeBlock> m_codeBlockForCall;
+        OwnPtr<FunctionCodeBlock> m_codeBlockForConstruct;
         Identifier m_name;
         Identifier m_name;
+        SharedSymbolTable* m_symbolTable;
 
 #if ENABLE(JIT)
     public:
 
 #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
     };
 
 #endif
     };
 
@@ -352,6 +454,11 @@ namespace JSC {
         return m_executable->isHostFunction();
     }
 
         return m_executable->isHostFunction();
     }
 
+    inline NativeFunction JSFunction::nativeFunction()
+    {
+        ASSERT(isHostFunction());
+        return static_cast<NativeExecutable*>(m_executable.get())->function();
+    }
 }
 
 #endif
 }
 
 #endif
index 9b0b1bbe46cbd8e03b630a79c1095f47ca5d876f..348d04ea4fe3b23b94604c41d3b18c8a61e641b8 100644 (file)
@@ -22,6 +22,7 @@
 #include "FunctionConstructor.h"
 
 #include "Debugger.h"
 #include "FunctionConstructor.h"
 
 #include "Debugger.h"
+#include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "FunctionPrototype.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "Lexer.h"
 #include "Nodes.h"
 #include "Parser.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);
 
 
 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
 
     // 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)
 }
 
 ConstructType FunctionConstructor::getConstructData(ConstructData& constructData)
@@ -55,9 +58,10 @@ ConstructType FunctionConstructor::getConstructData(ConstructData& constructData
     return ConstructTypeHost;
 }
 
     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
 }
 
 // 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
 }
 
 // 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
 {
     // 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)
     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 {
     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++) {
         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})");
         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);
     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
 }
 
 // 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
 }
 
 } // namespace JSC
index 197f320c2896627872741ebf57ca1e94b0043263..ba112b9fc7951571ed1cc700a26bbb7c80921e0e 100644 (file)
@@ -29,15 +29,17 @@ namespace JSC {
 
     class FunctionConstructor : public InternalFunction {
     public:
 
     class FunctionConstructor : public InternalFunction {
     public:
-        FunctionConstructor(ExecState*, NonNullPassRefPtr<Structure>, FunctionPrototype*);
+        FunctionConstructor(ExecState*, JSGlobalObject*, Structure*, FunctionPrototype*);
 
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     };
 
 
     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
 
 
 } // namespace JSC
 
index a77b5b27e9d1a856b4e808701274887375e1946d..e2a49416ddee3c4b75f1fa326075583517957f2b 100644 (file)
 #include "JSStringBuilder.h"
 #include "Interpreter.h"
 #include "Lexer.h"
 #include "JSStringBuilder.h"
 #include "Interpreter.h"
 #include "Lexer.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
 
 
 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);
     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);
 }
 
     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
 }
 
 // ECMA 15.3.4
@@ -71,76 +70,80 @@ CallType FunctionPrototype::getCallData(CallData& callData)
 static inline void insertSemicolonIfNeeded(UString& functionBody)
 {
     ASSERT(functionBody[0] == '{');
 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 != '}')
         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;
         }
     }
 }
 
             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);
         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);
         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;
     CallData callData;
-    CallType callType = thisValue.getCallData(callData);
+    CallType callType = getCallData(thisValue, callData);
     if (callType == CallTypeNone)
     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())
 
     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);
             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
             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;
     CallData callData;
-    CallType callType = thisValue.getCallData(callData);
+    CallType callType = getCallData(thisValue, callData);
     if (callType == CallTypeNone)
     if (callType == CallTypeNone)
-        return throwError(exec, TypeError);
+        return throwVMTypeError(exec);
 
 
+    ArgList args(exec);
     ArgList callArgs;
     args.getSlice(1, callArgs);
     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
 }
 
 } // namespace JSC
index af783f7b2b3be2678d79ed25bf273714c0488cbd..ab708dd7de33a1900a43b0aa58ec6caa6d5117b5 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class PrototypeFunction;
-
     class FunctionPrototype : public InternalFunction {
     public:
     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:
         }
 
     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 {
 
 
 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)
 
     if (m_getter)
-        markStack.append(m_getter);
+        visitor.append(&m_getter);
     if (m_setter)
     if (m_setter)
-        markStack.append(m_setter);
+        visitor.append(&m_setter);
 }
 
 bool GetterSetter::isGetterSetter() const
 }
 
 bool GetterSetter::isGetterSetter() const
index 27ffbe78a76294e1cb1b566645ce56787a7a67ab..aca7e3cbb0272f1ff9dea99c60fe5cdbd309a1d2 100644 (file)
@@ -26,6 +26,7 @@
 #include "JSCell.h"
 
 #include "CallFrame.h"
 #include "JSCell.h"
 
 #include "CallFrame.h"
+#include "Structure.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -37,35 +38,36 @@ namespace JSC {
         friend class JIT;
     public:
         GetterSetter(ExecState* exec)
         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;
 
     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)
     {
     };
 
     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 "Identifier.h"
 
 #include "CallFrame.h"
+#include "JSObject.h"
 #include "NumericStrings.h"
 #include "NumericStrings.h"
+#include "ScopeChain.h"
 #include <new> // for placement new
 #include <string.h> // for strlen
 #include <wtf/Assertions.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;
 }
 
     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();
 {
     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;
 }
 
     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)
     {
 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);
     }
 
     {
         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;
     {
         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);
         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)
 {
     if (!c)
-        return UString::null().rep();
+        return 0;
     if (!c[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])));
 
     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;
 
     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.
 
     // 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();
 }
 
 
     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);
 }
 {
     return add(&exec->globalData(), c);
 }
@@ -149,18 +140,18 @@ struct UCharBuffer {
 struct IdentifierUCharBufferTranslator {
     static unsigned hash(const UCharBuffer& buf)
     {
 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);
     }
 
     {
         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;
     {
         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);
         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 (length == 1) {
         UChar c = s[0];
-        if (c <= 0xFF)
+        if (c <= maxSingleCharacterString)
             return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
     }
     if (!length)
             return add(globalData, globalData->smallStrings.singleCharacterStringRep(c));
     }
     if (!length)
-        return UString::Rep::empty();
+        return StringImpl::empty();
     UCharBuffer buf = {s, length}; 
     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;
 }
 
 
     // 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);
 }
 
 {
     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
 {
     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 (r->length() == 1) {
         UChar c = r->characters()[0];
-        if (c <= 0xFF)
+        if (c <= maxSingleCharacterString)
             r = globalData->smallStrings.singleCharacterStringRep(c);
             if (r->isIdentifier())
                 return r;
             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;
 }
 
     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);
 }
 {
     return addSlowCase(&exec->globalData(), r);
 }
@@ -228,6 +262,21 @@ Identifier Identifier::from(ExecState* exec, double value)
     return Identifier(exec, exec->globalData().numericStrings.add(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)
 #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 "JSGlobalData.h"
 #include "ThreadSpecific.h"
 #include "UString.h"
+#include <wtf/text/CString.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -34,38 +35,37 @@ namespace JSC {
     public:
         Identifier() { }
 
     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);
         
         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&);
         
         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*);
     
         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:
 
     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);
         {
 #ifndef NDEBUG
             checkCurrentIdentifierTable(exec);
@@ -98,7 +98,7 @@ namespace JSC {
                 return r;
             return addSlowCase(exec, r);
         }
                 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);
         {
 #ifndef NDEBUG
             checkCurrentIdentifierTable(globalData);
@@ -108,8 +108,8 @@ namespace JSC {
             return addSlowCase(globalData, r);
         }
 
             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*);
 
         static void checkCurrentIdentifierTable(ExecState*);
         static void checkCurrentIdentifierTable(JSGlobalData*);
@@ -135,9 +135,25 @@ namespace JSC {
         return !Identifier::equal(a, b);
     }
 
         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*);
 
     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
 } // namespace JSC
 
 #endif // Identifier_h
index 51d43ee224c3b42d178392a8a784dac0e6d72965..27611b757b34be5c564ce03bb0553ba736e64660 100644 (file)
@@ -29,7 +29,7 @@
 #include "config.h"
 #include "InitializeThreading.h"
 
 #include "config.h"
 #include "InitializeThreading.h"
 
-#include "Collector.h"
+#include "Heap.h"
 #include "dtoa.h"
 #include "Identifier.h"
 #include "JSGlobalObject.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()
 {
 
 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();
     WTF::initializeThreading();
     wtfThreadData();
-    initializeUString();
     JSGlobalData::storeVPtrs();
 #if ENABLE(JSC_MULTIPLE_THREADS)
     s_dtoaP5Mutex = new Mutex;
     initializeDates();
     JSGlobalData::storeVPtrs();
 #if ENABLE(JSC_MULTIPLE_THREADS)
     s_dtoaP5Mutex = new Mutex;
     initializeDates();
+    RegisterFile::initializeThreading();
 #endif
 }
 
 #endif
 }
 
index f68e795f31cbd8b0a298a35c31e5a26b056f8f22..c3b07f8297028e96f2ff503d95178f1ccf98f6ae 100644 (file)
 #include "InternalFunction.h"
 
 #include "FunctionPrototype.h"
 #include "InternalFunction.h"
 
 #include "FunctionPrototype.h"
+#include "JSGlobalObject.h"
 #include "JSString.h"
 
 namespace JSC {
 
 #include "JSString.h"
 
 namespace JSC {
 
+// Ensure the compiler generates a vtable for InternalFunction!
+void InternalFunction::vtableAnchor() {}
+
 ASSERT_CLASS_FITS_IN_CELL(InternalFunction);
 
 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)
 {
 }
 
 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)
 {
 }
 
 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();
     
     
     if (displayName && isJSString(&exec->globalData(), displayName))
         return asString(displayName)->tryGetValue();
     
-    return UString::null();
+    return UString();
 }
 
 const UString InternalFunction::calculatedDisplayName(ExecState* exec)
 }
 
 const UString InternalFunction::calculatedDisplayName(ExecState* exec)
index d19b82b38aae2332cf86420aa7b5a0308f309918..28e260e30130ddd8c0ae796d663337298fe9cfa1 100644 (file)
 #ifndef InternalFunction_h
 #define InternalFunction_h
 
 #ifndef InternalFunction_h
 #define InternalFunction_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 #include "Identifier.h"
 
 namespace JSC {
 
     class FunctionPrototype;
 
 #include "Identifier.h"
 
 namespace JSC {
 
     class FunctionPrototype;
 
-    class InternalFunction : public JSObject {
+    class InternalFunction : public JSObjectWithGlobalObject {
     public:
     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*);
 
 
         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;
 
         }
 
     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;
 
     private:
         virtual CallType getCallData(CallData&) = 0;
+
+        virtual void vtableAnchor();
     };
 
     InternalFunction* asInternalFunction(JSValue);
 
     inline InternalFunction* asInternalFunction(JSValue value)
     {
     };
 
     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));
     }
 
         return static_cast<InternalFunction*>(asObject(value));
     }
 
index e83724a1da19391ead6accbb8f0653e96c547327..9a92a9311cea954139a7c0620f89c8c756e7bc57 100644 (file)
@@ -28,4 +28,6 @@
 
 namespace JSC {
 
 
 namespace JSC {
 
+const ClassInfo JSAPIValueWrapper::s_info = { "API Wrapper", 0, 0, 0 };
+
 } // namespace JSC
 } // namespace JSC
index 10ded4cd4418bd9bcd8f3c10c57d9bae50f6f81f..38cbb569e3691eadd8fe1a3289f5285e8d1b0cce 100644 (file)
 
 #include "JSCell.h"
 #include "CallFrame.h"
 
 #include "JSCell.h"
 #include "CallFrame.h"
+#include "Structure.h"
 
 namespace JSC {
 
     class JSAPIValueWrapper : public JSCell {
         friend JSValue jsAPIValueWrapper(ExecState*, JSValue);
     public:
 
 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; }
 
 
         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)
     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());
         }
 
             ASSERT(!value.isCell());
         }
 
-        JSValue m_value;
+        WriteBarrier<Unknown> m_value;
     };
 
     inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue 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);
 
 
 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()
 {
 }
 
 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;
 
     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;
         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 (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());
     // 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;
 }
 
     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));
 
 {
     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());
         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
 }
 
 // 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));
 
 {
     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 
         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();
 }
 
     return exec->globalThisValue();
 }
 
+JSValue JSActivation::toStrictThisObject(ExecState*) const
+{
+    return jsNull();
+}
+    
 bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
 {
 bool JSActivation::isDynamicScope(bool& requiresDynamicChecks) const
 {
-    requiresDynamicChecks = d()->functionExecutable->usesEval();
+    requiresDynamicChecks = m_requiresDynamicChecks;
     return false;
 }
 
     return false;
 }
 
-JSValue JSActivation::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
+JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
 {
     JSActivation* activation = asActivation(slotBase);
 {
     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
 }
 
 // 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:
     class JSActivation : public JSVariableObject {
         typedef JSVariableObject Base;
     public:
-        JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>);
+        JSActivation(CallFrame*, FunctionExecutable*);
         virtual ~JSActivation();
 
         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 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&);
 
 
         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 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:
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
 
     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();
 
         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)
     {
     };
 
     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));
     }
         return static_cast<JSActivation*>(asObject(value));
     }
+    
+    ALWAYS_INLINE JSActivation* Register::activation() const
+    {
+        return asActivation(jsValue());
+    }
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index eb778ed2a12af2ef10f6d46ab4098df0cc42248e..6bc316363ad3ee98dd6c969a4be1a7c32115579b 100644 (file)
@@ -33,8 +33,6 @@
 #include <wtf/OwnPtr.h>
 #include <Operations.h>
 
 #include <wtf/OwnPtr.h>
 #include <Operations.h>
 
-#define CHECK_ARRAY_CONSISTENCY 0
-
 using namespace std;
 using namespace WTF;
 
 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
 
 // 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;
 
 // 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)
 {
 
 static inline size_t storageSize(unsigned vectorLength)
 {
@@ -102,21 +113,6 @@ static inline size_t storageSize(unsigned vectorLength)
     return size;
 }
 
     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;
 static inline bool isDenseEnoughForVector(unsigned length, unsigned numValues)
 {
     return length / minDensityMultiplier <= numValues;
@@ -130,60 +126,109 @@ inline void JSArray::checkConsistency(ConsistencyCheckType)
 
 #endif
 
 
 #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)));
     unsigned initialCapacity = 0;
 
     m_storage = static_cast<ArrayStorage*>(fastZeroedMalloc(storageSize(initialCapacity)));
+    m_storage->m_allocBase = m_storage;
+    m_indexBias = 0;
     m_vectorLength = initialCapacity;
 
     checkConsistency();
     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 = static_cast<ArrayStorage*>(fastMalloc(storageSize(initialCapacity)));
+    m_storage->m_allocBase = m_storage;
     m_storage->m_length = initialLength;
     m_storage->m_length = initialLength;
+    m_indexBias = 0;
     m_vectorLength = initialCapacity;
     m_vectorLength = initialCapacity;
-    m_storage->m_numValuesInVector = 0;
     m_storage->m_sparseValueMap = 0;
     m_storage->subclassData = 0;
     m_storage->reportedMapCapacity = 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();
 
     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_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;
     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;
 
     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)
     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();
 
 
     checkConsistency();
 
-    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialCapacity));
+    Heap::heap(this)->reportExtraMemoryCost(storageSize(initialStorage));
 }
 
 JSArray::~JSArray()
 }
 
 JSArray::~JSArray()
@@ -192,13 +237,13 @@ JSArray::~JSArray()
     checkConsistency(DestructorConsistencyCheck);
 
     delete m_storage->m_sparseValueMap;
     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;
 }
 
 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);
     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) {
     }
 
     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()) {
             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;
             }
         }
                 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) {
 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;
         return true;
     }
 
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex)
         return JSArray::getOwnPropertySlot(exec, i, slot);
 
     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) {
 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;
     }
         return true;
     }
+
+    ArrayStorage* storage = m_storage;
     
     bool isArrayIndex;
     
     bool isArrayIndex;
-    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
+    unsigned i = propertyName.toArrayIndex(isArrayIndex);
     if (isArrayIndex) {
     if (isArrayIndex) {
-        if (i >= m_storage->m_length)
+        if (i >= storage->m_length)
             return false;
         if (i < m_vectorLength) {
             return false;
         if (i < m_vectorLength) {
-            JSValue& value = m_storage->m_vector[i];
+            WriteBarrier<Unknown>& value = storage->m_vector[i];
             if (value) {
             if (value) {
-                descriptor.setDescriptor(value, 0);
+                descriptor.setDescriptor(value.get(), 0);
                 return true;
             }
                 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()) {
             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;
                 }
             }
                     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;
 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;
     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)) {
     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);
             return;
         }
         setLength(newLength);
@@ -297,21 +344,23 @@ void JSArray::put(ExecState* exec, unsigned i, JSValue value)
 {
     checkConsistency();
 
 {
     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;
     if (i >= length && i <= MAX_ARRAY_INDEX) {
         length = i + 1;
-        m_storage->m_length = length;
+        storage->m_length = length;
     }
 
     if (i < m_vectorLength) {
     }
 
     if (i < m_vectorLength) {
-        JSValue& valueSlot = m_storage->m_vector[i];
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
         if (valueSlot) {
         if (valueSlot) {
-            valueSlot = value;
+            valueSlot.set(exec->globalData(), this, value);
             checkConsistency();
             return;
         }
             checkConsistency();
             return;
         }
-        valueSlot = value;
-        ++m_storage->m_numValuesInVector;
+        valueSlot.set(exec->globalData(), this, value);
+        ++storage->m_numValuesInVector;
         checkConsistency();
         return;
     }
         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;
 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) {
     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;
             }
 
                 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;
                 return;
-            }
 
             size_t capacity = map->capacity();
             if (capacity != storage->reportedMapCapacity) {
 
             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;
     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
             ++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;
 
     // 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)) {
     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.
         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))
             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;
     }
 
         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;
     unsigned vectorLength = m_vectorLength;
+    WriteBarrier<Unknown>* vector = storage->m_vector;
 
     if (newNumValuesInVector == storage->m_numValuesInVector + 1) {
         for (unsigned j = vectorLength; j < newVectorLength; ++j)
 
     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)
         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)
         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_vectorLength = newVectorLength;
     storage->m_numValuesInVector = newNumValuesInVector;
 
-    m_storage = storage;
+    storage->m_vector[i].set(exec->globalData(), this, value);
 
     checkConsistency();
 
 
     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;
 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);
 
     if (isArrayIndex)
         return deleteProperty(exec, i);
 
@@ -437,14 +496,14 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i)
     checkConsistency();
 
     ArrayStorage* storage = m_storage;
     checkConsistency();
 
     ArrayStorage* storage = m_storage;
-
+    
     if (i < m_vectorLength) {
     if (i < m_vectorLength) {
-        JSValue& valueSlot = storage->m_vector[i];
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[i];
         if (!valueSlot) {
             checkConsistency();
             return false;
         }
         if (!valueSlot) {
             checkConsistency();
             return false;
         }
-        valueSlot = JSValue();
+        valueSlot.clear();
         --storage->m_numValuesInVector;
         checkConsistency();
         return true;
         --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;
     // 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])
     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);
 }
 
     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
 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 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;
 
         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)
     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;
 }
 
     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;
     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) {
 
     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;
             bool hadValue = valueSlot;
-            valueSlot = JSValue();
+            valueSlot.clear();
             storage->m_numValuesInVector -= hadValue;
         }
 
             storage->m_numValuesInVector -= hadValue;
         }
 
@@ -553,7 +684,7 @@ void JSArray::setLength(unsigned newLength)
         }
     }
 
         }
     }
 
-    m_storage->m_length = newLength;
+    storage->m_length = newLength;
 
     checkConsistency();
 }
 
     checkConsistency();
 }
@@ -562,7 +693,9 @@ JSValue JSArray::pop()
 {
     checkConsistency();
 
 {
     checkConsistency();
 
-    unsigned length = m_storage->m_length;
+    ArrayStorage* storage = m_storage;
+    
+    unsigned length = storage->m_length;
     if (!length)
         return jsUndefined();
 
     if (!length)
         return jsUndefined();
 
@@ -571,29 +704,29 @@ JSValue JSArray::pop()
     JSValue result;
 
     if (length < m_vectorLength) {
     JSValue result;
 
     if (length < m_vectorLength) {
-        JSValue& valueSlot = m_storage->m_vector[length];
+        WriteBarrier<Unknown>& valueSlot = storage->m_vector[length];
         if (valueSlot) {
         if (valueSlot) {
-            --m_storage->m_numValuesInVector;
-            result = valueSlot;
-            valueSlot = JSValue();
+            --storage->m_numValuesInVector;
+            result = valueSlot.get();
+            valueSlot.clear();
         } else
             result = jsUndefined();
     } else {
         result = jsUndefined();
         } 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()) {
             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;
                 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();
 
 
     checkConsistency();
 
@@ -603,22 +736,25 @@ JSValue JSArray::pop()
 void JSArray::push(ExecState* exec, JSValue value)
 {
     checkConsistency();
 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;
     }
 
         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 (!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;
             }
                 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)
 }
 
 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);
 {
     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)
 {
 }
 
 void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType callType, const CallData& callData)
 {
+    ArrayStorage* storage = m_storage;
+
     unsigned lengthNotIncludingUndefined = compactForSorting();
     unsigned lengthNotIncludingUndefined = compactForSorting();
-    if (m_storage->m_sparseValueMap) {
+    if (storage->m_sparseValueMap) {
         throwOutOfMemoryError(exec);
         return;
     }
         throwOutOfMemoryError(exec);
         return;
     }
@@ -662,9 +896,9 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
         return;
         
     bool allValuesAreNumbers = true;
         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) {
     for (size_t i = 0; i < size; ++i) {
-        if (!m_storage->m_vector[i].isNumber()) {
+        if (!storage->m_vector[i].isNumber()) {
             allValuesAreNumbers = false;
             break;
         }
             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.
     // 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)
 {
 
     checkConsistency(SortConsistencyCheck);
 }
 
 void JSArray::sort(ExecState* exec)
 {
+    ArrayStorage* storage = m_storage;
+
     unsigned lengthNotIncludingUndefined = compactForSorting();
     unsigned lengthNotIncludingUndefined = compactForSorting();
-    if (m_storage->m_sparseValueMap) {
+    if (storage->m_sparseValueMap) {
         throwOutOfMemoryError(exec);
         return;
     }
         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++) {
     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;
     }
         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);
     // 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++)
     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);
     
 
     Heap::heap(this)->popTempSortVector(&values);
     
@@ -830,18 +1067,21 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 {
     checkConsistency();
 
 {
     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.
     // 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;
 
         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;
 
     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_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)
 
     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);
 
     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) {
 
     // 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) {
         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;
         if (v) {
             if (v.isUndefined())
                 ++numUndefined;
@@ -888,7 +1128,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
 
     unsigned newUsedVectorLength = numDefined + numUndefined;
 
 
     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.
         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;
             }
         }
                 return;
             }
         }
+        
+        storage = m_storage;
 
         SparseArrayValueMap::iterator end = map->end();
         for (SparseArrayValueMap::iterator it = map->begin(); it != end; ++it) {
 
         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;
             tree.insert(numDefined);
             ++numDefined;
         }
 
         delete map;
-        m_storage->m_sparseValueMap = 0;
+        storage->m_sparseValueMap = 0;
     }
 
     ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
     }
 
     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);
     // 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) {
     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)
         ++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)
 
     // 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)
 {
 
     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) {
     unsigned i = 0;
     for (; i < vectorEnd; ++i) {
-        JSValue& v = vector[i];
+        WriteBarrier<Unknown>& v = vector[i];
         if (!v)
             break;
         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));
 }
 
         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);
 {
     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) {
     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;
         if (!v)
             break;
-        buffer[i] = v;
+        buffer[i] = v.get();
     }
 
     for (; i < maxSize; ++i)
     }
 
     for (; i < maxSize; ++i)
@@ -975,23 +1220,24 @@ unsigned JSArray::compactForSorting()
 
     ArrayStorage* storage = m_storage;
 
 
     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) {
 
     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;
     }
         if (!v || v.isUndefined())
             break;
     }
+
     for (unsigned i = numDefined; i < usedVectorLength; ++i) {
     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
         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;
             // 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_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)
 
         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)
     for (unsigned i = newUsedVectorLength; i < usedVectorLength; ++i)
-        storage->m_vector[i] = JSValue();
+        storage->m_vector[i].clear();
 
     storage->m_numValuesInVector = newUsedVectorLength;
 
 
     storage->m_numValuesInVector = newUsedVectorLength;
 
@@ -1041,35 +1288,37 @@ void JSArray::setSubclassData(void* d)
 
 void JSArray::checkConsistency(ConsistencyCheckType type)
 {
 
 void JSArray::checkConsistency(ConsistencyCheckType type)
 {
-    ASSERT(m_storage);
+    ArrayStorage* storage = m_storage;
+
+    ASSERT(storage);
     if (type == SortConsistencyCheck)
     if (type == SortConsistencyCheck)
-        ASSERT(!m_storage->m_sparseValueMap);
+        ASSERT(!storage->m_sparseValueMap);
 
     unsigned numValuesInVector = 0;
     for (unsigned i = 0; i < m_vectorLength; ++i) {
 
     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)
             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)
             ++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;
             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)
             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"
 
 
 #include "JSObject.h"
 
+#define CHECK_ARRAY_CONSISTENCY 0
+
 namespace JSC {
 
 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 {
     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.
         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;
         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:
         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&);
         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.
 
         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.
 
         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 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));
         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; }
         }
 
         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));
         {
             ASSERT(canSetIndex(i));
-            JSValue& x = m_storage->m_vector[i];
+            
+            WriteBarrier<Unknown>& x = m_storage->m_vector[i];
             if (!x) {
             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);
 
         }
 
         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:
 
     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 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:
 
         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);
 
         bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
         void putSlowCase(ExecState*, unsigned propertyName, JSValue);
 
+        unsigned getNewVectorLength(unsigned desiredLength);
         bool increaseVectorLength(unsigned newLength);
         bool increaseVectorLength(unsigned newLength);
+        bool increaseVectorPrefixLength(unsigned newLength);
         
         unsigned compactForSorting();
 
         enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck };
         void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck);
 
         
         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)
     {
     };
 
     JSArray* asArray(JSValue);
 
     inline JSArray* asArray(JSCell* cell)
     {
-        ASSERT(cell->inherits(&JSArray::info));
+        ASSERT(cell->inherits(&JSArray::s_info));
         return static_cast<JSArray*>(cell);
     }
 
         return static_cast<JSArray*>(cell);
     }
 
@@ -134,93 +182,35 @@ namespace JSC {
         return asArray(value.asCell());
     }
 
         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, 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);
         
         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)
 
         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
 } // namespace JSC
 
 #endif // JSArray_h
index 803a08c97c23100f640c6904dbc04d3719de8d60..c2abaee1c8fbfc1eb846f9908d647d1aaa4e193d 100644 (file)
@@ -33,14 +33,13 @@ using namespace WTF;
 
 namespace JSC {
 
 
 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_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
 }
 
 #if !ASSERT_DISABLED
@@ -51,16 +50,15 @@ JSByteArray::~JSByteArray()
 #endif
 
 
 #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;
 }
 
 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;
     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;
 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;
     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;
 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;
     if (ok) {
         setIndex(exec, index, value);
         return;
index 5b7adcf88841da9f98e0534ecfa527fd867d1053..c481bb4c8b93ec1612971da1495a76e72bdf5b4d 100644 (file)
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class JSByteArray : public JSObject {
+    class JSByteArray : public JSNonFinalObject {
         friend class JSGlobalData;
     public:
         friend class JSGlobalData;
     public:
+        typedef JSNonFinalObject Base;
+
         bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
         bool canAccessIndex(unsigned i) { return i < m_storage->length(); }
-        JSValue getIndex(ExecState* exec, unsigned i)
+        JSValue getIndex(ExecState*, unsigned i)
         {
             ASSERT(canAccessIndex(i));
         {
             ASSERT(canAccessIndex(i));
-            return jsNumber(exec, m_storage->data()[i]);
+            return jsNumber(m_storage->data()[i]);
         }
 
         void setIndex(unsigned i, int value)
         }
 
         void setIndex(unsigned i, int value)
@@ -73,9 +75,9 @@ namespace JSC {
                 setIndex(i, byteValue);
         }
 
                 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&);
         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 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(); }
         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:
         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;
         {
         }
 
         RefPtr<WTF::ByteArray> m_storage;
-        const ClassInfo* m_classInfo;
     };
     
     JSByteArray* asByteArray(JSValue value);
     inline JSByteArray* asByteArray(JSValue value)
     {
     };
     
     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; }
     }
 
     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)
 
  
 #endif // !(defined NAN && defined INFINITY)
 
+const ClassInfo JSCell::s_dummyCellInfo = { "DummyCell", 0, 0, 0 };
+
 bool JSCell::getUInt32(uint32_t&) const
 {
     return false;
 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.
     // 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();
     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.
     // 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();
     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)
 {
 
 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)
 {
 }
 
 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)
 {
 }
 
 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)
 {
 }
 
 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
 {
 }
 
 JSObject* JSCell::toThisObject(ExecState* exec) const
 {
-    return toObject(exec);
-}
-
-const ClassInfo* JSCell::classInfo() const
-{
-    return 0;
+    return toObject(exec, exec->lexicalGlobalObject());
 }
 
 JSValue JSCell::getJSNumber()
 }
 
 JSValue JSCell::getJSNumber()
@@ -208,10 +205,25 @@ UString JSCell::toString(ExecState*) const
     return UString();
 }
 
     return UString();
 }
 
-JSObject* JSCell::toObject(ExecState*) const
+JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const
 {
     ASSERT_NOT_REACHED();
     return 0;
 }
 
 {
     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
 } // namespace JSC
index ae5aca3bf422eccde0516fce73fdc44cf66683f6..e30bc183ff69ce2396acef956e15ca566d15777d 100644 (file)
 #ifndef JSCell_h
 #define JSCell_h
 
 #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 "MarkStack.h"
-#include "Structure.h"
+#include "WriteBarrier.h"
 #include <wtf/Noncopyable.h>
 
 namespace JSC {
 
 #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 GetterSetter;
         friend class Heap;
-        friend class JIT;
-        friend class JSNumberCell;
         friend class JSObject;
         friend class JSPropertyNameIterator;
         friend class JSString;
         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 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:
 
     private:
-        explicit JSCell(Structure*);
+        explicit JSCell(VPtrStealingHackType) { }
+        JSCell(JSGlobalData&, Structure*);
+        JSCell(JSGlobalData&, Structure*, CreatingEarlyCellTag);
         virtual ~JSCell();
         virtual ~JSCell();
+        static const ClassInfo s_dummyCellInfo;
 
     public:
 
     public:
-        static PassRefPtr<Structure> createDummyStructure()
-        {
-            return Structure::create(jsNull(), TypeInfo(UnspecifiedType), AnonymousSlotCount);
-        }
+        static Structure* createDummyStructure(JSGlobalData&);
 
         // Querying the type.
 
         // Querying the type.
-#if USE(JSVALUE32)
-        bool isNumber() const;
-#endif
         bool isString() const;
         bool isObject() const;
         virtual bool isGetterSetter() const;
         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 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; }
 
 
         // 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.
 #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);
         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&);
 
         // 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;
 
     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&);
         
         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
 #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
     {
     }
 
     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 ----------------------------
     }
 
     // --- JSValue inlines ----------------------------
@@ -200,19 +226,28 @@ namespace JSC {
         return isCell() ? asCell()->getString(exec) : UString();
     }
 
         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 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
     }
 
     ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
@@ -230,14 +265,6 @@ namespace JSC {
         return false;
     }
 
         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();
     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.
     }
 
         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())
     inline JSValue JSValue::getJSNumber()
     {
         if (isInt32() || isDouble())
@@ -315,30 +335,17 @@ namespace JSC {
 
     inline JSObject* JSValue::toObject(ExecState* exec) const
     {
 
     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)
     }
 
     inline Heap* Heap::heap(JSValue v)
@@ -350,15 +357,76 @@ namespace JSC {
 
     inline Heap* Heap::heap(JSCell* c)
     {
 
     inline Heap* Heap::heap(JSCell* c)
     {
-        return cellBlock(c)->heap;
+        return MarkedSpace::heap(c);
     }
     
 #if ENABLE(JSC_ZOMBIES)
     inline bool JSValue::isZombie() const
     {
     }
     
 #if ENABLE(JSC_ZOMBIES)
     inline bool JSValue::isZombie() const
     {
-        return isCell() && asCell() && asCell()->isZombie();
+        return isCell() && asCell() > (JSCell*)0x1ffffffffL && asCell()->isZombie();
     }
 #endif
     }
 #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
 } // 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 "CodeBlock.h"
 #include "CommonIdentifiers.h"
 #include "CallFrame.h"
+#include "ExceptionHelpers.h"
 #include "FunctionPrototype.h"
 #include "JSGlobalObject.h"
 #include "FunctionPrototype.h"
 #include "JSGlobalObject.h"
+#include "JSNotAnObject.h"
 #include "Interpreter.h"
 #include "ObjectPrototype.h"
 #include "Parser.h"
 #include "Interpreter.h"
 #include "ObjectPrototype.h"
 #include "Parser.h"
@@ -40,86 +42,107 @@ using namespace WTF;
 using namespace Unicode;
 
 namespace JSC {
 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);
 
 
 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();
 }
 
 
 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);
 }
 
 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)
 }
 
 CallType JSFunction::getCallData(CallData& callData)
@@ -129,16 +152,10 @@ CallType JSFunction::getCallData(CallData& callData)
         return CallTypeHost;
     }
     callData.js.functionExecutable = jsExecutable();
         return CallTypeHost;
     }
     callData.js.functionExecutable = jsExecutable();
-    callData.js.scopeChain = scopeChain().node();
+    callData.js.scopeChain = scope();
     return CallTypeJS;
 }
 
     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);
 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);
 }
 
     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());
 {
     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)
 }
 
 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) {
         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 (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;
     }
         slot.setCacheableCustom(this, argumentsGetter);
         return true;
     }
@@ -189,6 +228,11 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN
     }
 
     if (propertyName == exec->propertyNames().caller) {
     }
 
     if (propertyName == exec->propertyNames().caller) {
+        if (jsExecutable()->isStrictMode()) {
+            throwTypeError(exec, StrictModeCallerAccessError);
+            slot.setValue(jsNull());
+            return true;
+        }
         slot.setCacheableCustom(this, callerGetter);
         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);
 }
 
     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);
             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);
             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)) {
 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);
         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;
     }
         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);
     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();
     if (isHostFunction())
         return ConstructTypeNone;
     constructData.js.functionExecutable = jsExecutable();
-    constructData.js.scopeChain = scopeChain().node();
+    constructData.js.scopeChain = scope();
     return ConstructTypeJS;
 }
 
     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
 } // namespace JSC
index 301b908117b550445a66c7e97422fea04b09de5b..42fd62a4d16c4b673a7fff64416f6539f2d08b4a 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef JSFunction_h
 #define JSFunction_h
 
 #ifndef JSFunction_h
 #define JSFunction_h
 
-#include "InternalFunction.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -34,24 +34,36 @@ namespace JSC {
     class JSActivation;
     class JSGlobalObject;
     class NativeExecutable;
     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;
 
         friend class JIT;
         friend class JSGlobalData;
 
-        typedef InternalFunction Base;
+        typedef JSObjectWithGlobalObject Base;
 
     public:
 
     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();
 
         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(); }
 
 
         ExecutableBase* executable() const { return m_executable.get(); }
 
@@ -59,76 +71,48 @@ namespace JSC {
         inline bool isHostFunction() const;
         FunctionExecutable* jsExecutable() const;
 
         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:
 
         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:
 
     private:
-        JSFunction(NonNullPassRefPtr<Structure>);
+        explicit JSFunction(VPtrStealingHackType);
 
         bool isHostFunctionNonInline() const;
 
 
         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 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&);
 
 
         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)
     {
     };
 
     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));
     }
 
         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
  *
  * 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 "JSGlobalData.h"
 
 #include "ArgList.h"
-#include "Collector.h"
-#include "CollectorHeapIterator.h"
+#include "Heap.h"
 #include "CommonIdentifiers.h"
 #include "CommonIdentifiers.h"
+#include "DebuggerActivation.h"
 #include "FunctionConstructor.h"
 #include "GetterSetter.h"
 #include "Interpreter.h"
 #include "FunctionConstructor.h"
 #include "GetterSetter.h"
 #include "Interpreter.h"
 #include "JSNotAnObject.h"
 #include "JSPropertyNameIterator.h"
 #include "JSStaticScopeObject.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 "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
 #include "Parser.h"
 #include "RegExpCache.h"
+#include "RegExpObject.h"
+#include "StrictEvalActivation.h"
 #include <wtf/WTFThreadData.h>
 #include <wtf/WTFThreadData.h>
+#if ENABLE(REGEXP_TRACING)
+#include "RegExp.h"
+#endif
+
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
 
 #if ENABLE(JSC_MULTIPLE_THREADS)
 #include <wtf/Threading.h>
 
 using namespace WTF;
 
 
 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 {
 
 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 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 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 regExpTable;
 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
+extern JSC_CONST_HASHTABLE HashTable regExpPrototypeTable;
 extern JSC_CONST_HASHTABLE HashTable stringTable;
 extern JSC_CONST_HASHTABLE HashTable stringTable;
+extern JSC_CONST_HASHTABLE HashTable stringConstructorTable;
 
 void* JSGlobalData::jsArrayVPtr;
 void* JSGlobalData::jsByteArrayVPtr;
 void* JSGlobalData::jsStringVPtr;
 void* JSGlobalData::jsFunctionVPtr;
 
 
 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()
 {
 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();
     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);
     JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
+    CLOBBER_MEMORY();
     JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
     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);
     JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
+    CLOBBER_MEMORY();
     JSGlobalData::jsStringVPtr = jsString->vptr();
     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();
     JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
-    jsFunction->~JSCell();
 }
 
 JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
     : globalDataType(globalDataType)
     , clientData(0)
 }
 
 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))
     , 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))
     , 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))
     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
+    , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
     , stringTable(fastNew<HashTable>(JSC::stringTable))
     , 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)
     , 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)
     , lexer(new Lexer(this))
     , parser(new Parser)
-    , interpreter(new Interpreter)
+    , interpreter(0)
     , heap(this)
     , heap(this)
-    , initializingLazyNumericCompareFunction(false)
-    , head(0)
+    , globalObjectCount(0)
     , dynamicGlobalObject(0)
     , dynamicGlobalObject(0)
-    , functionCodeBlockBeingReparsed(0)
-    , firstStringifierToMark(0)
-    , markStack(jsArrayVPtr)
     , cachedUTCOffset(NaN)
     , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
     , m_regExpCache(new RegExpCache(this))
     , 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
 {
 #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(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);
     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)
     CFRelease(canUseJITKey);
 #elif OS(UNIX)
-    m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
+    char* canUseJITString = getenv("JavaScriptCoreUseJIT");
+    m_canUseJIT = !canUseJITString || atoi(canUseJITString);
 #else
     m_canUseJIT = true;
 #endif
 #else
     m_canUseJIT = true;
 #endif
@@ -175,7 +260,36 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
     if (m_canUseJIT)
         m_canUseJIT = executableAllocator.isValid();
 #endif
     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
 }
 
 #endif
 }
 
@@ -189,23 +303,43 @@ JSGlobalData::~JSGlobalData()
     interpreter = 0;
 #endif
 
     interpreter = 0;
 #endif
 
-    arrayTable->deleteTable();
+    arrayPrototypeTable->deleteTable();
+    arrayConstructorTable->deleteTable();
+    booleanPrototypeTable->deleteTable();
     dateTable->deleteTable();
     dateTable->deleteTable();
+    dateConstructorTable->deleteTable();
+    errorPrototypeTable->deleteTable();
+    globalObjectTable->deleteTable();
     jsonTable->deleteTable();
     mathTable->deleteTable();
     jsonTable->deleteTable();
     mathTable->deleteTable();
-    numberTable->deleteTable();
+    numberConstructorTable->deleteTable();
+    numberPrototypeTable->deleteTable();
+    objectConstructorTable->deleteTable();
+    objectPrototypeTable->deleteTable();
     regExpTable->deleteTable();
     regExpConstructorTable->deleteTable();
     regExpTable->deleteTable();
     regExpConstructorTable->deleteTable();
+    regExpPrototypeTable->deleteTable();
     stringTable->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*>(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*>(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*>(regExpTable));
     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
+    fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
     fastDelete(const_cast<HashTable*>(stringTable));
     fastDelete(const_cast<HashTable*>(stringTable));
+    fastDelete(const_cast<HashTable*>(stringConstructorTable));
 
     delete parser;
     delete lexer;
 
     delete parser;
     delete lexer;
@@ -220,6 +354,9 @@ JSGlobalData::~JSGlobalData()
 
     delete clientData;
     delete m_regExpCache;
 
     delete clientData;
     delete m_regExpCache;
+#if ENABLE(REGEXP_TRACING)
+    delete m_rtTraceList;
+#endif
 }
 
 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
 }
 
 PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
@@ -234,10 +371,7 @@ PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
 
 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(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()
 }
 
 bool JSGlobalData::sharedInstanceExists()
@@ -249,7 +383,7 @@ JSGlobalData& JSGlobalData::sharedInstance()
 {
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
 {
     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
 #if ENABLE(JSC_MULTIPLE_THREADS)
         instance->makeUsableFromMultipleThreads();
 #endif
@@ -264,18 +398,21 @@ JSGlobalData*& JSGlobalData::sharedInstanceInternal()
     return sharedInstance;
 }
 
     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()
 {
 
 JSGlobalData::ClientData::~ClientData()
 {
@@ -286,6 +423,7 @@ void JSGlobalData::resetDateCache()
     cachedUTCOffset = NaN;
     dstOffsetCache.reset();
     cachedDateString = UString();
     cachedUTCOffset = NaN;
     dstOffsetCache.reset();
     cachedDateString = UString();
+    cachedDateStringValue = NaN;
     dateInstanceCache.reset();
 }
 
     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);
     // 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
 
 } // namespace JSC
index 6ccbf2c5a9872195cf3afc574653c432638ced10..fee7818396599a19173d912bc1885ed9adeaf240 100644 (file)
 #define JSGlobalData_h
 
 #include "CachedTranscendentalFunction.h"
 #define JSGlobalData_h
 
 #include "CachedTranscendentalFunction.h"
-#include "Collector.h"
+#include "Heap.h"
 #include "DateInstanceCache.h"
 #include "ExecutableAllocator.h"
 #include "DateInstanceCache.h"
 #include "ExecutableAllocator.h"
+#include "Strong.h"
 #include "JITStubs.h"
 #include "JSValue.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 "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/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;
 
 struct OpaqueJSClass;
 struct OpaqueJSClassContextData;
@@ -52,19 +58,24 @@ namespace JSC {
 
     class CodeBlock;
     class CommonIdentifiers;
 
     class CodeBlock;
     class CommonIdentifiers;
+    class HandleStack;
     class IdentifierTable;
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
     class Lexer;
     class IdentifierTable;
     class Interpreter;
     class JSGlobalObject;
     class JSObject;
     class Lexer;
+    class NativeExecutable;
     class Parser;
     class RegExpCache;
     class Stringifier;
     class Structure;
     class UString;
     class Parser;
     class RegExpCache;
     class Stringifier;
     class Structure;
     class UString;
+#if ENABLE(REGEXP_TRACING)
+    class RegExp;
+#endif
 
     struct HashTable;
 
     struct HashTable;
-    struct Instruction;    
+    struct Instruction;
 
     struct DSTOffsetCache {
         DSTOffsetCache()
 
     struct DSTOffsetCache {
         DSTOffsetCache()
@@ -108,6 +119,7 @@ namespace JSC {
         };
 
         bool isSharedInstance() { return globalDataType == APIShared; }
         };
 
         bool isSharedInstance() { return globalDataType == APIShared; }
+        bool usingAPI() { return globalDataType != Default; }
         static bool sharedInstanceExists();
         static JSGlobalData& sharedInstance();
 
         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.
 
 #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;
 
 #endif
 
         GlobalDataType globalDataType;
         ClientData* clientData;
 
-        const HashTable* arrayTable;
+        const HashTable* arrayConstructorTable;
+        const HashTable* arrayPrototypeTable;
+        const HashTable* booleanPrototypeTable;
         const HashTable* dateTable;
         const HashTable* dateTable;
+        const HashTable* dateConstructorTable;
+        const HashTable* errorPrototypeTable;
+        const HashTable* globalObjectTable;
         const HashTable* jsonTable;
         const HashTable* mathTable;
         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* regExpTable;
         const HashTable* regExpConstructorTable;
+        const HashTable* regExpPrototypeTable;
         const HashTable* stringTable;
         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();
 #endif
 
         static void storeVPtrs();
@@ -167,23 +199,32 @@ namespace JSC {
         ExecutableAllocator regexAllocator;
 #endif
 
         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
 #else
-        bool canUseJIT() { return false; }
+        bool canUseJIT() { return m_canUseJIT; }
 #endif
 #endif
+
+        const StackBounds& stack()
+        {
+            return wtfThreadData().stack();
+        }
+
         Lexer* lexer;
         Parser* parser;
         Interpreter* interpreter;
 #if ENABLE(JIT)
         OwnPtr<JITThunks> jitStubs;
         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
 #endif
+        NativeExecutable* getHostFunction(NativeFunction);
+
         TimeoutChecker timeoutChecker;
         Terminator terminator;
         Heap heap;
         TimeoutChecker timeoutChecker;
         Terminator terminator;
         Heap heap;
@@ -193,21 +234,12 @@ namespace JSC {
         ReturnAddressPtr exceptionLocation;
 #endif
 
         ReturnAddressPtr exceptionLocation;
 #endif
 
-        const Vector<Instruction>& numericCompareFunction(ExecState*);
-        Vector<Instruction> lazyNumericCompareFunction;
-        bool initializingLazyNumericCompareFunction;
-
         HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
 
         HashMap<OpaqueJSClass*, OpaqueJSClassContextData*> opaqueJSClassData;
 
-        JSGlobalObject* head;
+        unsigned globalObjectCount;
         JSGlobalObject* dynamicGlobalObject;
 
         JSGlobalObject* dynamicGlobalObject;
 
-        HashSet<JSObject*> arrayVisitedElements;
-
-        CodeBlock* functionCodeBlockBeingReparsed;
-        Stringifier* firstStringifierToMark;
-
-        MarkStack markStack;
+        HashSet<JSObject*> stringRecursionCheckVisitedObjects;
 
         double cachedUTCOffset;
         DSTOffsetCache dstOffsetCache;
 
         double cachedUTCOffset;
         DSTOffsetCache dstOffsetCache;
@@ -218,6 +250,12 @@ namespace JSC {
         int maxReentryDepth;
 
         RegExpCache* m_regExpCache;
         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;
 
 #ifndef NDEBUG
         ThreadIdentifier exclusiveThread;
@@ -232,6 +270,17 @@ namespace JSC {
         void dumpSampleData(ExecState* exec);
         void recompileAllJSFunctions();
         RegExpCache* regExpCache() { return m_regExpCache; }
         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();
     private:
         JSGlobalData(GlobalDataType, ThreadStackType);
         static JSGlobalData*& sharedInstanceInternal();
@@ -239,8 +288,14 @@ namespace JSC {
 #if ENABLE(JIT) && ENABLE(INTERPRETER)
         bool m_canUseJIT;
 #endif
 #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
 } // namespace JSC
 
 #endif // JSGlobalData_h
index 93ded4c7d9afb0d663b593630ecb0c1cc06d644b..a71624f33c468a2c2e5c0d1864085aa1069ffe77 100644 (file)
 #include "ErrorPrototype.h"
 #include "FunctionConstructor.h"
 #include "FunctionPrototype.h"
 #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 "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"
 #include "MathObject.h"
 #include "NativeErrorConstructor.h"
 #include "NativeErrorPrototype.h"
@@ -60,7 +60,6 @@
 #include "ObjectConstructor.h"
 #include "ObjectPrototype.h"
 #include "Profiler.h"
 #include "ObjectConstructor.h"
 #include "ObjectPrototype.h"
 #include "Profiler.h"
-#include "PrototypeFunction.h"
 #include "RegExpConstructor.h"
 #include "RegExpMatchesArray.h"
 #include "RegExpObject.h"
 #include "RegExpConstructor.h"
 #include "RegExpMatchesArray.h"
 #include "RegExpObject.h"
 #include "StringPrototype.h"
 #include "Debugger.h"
 
 #include "StringPrototype.h"
 #include "Debugger.h"
 
+#include "JSGlobalObject.lut.h"
+
 namespace JSC {
 
 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.
 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;
 
 // 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());
 
 }
 
 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** 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());
 }
 
 void JSGlobalObject::init(JSObject* thisValue)
 {
     ASSERT(JSLock::currentThreadIsHoldingLock());
-
+    
     structure()->disableSpecificFunctionTracking();
 
     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());
 }
 
     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));
 
 {
     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);
 }
         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));
 
 {
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
 
-    if (symbolTablePutWithAttributes(propertyName, value, attributes))
+    if (symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
         return;
 
         return;
 
-    JSValue valueBefore = getDirect(propertyName);
+    JSValue valueBefore = getDirect(exec->globalData(), propertyName);
     PutPropertySlot slot;
     JSVariableObject::put(exec, propertyName, value, slot);
     if (!valueBefore) {
     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);
     }
         if (valueAfter)
             JSObject::putWithAttributes(exec, propertyName, valueAfter, attributes);
     }
@@ -201,214 +187,190 @@ void JSGlobalObject::reset(JSValue prototype)
 {
     ExecState* exec = JSGlobalObject::globalExec();
 
 {
     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
 
 
     // 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 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, "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.
 }
 
 // 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* oldLastInPrototypeChain = lastInPrototypeChain(this);
-    JSObject* objectPrototype = d()->objectPrototype;
+    JSObject* objectPrototype = m_objectPrototype.get();
     if (oldLastInPrototypeChain != objectPrototype)
     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()
 {
 }
 
 ExecState* JSGlobalObject::globalExec()
 {
-    return CallFrame::create(d()->globalCallFrame + RegisterFile::CallFrameHeaderSize);
+    return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize);
 }
 
 bool JSGlobalObject::isDynamicScope(bool&) const
 }
 
 bool JSGlobalObject::isDynamicScope(bool&) const
@@ -416,19 +378,26 @@ bool JSGlobalObject::isDynamicScope(bool&) const
     return true;
 }
 
     return true;
 }
 
+void JSGlobalObject::disableEval()
+{
+    ASSERT(m_isEvalEnabled);
+    m_isEvalEnabled = false;
+}
+
 void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
 {
 void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile)
 {
-    ASSERT(!d()->registerArray);
-    ASSERT(!d()->registerArraySize);
+    ASSERT(!m_registerArray);
+    ASSERT(!m_registerArraySize);
 
     int numGlobals = registerFile.numGlobals();
     if (!numGlobals) {
 
     int numGlobals = registerFile.numGlobals();
     if (!numGlobals) {
-        d()->registers = 0;
+        m_registers = 0;
         return;
     }
         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)
 }
 
 void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
@@ -440,37 +409,111 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile)
     registerFile.setGlobalObject(this);
     registerFile.setNumGlobals(symbolTable().size());
 
     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::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) {
     , 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
 #endif
+
         m_dynamicGlobalObjectSlot = dynamicGlobalObject;
 
         // Reset the date cache between JS invocations to force the VM
         // to observe time zone changes.
         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
 } // namespace JSC
index dff45182d2b508a2c7812ab46a7297391c35e7ed..9f05d49123aa43f9ed33bdd423bc01d32b4da7e9 100644 (file)
@@ -26,9 +26,9 @@
 #include "JSGlobalData.h"
 #include "JSVariableObject.h"
 #include "JSWeakObjectMapRefInternal.h"
 #include "JSGlobalData.h"
 #include "JSVariableObject.h"
 #include "JSWeakObjectMapRefInternal.h"
-#include "NativeFunctionWrapper.h"
 #include "NumberPrototype.h"
 #include "StringPrototype.h"
 #include "NumberPrototype.h"
 #include "StringPrototype.h"
+#include "StructureChain.h"
 #include <wtf/HashSet.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RandomNumber.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 ErrorConstructor;
     class FunctionPrototype;
     class GlobalCodeBlock;
-    class GlobalEvalFunction;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
     class NativeErrorConstructor;
     class ProgramCodeBlock;
-    class PrototypeFunction;
     class RegExpConstructor;
     class RegExpPrototype;
     class RegisterFile;
     class RegExpConstructor;
     class RegExpPrototype;
     class RegisterFile;
@@ -57,130 +55,106 @@ namespace JSC {
     
     class JSGlobalObject : public JSVariableObject {
     protected:
     
     class JSGlobalObject : public JSVariableObject {
     protected:
-        using JSVariableObject::JSVariableObjectData;
         typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
 
         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*);
 
 
     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);
         }
 
             init(this);
         }
 
+        static JS_EXPORTDATA const ClassInfo s_info;
+
     protected:
     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();
 
             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&);
 
         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);
 
         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.
 
 
         // 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; }
         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; }
 
 
         virtual bool isGlobalObject() const { return true; }
 
@@ -262,35 +236,39 @@ namespace JSC {
 
         virtual bool isDynamicScope(bool& requiresDynamicChecks) const;
 
 
         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 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)
         {
         }
 
         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)
         {
         }
 
         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:
 
     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)
 
         struct GlobalPropertyInfo {
             GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
@@ -307,13 +285,11 @@ namespace JSC {
         void addStaticGlobals(GlobalPropertyInfo*, int count);
 
     private:
         void addStaticGlobals(GlobalPropertyInfo*, int count);
 
     private:
-        static void destroyJSGlobalObjectData(void*);
-
         // FIXME: Fold reset into init.
         void init(JSObject* thisValue);
         void reset(JSValue prototype);
 
         // 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
     };
 
         void* operator new(size_t); // can only be allocated with JSGlobalData
     };
@@ -326,42 +302,10 @@ namespace JSC {
         return static_cast<JSGlobalObject*>(asObject(value));
     }
 
         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);
     {
         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)
     }
 
     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
@@ -373,21 +317,19 @@ namespace JSC {
         return symbolTableGet(propertyName, slot, slotIsWriteable);
     }
 
         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)
     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();
         ASSERT(typeInfo().type() == StringType);
         return exec->lexicalGlobalObject()->stringPrototype();
-#endif
     }
 
     inline StructureChain* Structure::prototypeChain(ExecState* exec) const
     }
 
     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);
         // 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();
     }
         }
         return m_cachedPrototypeChain.get();
     }
@@ -406,9 +348,9 @@ namespace JSC {
             return false;
 
         JSValue prototype = prototypeForLookup(exec);
             return false;
 
         JSValue prototype = prototypeForLookup(exec);
-        RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
+        WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
         while(*cachedStructure && !prototype.isNull()) {
         while(*cachedStructure && !prototype.isNull()) {
-            if (asObject(prototype)->structure() != *cachedStructure)
+            if (asObject(prototype)->structure() != cachedStructure->get())
                 return false;
             ++cachedStructure;
             prototype = asObject(prototype)->prototype();
                 return false;
             ++cachedStructure;
             prototype = asObject(prototype)->prototype();
@@ -427,46 +369,62 @@ namespace JSC {
         return globalData().dynamicGlobalObject;
     }
 
         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)
     {
     }
 
     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);
     {
         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)
     {
     }
 
     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:
     public:
-        DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject);
+        DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
 
         ~DynamicGlobalObjectScope()
         {
 
         ~DynamicGlobalObjectScope()
         {
index 228ed6cd87d4f5cfd3f92db70c572739ec4621f9..35507e872042e5812ae85f7f0dd9ba930be97a84 100644 (file)
@@ -26,7 +26,6 @@
 #include "JSGlobalObjectFunctions.h"
 
 #include "CallFrame.h"
 #include "JSGlobalObjectFunctions.h"
 
 #include "CallFrame.h"
-#include "GlobalEvalFunction.h"
 #include "Interpreter.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "Interpreter.h"
 #include "JSGlobalObject.h"
 #include "JSString.h"
 #include "LiteralParser.h"
 #include "Nodes.h"
 #include "Parser.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 "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/ASCIICType.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
+#include <wtf/StringExtras.h>
 #include <wtf/unicode/UTF8.h>
 
 using namespace WTF;
 #include <wtf/unicode/UTF8.h>
 
 using namespace WTF;
@@ -51,12 +49,12 @@ using namespace Unicode;
 
 namespace JSC {
 
 
 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())
     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();
 
     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);
 }
 
     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;
 {
     JSStringBuilder builder;
-    UString str = args.at(0).toString(exec);
+    UString str = exec->argument(0).toString(exec);
     int k = 0;
     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;
     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)
             }
             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'
                 // 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) {
 bool isStrWhiteSpace(UChar c)
 {
     switch (c) {
+        // ECMA-262-5th 7.2 & 7.3
         case 0x0009:
         case 0x000A:
         case 0x000B:
         case 0x0009:
         case 0x000A:
         case 0x000B:
@@ -151,6 +150,7 @@ bool isStrWhiteSpace(UChar c)
         case 0x00A0:
         case 0x2028:
         case 0x2029:
         case 0x00A0:
         case 0x2028:
         case 0x2029:
+        case 0xFEFF:
             return true;
         default:
             return c > 0xff && isSeparatorSpace(c);
             return true;
         default:
             return c > 0xff && isSeparatorSpace(c);
@@ -195,10 +195,32 @@ double parseIntOverflow(const char* s, int length, int radix)
     return number;
 }
 
     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)
 {
 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]))
     int p = 0;
 
     while (p < length && isStrWhiteSpace(data[p]))
@@ -241,11 +263,10 @@ static double parseInt(const UString& s, int radix)
     }
 
     if (number >= mantissaOverflowLowerBound) {
     }
 
     if (number >= mantissaOverflowLowerBound) {
-        // FIXME: It is incorrect to use UString::ascii() here because it's not thread-safe.
         if (radix == 10)
         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)
         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)
     }
 
     if (!sawDigit)
@@ -254,105 +275,241 @@ static double parseInt(const UString& s, int radix)
     return sign * number;
 }
 
     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)
 {
 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();
     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())
     if (!x.isString())
-        return x;
+        return JSValue::encode(x);
 
     UString s = x.toString(exec);
 
 
     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())
     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)
     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)
 
     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())
 
     if (value.isInt32())
-        return value;
+        return JSValue::encode(value);
 
     if (value.isDouble()) {
         double d = value.asDouble();
         if (isfinite(d))
 
     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))
         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[] =
         "#$&+,/:;=?@";
 
 {
     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"
 {
     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"
         "!#$&'()*+,-./:;=?@_~";
 
         "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"
 {
     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"
         "!'()*-._~";
 
         "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"
 {
     static const char do_not_escape[] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -383,9 +540,9 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons
         "*+-./@_";
 
     JSStringBuilder builder;
         "*+-./@_";
 
     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];
         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 k = 0;
-    int len = str.size();
+    int len = str.length();
     while (k < len) {
     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])) {
         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);
     }
 
         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
 
 } // namespace JSC
index b1046f2dd48ee106da588968b714399db565aab5..36e9ac4cf90d103e54c10dd6ff333e69ca3a343e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -24,6 +24,7 @@
 #ifndef JSGlobalObjectFunctions_h
 #define JSGlobalObjectFunctions_h
 
 #ifndef JSGlobalObjectFunctions_h
 #define JSGlobalObjectFunctions_h
 
+#include "JSValue.h"
 #include <wtf/unicode/Unicode.h>
 
 namespace JSC {
 #include <wtf/unicode/Unicode.h>
 
 namespace JSC {
@@ -31,29 +32,27 @@ namespace JSC {
     class ArgList;
     class ExecState;
     class JSObject;
     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.
 
 
     // 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);
 
     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);
     bool isStrWhiteSpace(UChar);
+    double jsToNumber(const UString& s);
 
 } // namespace JSC
 
 
 } // 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 "config.h"
 #include "JSLock.h"
 
-#include "Collector.h"
+#include "Heap.h"
 #include "CallFrame.h"
 #include "CallFrame.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if USE(PTHREADS)
 #include <pthread.h>
 #endif
 
 namespace JSC {
 
 #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;
 
 // 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);
 }
 
     lock(m_lockBehavior);
 }
 
+JSLock::JSLock(JSGlobalData* globalData)
+    : m_lockBehavior(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
+{
+    lock(m_lockBehavior);
+}
+
 void JSLock::lock(JSLockBehavior lockBehavior)
 {
 #ifdef NDEBUG
 void JSLock::lock(JSLockBehavior lockBehavior)
 {
 #ifdef NDEBUG
@@ -202,7 +213,7 @@ JSLock::DropAllLocks::~DropAllLocks()
     --lockDropDepth;
 }
 
     --lockDropDepth;
 }
 
-#else
+#else // ENABLE(JSC_MULTIPLE_THREADS) && (OS(DARWIN) || USE(PTHREADS))
 
 JSLock::JSLock(ExecState*)
     : m_lockBehavior(SilenceAssertionsOnly)
 
 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
 
 } // 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;
     // assertions working, so that clients that use the shared context don't break.
 
     class ExecState;
+    class JSGlobalData;
 
     enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
 
 
     enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
 
-    class JSLock : public Noncopyable {
+    class JSLock {
+        WTF_MAKE_NONCOPYABLE(JSLock);
     public:
         JSLock(ExecState*);
     public:
         JSLock(ExecState*);
+        JSLock(JSGlobalData*);
 
         JSLock(JSLockBehavior lockBehavior)
             : m_lockBehavior(lockBehavior)
 
         JSLock(JSLockBehavior lockBehavior)
             : m_lockBehavior(lockBehavior)
@@ -87,7 +90,8 @@ namespace JSC {
 
         JSLockBehavior m_lockBehavior;
 
 
         JSLockBehavior m_lockBehavior;
 
-        class DropAllLocks : public Noncopyable {
+        class DropAllLocks {
+            WTF_MAKE_NONCOPYABLE(DropAllLocks);
         public:
             DropAllLocks(ExecState* exec);
             DropAllLocks(JSLockBehavior);
         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
 {
 // 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&)
 {
 }
 
 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
 {
     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
 {
     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
 {
     return NaN;
 }
 
 UString JSNotAnObject::toString(ExecState* exec) const
 {
-    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
+    ASSERT_UNUSED(exec, exec->hadException());
     return "";
 }
 
     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&)
 {
 }
 
 // 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&)
 {
     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&)
 {
     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&)
 {
     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)
 {
 }
 
 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&)
 {
 }
 
 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)
 {
     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)
 {
     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
 }
 
 } // namespace JSC
index 339d41f5a2294413c140ae9fdff58347f30fa6fb..4c6806a5f1250eb22c30742c30524a94f87ffb46 100644 (file)
 
 namespace JSC {
 
 
 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.
     // 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:
     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:
         
         }
 
      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;
 
         // 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 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&);
 
         // 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);
         virtual bool deleteProperty(ExecState*, unsigned propertyName);
 
         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
-
-        JSNotAnObjectErrorStub* m_exception;
     };
 
 } // namespace JSC
     };
 
 } // 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 "Error.h"
 #include "ExceptionHelpers.h"
 #include "JSArray.h"
+#include "JSGlobalObject.h"
 #include "LiteralParser.h"
 #include "LiteralParser.h"
+#include "Local.h"
+#include "LocalScope.h"
 #include "Lookup.h"
 #include "PropertyNameArray.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);
 
 #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 {
 
 
 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:
 // 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;
 };
 
     mutable JSValue m_value;
 };
 
-class Stringifier : public Noncopyable {
+class Stringifier {
+    WTF_MAKE_NONCOPYABLE(Stringifier);
 public:
 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:
 
 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:
 
     private:
-        JSObject* const m_object;
+        Local<JSObject> m_object;
         const bool m_isArray;
         bool m_isJSArray;
         unsigned m_index;
         const bool m_isArray;
         bool m_isJSArray;
         unsigned m_index;
@@ -91,28 +101,26 @@ private:
 
     friend class Holder;
 
 
     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 };
 
     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();
 
     bool willIndent() const;
     void indent();
     void unindent();
-    void startNewLine(StringBuilder&) const;
+    void startNewLine(UStringBuilder&) const;
 
 
-    Stringifier* const m_nextStringifierToMark;
     ExecState* const m_exec;
     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;
 
     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;
     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 (!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));
         return jsString(exec, object->toString(exec));
-    if (object->inherits(&BooleanObject::info))
+    if (object->inherits(&BooleanObject::s_info))
         return object->toPrimitive(exec);
     return value;
 }
         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 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;
 }
     }
     return spaces;
 }
@@ -182,30 +190,27 @@ JSValue PropertyNameForFunctionCall::value(ExecState* exec) const
         if (m_identifier)
             m_value = jsString(exec, m_identifier->ustring());
         else
         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 --------------------------------
 
     }
     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_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 (!m_replacer.isObject())
         return;
 
-    if (asObject(m_replacer)->inherits(&JSArray::info)) {
+    if (m_replacer.asObject()->inherits(&JSArray::s_info)) {
         m_usingArrayReplacer = true;
         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);
         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 (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())
                     continue;
                 propertyName = name.toString(exec);
                 if (exec->hadException())
@@ -236,52 +241,34 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
         return;
     }
 
         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())
 {
     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);
 
     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())
     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('"');
 
 
     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] != '\\'))
     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] };
                 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;
         }
     }
                 break;
         }
     }
@@ -350,11 +337,11 @@ inline JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFunctionC
         return value;
 
     JSValue list[] = { propertyName.value(m_exec) };
         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);
 }
 
     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);
 {
     // 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 };
     // 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 (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()) {
         return StringifyFailedDueToUndefinedValue;
 
     if (value.isNull()) {
@@ -399,7 +386,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
         if (!isfinite(numericValue))
             builder.append("null");
         else
         if (!isfinite(numericValue))
             builder.append("null");
         else
-            builder.append(UString::from(numericValue));
+            builder.append(UString::number(numericValue));
         return StringifySucceeded;
     }
 
         return StringifySucceeded;
     }
 
@@ -410,7 +397,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
 
     CallData callData;
     if (object->getCallData(callData) != CallTypeNone) {
 
     CallData callData;
     if (object->getCallData(callData) != CallTypeNone) {
-        if (holder->inherits(&JSArray::info)) {
+        if (holder->inherits(&JSArray::s_info)) {
             builder.append("null");
             return StringifySucceeded;
         }
             builder.append("null");
             return StringifySucceeded;
         }
@@ -418,12 +405,14 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
     }
 
     // Handle cycle detection, and put the holder on the stack.
     }
 
     // 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();
     }
     bool holderStackWasEmpty = m_holderStack.isEmpty();
-    m_holderStack.append(object);
+    m_holderStack.append(Holder(m_exec->globalData(), object));
     if (!holderStackWasEmpty)
         return StringifySucceeded;
 
     if (!holderStackWasEmpty)
         return StringifySucceeded;
 
@@ -437,13 +426,12 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder&
                 return StringifyFailed;
             if (!--tickCount) {
                 if (localTimeoutChecker.didTimeOut(m_exec)) {
                 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();
             }
         }
                     return StringifyFailed;
                 }
                 tickCount = localTimeoutChecker.ticksUntilNextCheck();
             }
         }
-        m_holderCycleDetector.remove(m_holderStack.last().object());
         m_holderStack.removeLast();
     } while (!m_holderStack.isEmpty());
     return StringifySucceeded;
         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.
 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()
 {
 }
 
 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;
 {
     if (m_gap.isEmpty())
         return;
@@ -478,14 +466,14 @@ inline void Stringifier::startNewLine(StringBuilder& builder) const
     builder.append(m_indent);
 }
 
     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)
 {
 }
 
     , m_index(0)
 {
 }
 
-bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBuilder& builder)
+bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, UStringBuilder& builder)
 {
     ASSERT(m_index <= m_size);
 
 {
     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) {
     // 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 {
             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();
     // 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;
             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_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 {
         else {
-            PropertySlot slot(m_object);
+            PropertySlot slot(m_object.get());
             if (!m_object->getOwnPropertySlot(exec, index, slot))
                 slot.setUndefined();
             if (exec->hadException())
             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.
         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.
     } 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;
         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;
 
         if (exec->hadException())
             return false;
 
-        rollBackPoint = builder.size();
+        rollBackPoint = builder.length();
 
         // Append the separator string.
         if (builder[rollBackPoint - 1] != '{')
 
         // 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.
             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
     }
 
     // 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 --------------------------------
 
 
 // ------------------------------ 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
 
 /* 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
 */
 
 @end
 */
 
@@ -616,16 +604,11 @@ bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro
     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
 }
 
     return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
 }
 
-void JSONObject::markStringifiers(MarkStack& markStack, Stringifier* stringifier)
-{
-    stringifier->markAggregate(markStack);
-}
-
 class Walker {
 public:
 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_exec(exec)
-        , m_function(function)
+        , m_function(exec->globalData(), function)
         , m_callType(callType)
         , m_callData(callData)
     {
         , m_callType(callType)
         , m_callData(callData)
     {
@@ -636,13 +619,13 @@ private:
     {
         JSValue args[] = { property, unfiltered };
         ArgList argList(args, 2);
     {
         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;
     }
 
     friend class Holder;
 
     ExecState* m_exec;
-    JSObject* m_function;
+    Local<JSObject> m_function;
     CallType m_callType;
     CallData m_callData;
 };
     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<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;
     
     Vector<WalkerState, 16> stateStack;
     WalkerState state = StateUnknown;
@@ -672,32 +655,28 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
             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);
 
                 JSArray* array = asArray(inValue);
-                arrayStack.append(array);
+                arrayStack.push(array);
                 indexStack.append(0);
                 // fallthrough
             }
             arrayStartVisitMember:
             case ArrayStartVisitMember: {
                 if (!--tickCount) {
                 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();
                 }
 
                     tickCount = localTimeoutChecker.ticksUntilNextCheck();
                 }
 
-                JSArray* array = arrayStack.last();
+                JSArray* array = arrayStack.peek();
                 uint32_t index = indexStack.last();
                 if (index == array->length()) {
                     outValue = array;
                 uint32_t index = indexStack.last();
                 if (index == array->length()) {
                     outValue = array;
-                    arrayStack.removeLast();
+                    arrayStack.pop();
                     indexStack.removeLast();
                     break;
                 }
                     indexStack.removeLast();
                     break;
                 }
@@ -719,13 +698,13 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 // fallthrough
             }
             case ArrayEndVisitMember: {
                 // 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()))
                 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);
                 }
                     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());
             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);
 
                 JSObject* object = asObject(inValue);
-                objectStack.append(object);
+                objectStack.push(object);
                 indexStack.append(0);
                 propertyStack.append(PropertyNameArray(m_exec));
                 object->getOwnPropertyNames(m_exec, propertyStack.last());
                 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) {
             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();
                 }
 
                     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;
                 uint32_t index = indexStack.last();
                 PropertyNameArray& properties = propertyStack.last();
                 if (index == properties.size()) {
                     outValue = object;
-                    objectStack.removeLast();
+                    objectStack.pop();
                     indexStack.removeLast();
                     propertyStack.removeLast();
                     break;
                     indexStack.removeLast();
                     propertyStack.removeLast();
                     break;
@@ -788,7 +763,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                 // fallthrough
             }
             case ObjectEndVisitMember: {
                 // 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);
                 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);
                     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;
         }
                     goto arrayStartState;
                 goto objectStartState;
         }
@@ -819,10 +794,8 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
         stateStack.removeLast();
 
         if (!--tickCount) {
         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();
         }
     }
             tickCount = localTimeoutChecker.ticksUntilNextCheck();
         }
     }
@@ -833,45 +806,48 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
 }
 
 // ECMA-262 v5 15.12.2
 }
 
 // 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())
     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)
     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;
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
     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
 }
 
 // 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)
 {
 }
 
 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);
     if (result.isUndefinedOrNull())
         return UString();
     return result.getString(exec);
index 7a9e0a48b90e035647b9686e053245a1325240c5..b7733205c808be2d783fd7c7e82e891f4dceb1fb 100644 (file)
 #ifndef JSONObject_h
 #define JSONObject_h
 
 #ifndef JSONObject_h
 #define JSONObject_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
 
     class Stringifier;
 
 
 namespace JSC {
 
     class Stringifier;
 
-    class JSONObject : public JSObject {
+    class JSONObject : public JSObjectWithGlobalObject {
     public:
     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;
 
     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 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);
     };
 
     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 "DatePrototype.h"
 #include "ErrorConstructor.h"
 #include "GetterSetter.h"
+#include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "NativeErrorConstructor.h"
 #include "ObjectPrototype.h"
 #include "JSGlobalObject.h"
 #include "NativeErrorConstructor.h"
 #include "ObjectPrototype.h"
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSObject);
 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)
 {
 
 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
 #ifndef NDEBUG
-    bool wasCheckingForDefaultMarkViolation = markStack.m_isCheckingForDefaultMarkViolation;
-    markStack.m_isCheckingForDefaultMarkViolation = false;
+    bool wasCheckingForDefaultMarkViolation = visitor.m_isCheckingForDefaultMarkViolation;
+    visitor.m_isCheckingForDefaultMarkViolation = false;
 #endif
 
 #endif
 
-    markChildrenDirect(markStack);
+    visitChildrenDirect(visitor);
 
 #ifndef NDEBUG
 
 #ifndef NDEBUG
-    markStack.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
+    visitor.m_isCheckingForDefaultMarkViolation = wasCheckingForDefaultMarkViolation;
 #endif
 }
 
 UString JSObject::className() const
 {
     const ClassInfo* info = classInfo();
 #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)
 }
 
 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)
 {
 
 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
 }
 
 // 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;
         // 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;
     }
 
         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()) {
     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;
             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;
         return;
+    }
 
     for (JSObject* obj = this; ; obj = asObject(prototype)) {
 
     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) {
             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;
     }
 
             break;
     }
 
-    putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot);
+    if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode())
+        throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
     return;
 }
 
     return;
 }
 
@@ -170,6 +172,21 @@ void JSObject::put(ExecState* exec, unsigned propertyName, JSValue value)
     put(exec, Identifier::from(exec, propertyName), value, slot);
 }
 
     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);
 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;
 {
     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;
         if ((attributes & DontDelete))
             return false;
-        removeDirect(propertyName);
+        removeDirect(exec->globalData(), propertyName);
         return true;
     }
 
         return true;
     }
 
@@ -233,7 +250,7 @@ static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSO
 {
     JSValue function = object->get(exec, propertyName);
     CallData callData;
 {
     JSValue function = object->get(exec, propertyName);
     CallData callData;
-    CallType callType = function.getCallData(callData);
+    CallType callType = getCallData(function, callData);
     if (callType == CallTypeNone)
         return exec->exception();
 
     if (callType == CallTypeNone)
         return exec->exception();
 
@@ -280,7 +297,7 @@ JSValue JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) con
 
     ASSERT(!exec->hadException());
 
 
     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
 }
 
 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)
 {
 
 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());
     if (object && object.isGetterSetter()) {
         ASSERT(m_structure->hasGetterSetterProperties());
-        asGetterSetter(object)->setGetter(getterFunction);
+        asGetterSetter(object)->setGetter(exec->globalData(), getterFunction);
         return;
     }
 
         return;
     }
 
+    JSGlobalData& globalData = exec->globalData();
     PutPropertySlot slot;
     GetterSetter* getterSetter = new (exec) GetterSetter(exec);
     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) {
 
     // 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);
     }
 
     m_structure->setHasGetterSetterProperties(true);
-    getterSetter->setGetter(getterFunction);
+    getterSetter->setGetter(globalData, getterFunction);
 }
 
 void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
 {
 }
 
 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());
     if (object && object.isGetterSetter()) {
         ASSERT(m_structure->hasGetterSetterProperties());
-        asGetterSetter(object)->setSetter(setterFunction);
+        asGetterSetter(object)->setSetter(exec->globalData(), setterFunction);
         return;
     }
 
         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) {
     // 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);
     }
 
     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) {
 {
     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();
             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) {
 {
     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();
             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()) {
         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;
     }
 
         return false;
     }
 
@@ -412,10 +426,10 @@ bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyN
     return descriptor.enumerable();
 }
 
     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;
 {
     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
         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)
 {
 
 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);
 }
 
     getClassPropertyNames(exec, classInfo(), propertyNames, mode);
 }
 
@@ -473,7 +487,7 @@ UString JSObject::toString(ExecState* exec) const
     return primitive.toString(exec);
 }
 
     return primitive.toString(exec);
 }
 
-JSObject* JSObject::toObject(ExecState*) const
+JSObject* JSObject::toObject(ExecState*, JSGlobalObject*) const
 {
     return const_cast<JSObject*>(this);
 }
 {
     return const_cast<JSObject*>(this);
 }
@@ -483,40 +497,79 @@ JSObject* JSObject::toThisObject(ExecState*) const
     return const_cast<JSObject*>(this);
 }
 
     return const_cast<JSObject*>(this);
 }
 
+JSValue JSObject::toStrictThisObject(ExecState*) const
+{
+    return const_cast<JSObject*>(this);
+}
+
 JSObject* JSObject::unwrappedObject()
 {
     return 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()) {
     size_t offset;
     if (m_structure->isUncacheableDictionary()) {
-        offset = m_structure->removePropertyWithoutTransition(propertyName);
+        offset = m_structure->removePropertyWithoutTransition(globalData, propertyName);
         if (offset != WTF::notFound)
         if (offset != WTF::notFound)
-            putDirectOffset(offset, jsUndefined());
+            putUndefinedAtDirectOffset(offset);
         return;
     }
 
         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)
     if (offset != WTF::notFound)
-        putDirectOffset(offset, jsUndefined());
+        putUndefinedAtDirectOffset(offset);
 }
 
 void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr)
 {
 }
 
 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)
 {
 }
 
 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
         if (!structure()->isDictionary())
             slot.setCacheableGetterSlot(this, getterFunction, offsetForLocation(location));
         else
@@ -525,22 +578,38 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue*
         slot.setUndefined();
 }
 
         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)
 {
     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;
 {
     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);
     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()) {
 {
     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;
         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 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;
 
     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)
     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)
             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;
         }
     }
             return false;
         }
     }
@@ -607,7 +703,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
     if (descriptor.isGenericDescriptor()) {
         if (!current.attributesEqual(descriptor)) {
             deleteProperty(exec, 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;
     }
         }
         return true;
     }
@@ -616,11 +712,11 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
     if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
         if (!current.configurable()) {
             if (throwException)
     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 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
     }
 
     // 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)
         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)
                 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;
                 }
             }
                     return false;
                 }
             }
@@ -648,32 +744,32 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
             return true;
         }
         deleteProperty(exec, 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()) {
     }
 
     // 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)
             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;
         }
             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)
             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;
         }
     }
             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())
     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())
         if (descriptor.getter())
-            getterSetter->setGetter(asObject(descriptor.getter()));
+            getterSetter->setGetter(exec->globalData(), asObject(descriptor.getter()));
         return true;
     }
     deleteProperty(exec, propertyName);
         return true;
     }
     deleteProperty(exec, propertyName);
@@ -682,8 +778,13 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName
         attrs |= Setter;
     if (descriptor.getter())
         attrs |= Getter;
         attrs |= Setter;
     if (descriptor.getter())
         attrs |= Getter;
-    putDirect(propertyName, getterSetter, attrs);
+    putDirect(exec->globalData(), propertyName, getterSetter, attrs);
     return true;
 }
 
     return true;
 }
 
+JSObject* throwTypeError(ExecState* exec, const UString& message)
+{
+    return throwError(exec, createTypeError(exec, message));
+}
+
 } // namespace JSC
 } // namespace JSC
index 6824c23fea7c39a79aa1e518febfaaf724ea73e4..60def6e9cea26a06dac76a6f50a645474aed69ca 100644 (file)
@@ -29,7 +29,6 @@
 #include "Completion.h"
 #include "CallFrame.h"
 #include "JSCell.h"
 #include "Completion.h"
 #include "CallFrame.h"
 #include "JSCell.h"
-#include "JSNumberCell.h"
 #include "MarkStack.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
 #include "MarkStack.h"
 #include "PropertySlot.h"
 #include "PutPropertySlot.h"
@@ -55,6 +54,9 @@ namespace JSC {
     class Structure;
     struct HashTable;
 
     class Structure;
     struct HashTable;
 
+    JSObject* throwTypeError(ExecState*, const UString&);
+    extern const char* StrictModeReadonlyPropertyWriteError;
+
     // ECMA 262-3 8.6.1
     // Property attributes
     enum Attribute {
     // ECMA 262-3 8.6.1
     // Property attributes
     enum Attribute {
@@ -67,29 +69,29 @@ namespace JSC {
         Setter       = 1 << 6   // property is a setter
     };
 
         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;
 
     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:
 
     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;
 
         // 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;
 
 
         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 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);
         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 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 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.
         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();
         }
 
             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;
         }
 
             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;
         {
             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;
         }
 
             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(); }
 
         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, 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, InternalFunction* function, unsigned attr = 0);
+        void putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr = 0);
 
         // Fast access to known property offsets.
 
         // 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);
 
         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 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);
 
         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:
     protected:
+        static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
+        {
+            return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+        }
+
         static const unsigned StructureFlags = 0;
 
         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:
         }
 
     private:
@@ -241,40 +279,118 @@ namespace JSC {
         void getString(ExecState* exec);
         void isObject();
         void isString();
         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;
         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());
 inline JSObject* asObject(JSCell* cell)
 {
     ASSERT(cell->isObject());
@@ -286,23 +402,22 @@ inline JSObject* asObject(JSValue value)
     return asObject(value.asCell());
 }
 
     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()));
     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()
 {
 }
 
 inline JSObject::~JSObject()
 {
-    ASSERT(m_structure);
     if (!isUsingInlineStorage())
     if (!isUsingInlineStorage())
-        delete [] m_externalStorage;
-    m_structure->deref();
+        delete [] m_propertyStorage;
 }
 
 inline JSValue JSObject::prototype() const
 }
 
 inline JSValue JSObject::prototype() const
@@ -310,29 +425,43 @@ inline JSValue JSObject::prototype() const
     return m_structure->storedPrototype();
 }
 
     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);
 {
     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 m_inheritorID.get();
-    return createInheritorID();
+    }
+    return createInheritorID(globalData);
 }
 
 inline bool Structure::isUsingInlineStorage() const
 {
 }
 
 inline bool Structure::isUsingInlineStorage() const
 {
-    return (propertyStorageCapacity() == JSObject::inlineStorageCapacity);
+    return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity;
 }
 
 inline bool JSCell::inherits(const ClassInfo* info) const
 }
 
 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)
 {
 
 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
             fillGetterPropertySlot(slot, location);
         else
-            slot.setValueSlot(this, location, offsetForLocation(location));
+            slot.setValue(this, location->get(), offsetForLocation(location));
         return true;
     }
 
         return true;
     }
 
@@ -430,7 +559,7 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
     return jsUndefined();
 }
 
     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));
 {
     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;
     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))
         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)
             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
             // 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);
             // 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();
         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());
         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);
         // See comment on setNewProperty call below.
         if (!specificFunction)
             slot.setNewProperty(this, offset);
-        return;
+        return true;
     }
 
     size_t offset;
     size_t currentCapacity = m_structure->propertyStorageCapacity();
     }
 
     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());
         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);
         // 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;
     }
 
     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)
     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*.
 
         // 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) {
         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).
             }
             // 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);
         }
 
         // 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());
 
     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);
     // 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));
 
 {
     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;
 }
 
 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));
 
 {
     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;
 {
     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;
 {
     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 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());
     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 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());
     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());
 {
     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
 }
 
 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);
 }
 
     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());
 {
     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)
 }
 
 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);
 }
 
     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();
     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 ----------------------------
 }
 
 // --- 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));
 }
 
     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
 } // 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);
 
 
 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)
 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_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)
 {
     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)
 }
 
 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);
     
     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;
     }
 
     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)
 {
     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))))
         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;
 }
 
     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
 }
 
 } // namespace JSC
index 01700ac212155b4fe9b97faaad1bfdcc74042ffa..ff129f0549a1324b9a48080874680b347adf6d27 100644 (file)
@@ -45,16 +45,14 @@ namespace JSC {
     public:
         static JSPropertyNameIterator* create(ExecState*, JSObject*);
         
     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 bool isPropertyNameIterator() const { return true; }
 
-        virtual void markChildren(MarkStack&);
+        virtual void visitChildren(SlotVisitor&);
 
         bool getOffset(size_t i, int& offset)
         {
 
         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; }
 
         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);
         {
             ASSERT(!m_cachedStructure);
             ASSERT(structure);
-            m_cachedStructure = structure;
+            m_cachedStructure.set(globalData, this, structure);
         }
         Structure* cachedStructure() { return m_cachedStructure.get(); }
 
         }
         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(); }
         StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }
+        
+        static const ClassInfo s_info;
 
     private:
         JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot);
 
 
     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;
         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());
     {
         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
     }
 
 } // namespace JSC
index ad1021809386f695e7e22538aa3edf36598384d3..5206510d6cd2a7724a73b5bed12a1f2d6d8cc716 100644 (file)
 
 #include "JSStaticScopeObject.h"
 
 
 #include "JSStaticScopeObject.h"
 
-namespace JSC {
+#include "Error.h"
 
 
+namespace JSC {
 ASSERT_CLASS_FITS_IN_CELL(JSStaticScopeObject);
 
 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
 }
 
 JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
@@ -42,17 +46,37 @@ JSObject* JSStaticScopeObject::toThisObject(ExecState* exec) const
     return exec->globalThisValue();
 }
 
     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();
 }
 
         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();
         return;
     
     ASSERT_NOT_REACHED();
@@ -63,13 +87,7 @@ bool JSStaticScopeObject::isDynamicScope(bool&) const
     return false;
 }
 
     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);
 }
 {
     return symbolTableGet(propertyName, slot);
 }
index dcece9d97346c6e32f49060fdcaf888e98da50e8..b201fe05676b2f17171a74caea418a99af31c928 100644 (file)
 namespace JSC{
     
     class JSStaticScopeObject : public JSVariableObject {
 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)
     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;
         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);
 
         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:
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
 
     private:
 
     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 "JSString.h"
 
 #include "JSGlobalObject.h"
+#include "JSGlobalObjectFunctions.h"
 #include "JSObject.h"
 #include "Operations.h"
 #include "StringObject.h"
 #include "JSObject.h"
 #include "Operations.h"
 #include "StringObject.h"
 
 namespace JSC {
     
 
 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
 
 // 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
 // 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
 // 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)
     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);
     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 {
                 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;
             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) {
 
             // 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;
                 }
                 m_fiberCount = 0;
-
+                
                 ASSERT(!isRope());
                 return;
             }
                 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());
 // 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];
     JSGlobalData* globalData = &exec->globalData();
 
     UString substringFibers[3];
@@ -124,9 +169,9 @@ JSString* JSString::substringFromRope(ExecState* exec, unsigned substringStart,
     unsigned fiberEnd = 0;
 
     RopeIterator end;
     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;
         ++fiberCount;
-        UStringImpl* fiberString = *it;
+        StringImpl* fiberString = *it;
         unsigned fiberStart = fiberEnd;
         fiberEnd = fiberStart + fiberString->length();
         if (fiberEnd <= substringStart)
         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
         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 (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);
             // 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);
 
     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)
             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()) {
 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 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;
     }
 
     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;
 
         ++fiberCount;
         if (matchString)
             continue;
 
-        UStringImpl* string = *it;
+        StringImpl* string = *it;
         matchPosition = string->find(character);
         matchPosition = string->find(character);
-        if (matchPosition == -1)
+        if (matchPosition == notFound)
             continue;
         matchString = string;
     }
             continue;
         matchString = string;
     }
@@ -190,21 +235,21 @@ JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UStri
     if (!matchString)
         return this;
 
     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);
 
     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;
         }
 
         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(replacement);
-        builder.append(UString(string).substr(matchPosition + 1));
+        builder.append(UString(string).substringSharingImpl(matchPosition + 1));
         matchString = 0;
     }
 
         matchString = 0;
     }
 
@@ -220,7 +265,7 @@ JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i)
     if (exec->exception())
         return jsString(exec, "");
     ASSERT(!isRope());
     if (exec->exception())
         return jsString(exec, "");
     ASSERT(!isRope());
-    ASSERT(i < m_value.size());
+    ASSERT(i < m_value.length());
     return jsSingleCharacterSubstring(exec, m_value, i);
 }
 
     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;
 bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result)
 {
     result = this;
-    number = value(exec).toDouble();
+    number = jsToNumber(value(exec));
     return false;
 }
 
     return false;
 }
 
@@ -243,7 +288,7 @@ bool JSString::toBoolean(ExecState*) const
 
 double JSString::toNumber(ExecState* exec) const
 {
 
 double JSString::toNumber(ExecState* exec) const
 {
-    return value(exec).toDouble();
+    return jsToNumber(value(exec));
 }
 
 UString JSString::toString(ExecState* exec) const
 }
 
 UString JSString::toString(ExecState* exec) const
@@ -251,19 +296,19 @@ UString JSString::toString(ExecState* exec) const
     return value(exec);
 }
 
     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
 {
 }
 
 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)
 }
 
 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) {
 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;
         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;
     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 "CallFrame.h"
 #include "CommonIdentifiers.h"
 #include "Identifier.h"
-#include "JSNumberCell.h"
 #include "PropertyDescriptor.h"
 #include "PropertySlot.h"
 #include "RopeImpl.h"
 #include "PropertyDescriptor.h"
 #include "PropertySlot.h"
 #include "RopeImpl.h"
+#include "Structure.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -59,9 +59,6 @@ namespace JSC {
     JSString* jsOwnedString(JSGlobalData*, const UString&); 
     JSString* jsOwnedString(ExecState*, const UString&); 
 
     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;
     class JS_EXPORTCLASS JSString : public JSCell {
     public:
         friend class JIT;
@@ -87,13 +84,13 @@ namespace JSC {
             void append(const UString& string)
             {
                 ASSERT(m_rope);
             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)
             }
             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());
             }
                 } else
                     append(jsString->string());
             }
@@ -132,12 +129,12 @@ namespace JSC {
                     return *this;
                 }
 
                     return *this;
                 }
 
-                UStringImpl* operator*()
+                StringImpl* operator*()
                 {
                     WorkItem& item = m_workQueue.last();
                     RopeImpl::Fiber fiber = item.fibers[item.i];
                     ASSERT(!RopeImpl::isRope(fiber));
                 {
                     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
                 }
 
                 bool operator!=(const RopeIterator& other) const
@@ -185,26 +182,26 @@ namespace JSC {
         };
 
         ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value)
         };
 
         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());
             , 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)
         }
 
         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());
         }
             , 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)
             , 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)
             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_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)
         }
         // 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)
         {
             , 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)
         // 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);
             , 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)
         // 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);
             , 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)
         // 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)
         {
             , 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)
 
         // 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;
             , 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)
 
         // 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;
             , m_fiberCount(s_maxInternalRopeLength)
         {
             unsigned index = 0;
@@ -298,27 +295,11 @@ namespace JSC {
             ASSERT(index <= s_maxInternalRopeLength);
         }
 
             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)
         ~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
         }
 
         const UString& value(ExecState* exec) const
@@ -345,33 +326,39 @@ namespace JSC {
 
         JSValue replaceCharacter(ExecState*, UChar, const UString& replacement);
 
 
         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:
 
     private:
-        enum VPtrStealingHackType { VPtrStealingHack };
         JSString(VPtrStealingHackType) 
         JSString(VPtrStealingHackType) 
-            : JSCell(0)
+            : JSCell(VPtrStealingHack)
             , m_fiberCount(0)
         {
         }
 
         void resolveRope(ExecState*) const;
             , 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)
         {
         JSString* substringFromRope(ExecState*, unsigned offset, unsigned length);
 
         void appendStringInConstruct(unsigned& index, const UString& string)
         {
-            UStringImpl* impl = string.rep();
+            StringImpl* impl = string.impl();
             impl->ref();
             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) {
         }
 
         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();
                     fiber->ref();
-                    m_other.m_fibers[index++] = fiber;
+                    m_fibers[index++] = fiber;
                 }
             } else
                 appendStringInConstruct(index, jsString->string());
                 }
             } else
                 appendStringInConstruct(index, jsString->string());
@@ -380,17 +367,17 @@ namespace JSC {
         void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v)
         {
             if (v.isString()) {
         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));
                 appendStringInConstruct(index, s);
                 m_length += s->length();
             } else {
                 UString u(v.toString(exec));
-                UStringImpl* impl = u.rep();
+                StringImpl* impl = u.impl();
                 impl->ref();
                 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 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;
         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;
         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; }
 
         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, 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);
     };
 
         friend JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length);
     };
 
@@ -453,8 +429,8 @@ namespace JSC {
 
     inline JSString* asString(JSValue value)
     {
 
     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)
     }
 
     inline JSString* jsEmptyString(JSGlobalData* globalData)
@@ -464,7 +440,7 @@ namespace JSC {
 
     inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c)
     {
 
     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)));
     }
             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();
     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 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)
     }
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s)
@@ -489,7 +465,7 @@ namespace JSC {
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
 
     inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s)
     {
-        ASSERT(s.size() > 1);
+        ASSERT(s.length() > 1);
         return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
     }
 
         return fixupVPtr(globalData, new (globalData) JSString(globalData, s));
     }
 
@@ -498,30 +474,23 @@ namespace JSC {
         ASSERT(canGetIndex(i));
         if (isRope())
             return getIndexSlowCase(exec, i);
         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)
     {
         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) {
         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));
     }
 
                 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()));
     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)
     {
 
     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) {
         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 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)
     {
     }
 
     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) {
         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));
                 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) {
     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;
             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;
         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
     {
 
     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())
         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 "ExceptionHelpers.h"
 #include "JSString.h"
+#include "UStringConcatenate.h"
 #include "Vector.h"
 
 namespace JSC {
 #include "Vector.h"
 
 namespace JSC {
@@ -65,7 +66,7 @@ public:
 
     void append(const UString& str)
     {
 
     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)
     }
 
     JSValue build(ExecState* exec)
@@ -86,7 +87,7 @@ protected:
 template<typename StringType1, typename StringType2>
 inline JSValue jsMakeNontrivialString(ExecState* exec, StringType1 string1, StringType2 string2)
 {
 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);
     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)
 {
 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);
     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)
 {
 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);
     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)
 {
 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);
     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)
 {
 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);
     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,
         NumberType        = 3,
         NullType          = 4,
         StringType        = 5,
+        LeafType          = 6,
         // The CompoundType value must come before any JSType that may have children
         // 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
     };
 
 } // namespace JSC
index e225bc72ce78a6958f004329e930bc051ba88e8b..1c63a91e7870b02f142b4deca0e657cada284aa5 100644 (file)
 
 namespace JSC {
 
 
 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 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 OverridesGetPropertyNames = 1 << 7;
+    static const unsigned IsJSFinalObject = 1 << 8;
+    static const unsigned ProhibitsPropertyCaching = 1 << 9;
 
     class TypeInfo {
 
     class TypeInfo {
-        friend class JIT;
     public:
         TypeInfo(JSType type, unsigned flags = 0)
             : m_type(type)
     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)
             // 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; }
         }
 
         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 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; }
         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; }
 
         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;
     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 "BooleanConstructor.h"
 #include "BooleanPrototype.h"
+#include "Error.h"
 #include "ExceptionHelpers.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
 #include "ExceptionHelpers.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
@@ -53,18 +54,18 @@ double JSValue::toIntegerPreserveNaN(ExecState* exec) const
     return trunc(toNumber(exec));
 }
 
     return trunc(toNumber(exec));
 }
 
-JSObject* JSValue::toObjectSlowCase(ExecState* exec) const
+JSObject* JSValue::toObjectSlowCase(ExecState* exec, JSGlobalObject* globalObject) const
 {
     ASSERT(!isCell());
 
     if (isInt32() || isDouble())
 {
     ASSERT(!isCell());
 
     if (isInt32() || isDouble())
-        return constructNumber(exec, asValue());
+        return constructNumber(exec, globalObject, asValue());
     if (isTrue() || isFalse())
     if (isTrue() || isFalse())
-        return constructBooleanFromImmediateBoolean(exec, asValue());
+        return constructBooleanFromImmediateBoolean(exec, globalObject, asValue());
+
     ASSERT(isUndefinedOrNull());
     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
 }
 
 JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
@@ -72,9 +73,9 @@ JSObject* JSValue::toThisObjectSlowCase(ExecState* exec) const
     ASSERT(!isCell());
 
     if (isInt32() || isDouble())
     ASSERT(!isCell());
 
     if (isInt32() || isDouble())
-        return constructNumber(exec, asValue());
+        return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
     if (isTrue() || isFalse())
     if (isTrue() || isFalse())
-        return constructBooleanFromImmediateBoolean(exec, asValue());
+        return constructBooleanFromImmediateBoolean(exec, exec->lexicalGlobalObject(), asValue());
     ASSERT(isUndefinedOrNull());
     return exec->globalThisValue();
 }
     ASSERT(isUndefinedOrNull());
     return exec->globalThisValue();
 }
@@ -83,13 +84,13 @@ JSObject* JSValue::synthesizeObject(ExecState* exec) const
 {
     ASSERT(!isCell());
     if (isNumber())
 {
     ASSERT(!isCell());
     if (isNumber())
-        return constructNumber(exec, asValue());
+        return constructNumber(exec, exec->lexicalGlobalObject(), asValue());
     if (isBoolean())
     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
 }
 
 JSObject* JSValue::synthesizePrototype(ExecState* exec) const
@@ -100,9 +101,9 @@ JSObject* JSValue::synthesizePrototype(ExecState* exec) const
     if (isBoolean())
         return exec->lexicalGlobalObject()->booleanPrototype();
 
     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
 }
 
 #ifndef NDEBUG
@@ -125,51 +126,58 @@ char* JSValue::description()
         snprintf(description, size, "False");
     else if (isNull())
         snprintf(description, size, "Null");
         snprintf(description, size, "False");
     else if (isNull())
         snprintf(description, size, "Null");
-    else {
-        ASSERT(isUndefined());
+    else if (isUndefined())
         snprintf(description, size, "Undefined");
         snprintf(description, size, "Undefined");
-    }
+    else
+        snprintf(description, size, "INVALID");
 
     return description;
 }
 #endif
 
 
     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;
         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()
 }
 
 NEVER_INLINE double nonInlineNaN()
@@ -181,4 +189,9 @@ NEVER_INLINE double nonInlineNaN()
 #endif
 }
 
 #endif
 }
 
+bool JSValue::isValidCallee()
+{
+    return asObject(asObject(asCell())->getAnonymousValue(0))->isGlobalObject();
+}
+
 } // namespace JSC
 } // namespace JSC
index 283b3da942f5dd6f27f21928b760c9fe72c2aedb..de50011327c0dc2a1e50e3c49f3f9d3edafcc3cf 100644 (file)
@@ -23,8 +23,6 @@
 #ifndef JSValue_h
 #define JSValue_h
 
 #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 <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/Assertions.h>
 #include <wtf/HashTraits.h>
 #include <wtf/MathExtras.h>
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
+    extern const double NaN;
+    extern const double Inf;
+
+    class ExecState;
     class Identifier;
     class JSCell;
     class JSGlobalData;
     class Identifier;
     class JSCell;
     class JSGlobalData;
-    class JSImmediate;
+    class JSGlobalObject;
     class JSObject;
     class JSString;
     class PropertySlot;
     class JSObject;
     class JSString;
     class PropertySlot;
@@ -48,20 +51,52 @@ namespace JSC {
     struct ClassInfo;
     struct Instruction;
 
     struct ClassInfo;
     struct Instruction;
 
+    template <class T> class WriteBarrierBase;
+
     enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
 
     enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString };
 
+
 #if USE(JSVALUE32_64)
     typedef int64_t EncodedJSValue;
 #else
     typedef void* EncodedJSValue;
 #endif
 #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();
 
     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 {
 
     class JSValue {
-        friend class JSImmediate;
         friend struct EncodedJSValueHashTraits;
         friend class JIT;
         friend class JITStubs;
         friend struct EncodedJSValueHashTraits;
         friend class JIT;
         friend class JITStubs;
@@ -70,14 +105,9 @@ namespace JSC {
         friend class SpecializedThunkJIT;
 
     public:
         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 };
         enum JSNullTag { JSNull };
         enum JSUndefinedTag { JSUndefined };
         enum JSTrueTag { JSTrue };
@@ -93,21 +123,18 @@ namespace JSC {
         JSValue(const JSCell* ptr);
 
         // Numbers
         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;
 
         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
 
         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;
         
         // 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;
         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;
 
         // 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*) const;
-        uint32_t toUInt32(ExecState*, bool& ok) const;
 
 #if ENABLE(JSC_ZOMBIES)
         bool isZombie() const;
 
 #if ENABLE(JSC_ZOMBIES)
         bool isZombie() const;
@@ -190,6 +213,7 @@ namespace JSC {
 
         bool needsThisConversion() const;
         JSObject* toThisObject(ExecState*) const;
 
         bool needsThisConversion() const;
         JSObject* toThisObject(ExecState*) const;
+        JSValue toStrictThisObject(ExecState*) const;
         UString toThisString(ExecState*) const;
         JSString* toThisJSString(ExecState*) const;
 
         UString toThisString(ExecState*) const;
         JSString* toThisJSString(ExecState*) const;
 
@@ -204,55 +228,140 @@ namespace JSC {
 
         bool isCell() const;
         JSCell* asCell() const;
 
         bool isCell() const;
         JSCell* asCell() const;
+        bool isValidCallee();
 
 #ifndef NDEBUG
         char* description();
 #endif
 
     private:
 
 #ifndef NDEBUG
         char* description();
 #endif
 
     private:
+        template <class T> JSValue(WriteBarrierBase<T>);
+
         enum HashTableDeletedValueTag { HashTableDeletedValue };
         JSValue(HashTableDeletedValueTag);
 
         inline const JSValue asValue() const { return *this; }
         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)
         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 { 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 };
         enum { LowestTag =  DeletedValueTag };
-        
+
         uint32_t tag() const;
         int32_t payload() const;
         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
 #endif
-        } u;
-#else // USE(JSVALUE32_64)
-        JSCell* m_ptr;
-#endif // USE(JSVALUE32_64)
+
+        EncodedValueDescriptor u;
     };
 
 #if USE(JSVALUE32_64)
     };
 
 #if USE(JSVALUE32_64)
@@ -289,79 +398,64 @@ namespace JSC {
         return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse);
     }
 
         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); }
     }
 
     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 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
 } // 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)
 {
 
 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);
         return false;
 
     return JSObject::deleteProperty(exec, propertyName);
@@ -60,9 +60,9 @@ bool JSVariableObject::isVariableObject() const
 
 bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
 
 bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
 {
-    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
+    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
     if (!entry.isNull()) {
     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;
         return true;
     }
     return false;
index f2efcdf3989affb0b2ef4b6765ce5f8c6a0939ad..89bb6b02b67d99ac2dc3d45cf538379fcdfcf4b5 100644 (file)
@@ -40,11 +40,11 @@ namespace JSC {
 
     class Register;
 
 
     class Register;
 
-    class JSVariableObject : public JSObject {
+    class JSVariableObject : public JSNonFinalObject {
         friend class JIT;
 
     public:
         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;
 
 
         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;
 
         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;
         }
         
     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 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)
     {
     };
 
     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()) {
         if (!entry.isNull()) {
-            slot.setRegisterSlot(&registerAt(entry.getIndex()));
+            slot.setValue(registerAt(entry.getIndex()).get());
             return true;
         }
         return false;
             return true;
         }
         return false;
@@ -113,55 +101,58 @@ namespace JSC {
 
     inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
     {
 
     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()) {
         if (!entry.isNull()) {
-            slot.setRegisterSlot(&registerAt(entry.getIndex()));
+            slot.setValue(registerAt(entry.getIndex()).get());
             slotIsWriteable = !entry.isReadOnly();
             return true;
         }
         return false;
     }
 
             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));
 
     {
         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;
         if (entry.isNull())
             return false;
         if (entry.isReadOnly())
             return true;
-        registerAt(entry.getIndex()) = value;
+        registerAt(entry.getIndex()).set(globalData, this, value);
         return true;
     }
 
         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));
 
     {
         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);
         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;
     }
 
         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
     }
 
 } // namespace JSC
index 2c39f5c23849fee2affa194d4c6ee59399aba741..8d6387ec0ab20adf7afa53e1f10fdad0430f01e2 100644 (file)
@@ -26,11 +26,14 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(JSWrapperObject);
 
 
 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)
     if (m_internalValue)
-        markStack.append(m_internalValue);
+        visitor.append(&m_internalValue);
 }
 
 } // namespace JSC
 }
 
 } // 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.
 
     // 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:
     protected:
-        explicit JSWrapperObject(NonNullPassRefPtr<Structure>);
+        explicit JSWrapperObject(JSGlobalData&, Structure*);
 
     public:
 
     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:
         }
 
     protected:
-        static const unsigned AnonymousSlotCount = 1 + JSObject::AnonymousSlotCount;
+        static const unsigned StructureFlags = OverridesVisitChildren | JSNonFinalObject::StructureFlags;
 
     private:
 
     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());
     {
         ASSERT(value);
         ASSERT(!value.isObject());
-        m_internalValue = value;
-        putAnonymousValue(0, value);
+        m_internalValue.set(globalData, this, value);
     }
 
 } // namespace JSC
     }
 
 } // namespace JSC
index 072d29b6af9567418cdf99f42a455a97a472ec5e..efabc93fc1bc35196106cfd7d307509c5a3558cb 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "JSZombie.h"
 #include "ClassInfo.h"
 #include "config.h"
 #include "JSZombie.h"
 #include "ClassInfo.h"
+#include "JSObject.h"
+#include "ScopeChain.h"
 
 #if ENABLE(JSC_ZOMBIES)
 
 
 #if ENABLE(JSC_ZOMBIES)
 
@@ -33,16 +35,6 @@ namespace JSC {
 
 const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 };
 
 
 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)
 }
 
 #endif // ENABLE(JSC_ZOMBIES)
index 711f6732bcceaeb81c0e07770c234d2720150f54..795036ea1a33184ee0dd7fd24799f914f52d4d19 100644 (file)
 #define JSZombie_h
 
 #include "JSCell.h"
 #define JSZombie_h
 
 #include "JSCell.h"
+#include "Structure.h"
 
 #if ENABLE(JSC_ZOMBIES)
 namespace JSC {
 
 class JSZombie : public JSCell {
 public:
 
 #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)
     {
         , m_oldInfo(oldInfo)
     {
+        ASSERT(inherits(&s_info));
     }
     }
+
     virtual bool isZombie() const { return true; }
     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; }
 
     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 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 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; }
     
     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;
     static const ClassInfo s_info;
+
 private:
     const ClassInfo* m_oldInfo;
 };
 private:
     const ClassInfo* m_oldInfo;
 };
index cc33bae187be78c14c6fb3a515cdc2577ecf4beb..ed42d0d2fd960f9ec0b26c59519437db1dfc9927 100644 (file)
 #include "JSArray.h"
 #include "JSString.h"
 #include "Lexer.h"
 #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 {
 
 #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);
         ++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;
         case '(':
             token.type = TokLParen;
             token.end = ++m_ptr;
-            return TokLBracket;
+            return TokLParen;
         case ')':
             token.type = TokRParen;
             token.end = ++m_ptr;
         case ')':
             token.type = TokRParen;
             token.end = ++m_ptr;
-            return TokRBracket;
+            return TokRParen;
         case '{':
             token.type = TokLBrace;
             token.end = ++m_ptr;
         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 '"':
             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;
         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;
             }
                 token.end = m_ptr;
                 return TokNull;
             }
-            break;    
+            break;
         case '-':
         case '0':
         case '1':
         case '-':
         case '0':
         case '1':
@@ -122,27 +223,69 @@ LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
         case '9':
             return lexNumber(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;
 }
 
     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.
 }
 
 // "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;
 {
     ++m_ptr;
-    const UChar* runStart;
-    StringBuilder builder;
+    const UChar* runStart = m_ptr;
+    UStringBuilder builder;
     do {
         runStart = m_ptr;
     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;
             ++m_ptr;
-        if (runStart < m_ptr)
+        if (builder.length())
             builder.append(runStart, m_ptr - runStart);
             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;
             ++m_ptr;
             if (m_ptr >= m_end)
                 return TokError;
@@ -192,15 +335,28 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera
                     break;
 
                 default:
                     break;
 
                 default:
+                    if (*m_ptr == '\'' && mode != StrictJSON) {
+                        builder.append('\'');
+                        m_ptr++;
+                        break;
+                    }
                     return TokError;
             }
         }
                     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;
 
         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;
     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;
         ++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]+)?
     }
 
     //  ([eE][+-]? [0-9]+)?
@@ -330,7 +502,7 @@ JSValue LiteralParser::parse(ParserState initialState)
                 objectStack.append(object);
 
                 TokenType type = m_lexer.next();
                 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
                     Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
 
                     // Check for colon
@@ -338,10 +510,11 @@ JSValue LiteralParser::parse(ParserState initialState)
                         return JSValue();
                     
                     m_lexer.next();
                         return JSValue();
                     
                     m_lexer.next();
-                    identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
+                    identifierStack.append(makeIdentifier(identifierToken.stringToken, identifierToken.stringLength));
                     stateStack.append(DoParseObjectEndExpression);
                     goto startParseExpression;
                     stateStack.append(DoParseObjectEndExpression);
                     goto startParseExpression;
-                } else if (type != TokRBrace) 
+                }
+                if (type != TokRBrace) 
                     return JSValue();
                 m_lexer.next();
                 lastValue = objectStack.last();
                     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();
             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();
 
                     return JSValue();
                 Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
 
@@ -360,13 +533,13 @@ JSValue LiteralParser::parse(ParserState initialState)
                     return JSValue();
 
                 m_lexer.next();
                     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:
             {
                 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;
                 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();
                     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();
                         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:
                         break;
                     }
                     case TokNull:
index 0f8072bd583d052931d616f9db809d660338a824..40c3d586f59ae64c627fbf3aa5f15b788c360bbb 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef LiteralParser_h
 #define LiteralParser_h
 
 #ifndef LiteralParser_h
 #define LiteralParser_h
 
+#include "Identifier.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSValue.h"
 #include "UString.h"
 #include "JSGlobalObjectFunctions.h"
 #include "JSValue.h"
 #include "UString.h"
@@ -34,10 +35,10 @@ namespace JSC {
 
     class LiteralParser {
     public:
 
     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_exec(exec)
-            , m_lexer(s, mode)
+            , m_lexer(characters, length, mode)
             , m_mode(mode)
         {
         }
             , m_mode(mode)
         {
         }
@@ -46,10 +47,33 @@ namespace JSC {
         {
             m_lexer.next();
             JSValue result = parse(m_mode == StrictJSON ? StartParseExpression : StartParseStatement);
         {
             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;
         }
             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, 
     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,
         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;
         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()
             {
             
             const LiteralParserToken& currentToken()
             {
@@ -88,9 +114,9 @@ namespace JSC {
             }
             
         private:
             }
             
         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;
             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;
         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
 }
 
 #endif
index cc1981257fed01b34fd80ca4df527e090ec9e086..25b516efb0fa26e1952f5432ff5199995ddfcb47 100644 (file)
@@ -20,8 +20,8 @@
 #include "config.h"
 #include "Lookup.h"
 
 #include "config.h"
 #include "Lookup.h"
 
+#include "Executable.h"
 #include "JSFunction.h"
 #include "JSFunction.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 
 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) {
     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];
 
         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 (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;
                 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)
 {
 
 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);
     ASSERT(entry->attributes() & Function);
-    JSValue* location = thisObj->getDirectLocation(propertyName);
+    WriteBarrierBase<Unknown>* location = thisObj->getDirectLocation(exec->globalData(), propertyName);
 
     if (!location) {
 
     if (!location) {
-        InternalFunction* function;
+        JSFunction* function;
+        JSGlobalObject* globalObject = asGlobalObject(thisObj->getAnonymousValue(0).asCell());
 #if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
         if (entry->generator())
 #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
         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
 }
 
 } // 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);
 
     typedef PropertySlot::GetValueFunc GetFunction;
     typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value);
 
-    class HashEntry : public FastAllocBase {
+    class HashEntry {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
     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
 #if ENABLE(JIT)
                         , ThunkGenerator generator = 0
 #endif
@@ -71,12 +72,12 @@ namespace JSC {
             m_next = 0;
         }
 
             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; }
 
 
         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; }
         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:
         HashEntry* next() const { return m_next; }
 
     private:
-        UString::Rep* m_key;
+        StringImpl* m_key;
         unsigned char m_attributes; // JSObject attributes
 
         union {
         unsigned char m_attributes; // JSObject attributes
 
         union {
@@ -159,13 +160,13 @@ namespace JSC {
         {
             ASSERT(table);
 
         {
             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())
                 return 0;
 
             do {
-                if (entry->key() == identifier.ustring().rep())
+                if (entry->key() == identifier.impl())
                     return entry;
                 entry = entry->next();
             } while (entry);
                     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()))
 
         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
             else
-                thisObj->putDirect(propertyName, value);
+                thisObj->putDirect(exec->globalData(), propertyName, value);
         } else if (!(entry->attributes() & ReadOnly))
             entry->propertyPutter()(exec, thisObj, 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);
 
 
 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 {
 
 
 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
 
 /* Source for MathObject.lut.h
 @begin mathTable
@@ -86,20 +84,20 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable };
 @end
 */
 
 @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)
 {
 
 bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
 {
@@ -113,62 +111,64 @@ bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& pro
 
 // ------------------------------ Functions --------------------------------
 
 
 // ------------------------------ 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 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;
         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;
     }
         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 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;
         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;
     }
         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
 
 {
     // 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))
 
     if (isnan(arg2))
-        return jsNaN(exec);
+        return JSValue::encode(jsNaN());
     if (isinf(arg2) && fabs(arg) == 1)
     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);
     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
 }
 
 } // namespace JSC
index a9f70313d4feab9e12b30d484b4d588b9ec95df5..75753be2922e9b794be2a14820bd5af8175f48f5 100644 (file)
 #ifndef MathObject_h
 #define MathObject_h
 
 #ifndef MathObject_h
 #define MathObject_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class MathObject : public JSObject {
+    class MathObject : public JSObjectWithGlobalObject {
     public:
     public:
-        MathObject(ExecState*, NonNullPassRefPtr<Structure>);
+        MathObject(ExecState*, JSGlobalObject*, Structure*);
 
         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
 
         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:
         }
 
     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);
 
 
 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)
 }
 
 ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructData)
@@ -62,9 +70,11 @@ ConstructType NativeErrorConstructor::getConstructData(ConstructData& constructD
     return ConstructTypeHost;
 }
     
     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)
 }
 
 CallType NativeErrorConstructor::getCallData(CallData& callData)
index 891f9226b128421e58efb55518700659f0274e32..4fb16f1a382e8b4c66119516282fb1687732f5e4 100644 (file)
@@ -31,19 +31,24 @@ namespace JSC {
 
     class NativeErrorConstructor : public InternalFunction {
     public:
 
     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:
 
     private:
+        static const unsigned StructureFlags = OverridesVisitChildren | InternalFunction::StructureFlags;
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
         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
     };
 
 } // namespace JSC
index 43ae6664d939e1e4962c9e8ab92a1146ee1632b4..de27d59ee4e2ea05af5a00ac47d0fcb203ac82a1 100644 (file)
@@ -22,6 +22,7 @@
 #include "NativeErrorPrototype.h"
 
 #include "ErrorPrototype.h"
 #include "NativeErrorPrototype.h"
 
 #include "ErrorPrototype.h"
+#include "JSGlobalObject.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
 #include "UString.h"
 #include "JSString.h"
 #include "NativeErrorConstructor.h"
 #include "UString.h"
@@ -30,12 +31,12 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype);
 
 
 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
 }
 
 } // namespace JSC
index 19468f7444817044155e37eb07f42b0fac2d8c0c..e1b05ceb82bc3f402f31d73659b3829257a10f6d 100644 (file)
 #ifndef NativeErrorPrototype_h
 #define NativeErrorPrototype_h
 
 #ifndef NativeErrorPrototype_h
 #define NativeErrorPrototype_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 
 namespace JSC {
     class NativeErrorConstructor;
 
 
 namespace JSC {
     class NativeErrorConstructor;
 
-    class NativeErrorPrototype : public JSObject {
+    class NativeErrorPrototype : public JSObjectWithGlobalObject {
     public:
     public:
-        NativeErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, const UString&, NativeErrorConstructor*);
+        NativeErrorPrototype(ExecState*, JSGlobalObject*, Structure*, const UString&, NativeErrorConstructor*);
     };
 
 } // namespace JSC
     };
 
 } // 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) 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
  *
  *  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 {
 
 
 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
 
 /* 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
    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
 */
 
 @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
     // 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
 
     // 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)
 {
 }
 
 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)
 {
 }
 
 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
 }
 
 // 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)
 }
 
 ConstructType NumberConstructor::getConstructData(ConstructData& constructData)
@@ -115,9 +117,9 @@ ConstructType NumberConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.7.2
 }
 
 // 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)
 }
 
 CallType NumberConstructor::getCallData(CallData& callData)
index 723c4b283152b01030225e3fae71b50fe926b918..69aa8a1320a70d8083754deeacdf013acb0039a1 100644 (file)
@@ -29,17 +29,17 @@ namespace JSC {
 
     class NumberConstructor : public InternalFunction {
     public:
 
     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;
 
 
         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 };
         }
 
         enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue };
@@ -50,8 +50,6 @@ namespace JSC {
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
     private:
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
-
-        virtual const ClassInfo* classInfo() const { return &info; }
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 1a7e44ccedfd925eb1a5941a93d1775e21d2f2c9..6ee103b38562951e522c5835295a90a6315f2bc7 100644 (file)
@@ -29,11 +29,12 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(NumberObject);
 
 
 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()
 }
 
 JSValue NumberObject::getJSNumber()
@@ -41,10 +42,10 @@ JSValue NumberObject::getJSNumber()
     return internalValue();
 }
 
     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;
 }
 
     return object;
 }
 
index 6c18cdd3bfa441ca588bd8b7cbb7e8c5ebdfb749..cba65dd0f724849f8da6ad7ee3737525b363f710 100644 (file)
@@ -27,29 +27,20 @@ namespace JSC {
 
     class NumberObject : public JSWrapperObject {
     public:
 
     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:
     private:
-        virtual const ClassInfo* classInfo() const { return &info; }
-
         virtual JSValue getJSNumber();
     };
 
         virtual JSValue getJSNumber();
     };
 
-    NumberObject* constructNumber(ExecState*, JSValue);
+    NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
 
 } // namespace JSC
 
 
 } // namespace JSC
 
index 16ceb5cd5525fee84a30e383dad0771d6b680cbb..cbf29da1a3711980a8ea9cd0607f98b0be6c13fb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000,2003 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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 "Error.h"
 #include "JSFunction.h"
 #include "JSString.h"
-#include "JSStringBuilder.h"
 #include "Operations.h"
 #include "Operations.h"
-#include "PrototypeFunction.h"
-#include "StringBuilder.h"
 #include "dtoa.h"
 #include <wtf/Assertions.h>
 #include "dtoa.h"
 #include <wtf/Assertions.h>
+#include <wtf/DecimalNumber.h>
 #include <wtf/MathExtras.h>
 #include <wtf/Vector.h>
 
 namespace JSC {
 
 #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 ---------------------------
 
 }
 
 // ------------------------------ 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)
     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();
     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)
         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";
 
 
     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();
             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)
             }
         }
     }
 
     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
 
     // 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))
     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)
 
     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));
 
     *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)
     // 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)
     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
 }
 
 } // namespace JSC
index 1fb20771e022126a66dcc244e2438001eae76b37..1f1323b687ee7abe47618f107539f271d5b1cd3e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  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:
 
     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
     };
 
 } // namespace JSC
index 89235af7766eb40b12f46913460f8988b039d8c3..d65f14265cdf63fb7449fa49e6f4ef8cdf00af1e 100644 (file)
@@ -27,6 +27,7 @@
 #define NumericStrings_h
 
 #include "UString.h"
 #define NumericStrings_h
 
 #include "UString.h"
+#include <wtf/FixedArray.h>
 #include <wtf/HashFunctions.h>
 
 namespace JSC {
 #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;
             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;
         }
 
             return entry.value;
         }
 
@@ -51,7 +52,7 @@ namespace JSC {
             if (i == entry.key && !entry.value.isNull())
                 return entry.value;
             entry.key = i;
             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;
         }
 
             return entry.value;
         }
 
@@ -63,7 +64,7 @@ namespace JSC {
             if (i == entry.key && !entry.value.isNull())
                 return entry.value;
             entry.key = i;
             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:
             return entry.value;
         }
     private:
@@ -82,14 +83,14 @@ namespace JSC {
         {
             ASSERT(i < cacheSize);
             if (smallIntCache[i].isNull())
         {
             ASSERT(i < cacheSize);
             if (smallIntCache[i].isNull())
-                smallIntCache[i] = UString::from(i);
+                smallIntCache[i] = UString::number(i);
             return smallIntCache[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
     };
 
 } // namespace JSC
index 0838eb43755004b579d6347b09b476a0a0ba93cf..c325fa070b1f7bb9460c218b20b62e78bbd4b8a5 100644 (file)
 #include "ObjectConstructor.h"
 
 #include "Error.h"
 #include "ObjectConstructor.h"
 
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSFunction.h"
 #include "JSArray.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
 #include "JSArray.h"
 #include "JSGlobalObject.h"
+#include "Lookup.h"
 #include "ObjectPrototype.h"
 #include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
 #include "ObjectPrototype.h"
 #include "PropertyDescriptor.h"
 #include "PropertyNameArray.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor);
 
 
 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
 {
     // 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
     // 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
 }
 
 // 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())
 {
     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)
 }
 
 ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
@@ -80,9 +115,10 @@ ConstructType ObjectConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
     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)
 }
 
 CallType ObjectConstructor::getCallData(CallData& callData)
@@ -91,75 +127,75 @@ CallType ObjectConstructor::getCallData(CallData& callData)
     return CallTypeHost;
 }
 
     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())
     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))
     PropertyDescriptor descriptor;
     if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
-        return jsUndefined();
+        return JSValue::encode(jsUndefined());
     if (exec->hadException())
     if (exec->hadException())
-        return jsUndefined();
+        return JSValue::encode(jsUndefined());
 
     JSObject* description = constructEmptyObject(exec);
     if (!descriptor.isAccessorDescriptor()) {
 
     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 {
     } 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.
 }
 
 // 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);
     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()));
     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.
 }
 
 // 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);
     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()));
     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()) {
 }
 
 // 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);
         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;
             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
                 return false;
             }
         } else
@@ -216,8 +252,8 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
             return false;
         if (!set.isUndefined()) {
             CallData callData;
             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
                 return false;
             }
         } else
@@ -230,32 +266,32 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor
         return true;
 
     if (desc.value()) {
         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()) {
         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;
 }
 
         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())
     if (exec->hadException())
-        return jsNull();
+        return JSValue::encode(jsNull());
     PropertyDescriptor descriptor;
     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);
     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)
 }
 
 static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* properties)
@@ -292,26 +328,77 @@ static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* pro
     return object;
 }
 
     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
 }
 
 } // namespace JSC
index 1d2cddeacca5cee733d363aea6b26fd2a81457fa..6ebafcdadfaa8c568414a206dfa0242eb36441f9 100644 (file)
@@ -29,7 +29,20 @@ namespace JSC {
 
     class ObjectConstructor : public InternalFunction {
     public:
 
     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&);
 
     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) 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
  *
  *  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 "JSFunction.h"
 #include "JSString.h"
 #include "JSStringBuilder.h"
-#include "PrototypeFunction.h"
 
 namespace JSC {
 
 
 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);
 
 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)
 {
     , 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)
 {
 }
 
 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;
 
     if (m_hasNoPropertiesWithUInt32Names) {
         bool isUInt32;
-        propertyName.toStrictUInt32(&isUInt32);
+        propertyName.toUInt32(isUInt32);
         m_hasNoPropertiesWithUInt32Names = !isUInt32;
     }
 }
         m_hasNoPropertiesWithUInt32Names = !isUInt32;
     }
 }
@@ -74,82 +86,100 @@ bool ObjectPrototype::getOwnPropertySlot(ExecState* exec, unsigned propertyName,
 {
     if (m_hasNoPropertiesWithUInt32Names)
         return false;
 {
     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);
 
     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())
 
     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();
     }
 }
 
         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;
     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;
     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
 }
 
 } // namespace JSC
index 489d962441b02efba2dc2b6a7839a6d87796d4d2..ec30b9c1feb80916e08ee707682f09dd3d03aaf4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
 /*
  *  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
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 
 namespace JSC {
 
 
 namespace JSC {
 
-    class ObjectPrototype : public JSObject {
+    class ObjectPrototype : public JSNonFinalObject {
     public:
     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&);
 
     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 getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
 
         bool m_hasNoPropertiesWithUInt32Names;
     };
 
 
         bool m_hasNoPropertiesWithUInt32Names;
     };
 
-    JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&);
+    EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*);
 
 } // namespace JSC
 
 
 } // 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));
 
     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)
 }
 
 JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v)
@@ -85,7 +85,7 @@ bool jsIsObjectType(JSValue v)
     if (!v.isCell())
         return v.isNull();
 
     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) {
     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 "ExceptionHelpers.h"
 #include "Interpreter.h"
-#include "JSImmediate.h"
-#include "JSNumberCell.h"
 #include "JSString.h"
 #include "JSString.h"
+#include "JSValueInlineMethods.h"
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -46,7 +45,7 @@ namespace JSC {
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
         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)
         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)
     {
 
     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();
         if (!length1)
             return s2;
         unsigned length2 = s2->length();
@@ -71,7 +70,7 @@ namespace JSC {
         if ((length1 + length2) < length1)
             return throwOutOfMemoryError(exec);
 
         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)
         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 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);
 
         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)
         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)
     {
 
     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);
         if (!length1)
             return jsString(exec, u2);
-        unsigned length2 = u2.size();
+        unsigned length2 = u2.length();
         if (!length2)
             return jsString(exec, u1);
         if ((length1 + length2) < length1)
         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)
     {
 
     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)
         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()))
         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;
         }
             else
                 ++fiberCount;
         }
@@ -189,17 +188,17 @@ namespace JSC {
         return new (globalData) JSString(globalData, ropeBuilder.release());
     }
 
         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()))
     {
         unsigned fiberCount = 0;
         if (LIKELY(thisValue.isString()))
-            fiberCount += asString(thisValue)->size();
+            fiberCount += asString(thisValue)->fiberCount();
         else
             ++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()))
             if (LIKELY(v.isString()))
-                fiberCount += asString(v)->size();
+                fiberCount += asString(v)->fiberCount();
             else
                 ++fiberCount;
         }
             else
                 ++fiberCount;
         }
@@ -216,8 +215,8 @@ namespace JSC {
         unsigned length = 0;
         bool overflow = false;
 
         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
             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))
     {
         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()
         
         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)
     {
 
     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) {
         size_t count = 0;
 
         while (slotBase != cell) {
@@ -424,14 +423,14 @@ namespace JSC {
             if (v.isNull())
                 return 0;
 
             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()) {
 
             // 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)
                 if (slotBase == cell)
-                    slotOffset = cell->structure()->get(propertyName); 
+                    slotOffset = cell->structure()->get(callFrame->globalData(), propertyName); 
             }
 
             ++count;
             }
 
             ++count;
@@ -449,18 +448,18 @@ namespace JSC {
             if (v.isNull())
                 return count;
 
             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())
 
             // 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;
         }
     }
 
 
             ++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;
     {
         ScopeChainIterator iter = scopeChain->begin();
         ScopeChainIterator next = iter;
@@ -471,8 +470,13 @@ namespace JSC {
         PropertySlot slot;
         JSObject* base;
         while (true) {
         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;
                 return base;
 
             iter = next;
index 44dc2b84ffd40cb8866cc0ddb27527ede48457e1..28a9364948dda664804fadc54794566001f9a251 100644 (file)
 #define PropertyMapHashTable_h
 
 #include "UString.h"
 #define PropertyMapHashTable_h
 
 #include "UString.h"
+#include "WriteBarrier.h"
+#include <wtf/HashTable.h>
+#include <wtf/PassOwnPtr.h>
 #include <wtf/Vector.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 {
 
 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
 } // namespace JSC
 
 #endif // PropertyMapHashTable_h
index 6b246691ba24af4b596cdbd2e719a271d480998f..8efb4065e1739cf05d5d9166c75becd80dde30fc 100644 (file)
@@ -21,6 +21,8 @@
 #include "config.h"
 #include "PropertyNameArray.h"
 
 #include "config.h"
 #include "PropertyNameArray.h"
 
+#include "JSObject.h"
+#include "ScopeChain.h"
 #include "Structure.h"
 #include "StructureChain.h"
 
 #include "Structure.h"
 #include "StructureChain.h"
 
@@ -28,20 +30,20 @@ namespace JSC {
 
 static const size_t setThreshold = 20;
 
 
 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) {
 
     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)
                 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;
         }
         if (!m_set.add(identifier).second)
             return;
index 3dbcc9df746ffaa1f8e6f760a5dc072ca44d391c..0da930f173f13f4a3e1b8c04d666a8c041a71ad5 100644 (file)
@@ -68,9 +68,9 @@ namespace JSC {
 
         JSGlobalData* globalData() { return m_globalData; }
 
 
         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]; }
 
         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:
         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;
 
         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);
 
     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
 }
 
 } // namespace JSC
index de9ddc99822a633f024e96362188d9d5c4ab6bc0..ce29ac4e6c7bb85553e7abcb79741adba36104f0 100644 (file)
@@ -32,8 +32,7 @@ namespace JSC {
     class ExecState;
     class JSObject;
 
     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)
 
 #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
         {
 
         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)
             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
         {
 
         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)
             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;
         }
 
             return m_offset;
         }
 
-        void setValueSlot(JSValue* valueSlot) 
+        void setValue(JSValue slotBase, JSValue value)
         {
         {
-            ASSERT(valueSlot);
-            clearBase();
+            ASSERT(value);
             clearOffset();
             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_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_slotBase = slotBase;
-            m_data.valueSlot = valueSlot;
+            m_value = value;
             m_offset = offset;
             m_cachedPropertyType = Value;
         }
             m_offset = offset;
             m_cachedPropertyType = Value;
         }
-        
+
         void setValue(JSValue value)
         {
             ASSERT(value);
             clearBase();
             clearOffset();
         void setValue(JSValue value)
         {
             ASSERT(value);
             clearBase();
             clearOffset();
-            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_getValue = JSC_VALUE_MARKER;
             m_value = value;
             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)
         }
 
         void setCustom(JSValue slotBase, GetValueFunc getValue)
@@ -251,8 +228,6 @@ namespace JSC {
         JSValue m_slotBase;
         union {
             JSObject* getterFunc;
         JSValue m_slotBase;
         union {
             JSObject* getterFunc;
-            JSValue* valueSlot;
-            Register* registerSlot;
             unsigned index;
         } m_data;
 
             unsigned index;
         } m_data;
 
index a0d5443dce723923e09c0c524a5231dae9b9c709..843c9e11148cc70a67cdb6625447263168bff7a8 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef Protect_h
 #define Protect_h
 
 #ifndef Protect_h
 #define Protect_h
 
-#include "Collector.h"
+#include "Heap.h"
 #include "JSValue.h"
 
 namespace JSC {
 #include "JSValue.h"
 
 namespace JSC {
@@ -52,164 +52,15 @@ namespace JSC {
     inline void gcProtect(JSValue value)
     {
         if (value && value.isCell())
     inline void gcProtect(JSValue value)
     {
         if (value && value.isCell())
-            gcProtect(asCell(value));
+            gcProtect(value.asCell());
     }
 
     inline void gcUnprotect(JSValue value)
     {
         if (value && value.isCell())
     }
 
     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
 } // 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 };
 
     public:
         enum Type { Uncachable, ExistingProperty, NewProperty };
 
-        PutPropertySlot()
+        PutPropertySlot(bool isStrictMode = false)
             : m_type(Uncachable)
             , m_base(0)
             : 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; }
 
         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;
         }
         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;
     private:
         Type m_type;
         JSObject* m_base;
         size_t m_offset;
+        bool m_isStrictMode;
     };
 
 } // namespace JSC
     };
 
 } // 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) 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
  *
  *  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 "config.h"
 #include "RegExp.h"
+
 #include "Lexer.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>
 
 #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 {
 
 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_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()
 {
 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)
 #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
 #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
 #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 (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;
         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) {
         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);
         }
 
         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;
 
             offsetVector[j] = -1;
 
-
+        int result;
 #if ENABLE(YARR_JIT)
 #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
 #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
 #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;
     }
 
 
         return result;
     }
 
-    m_lastMatchString = UString();
-    m_lastMatchStart = -1;
-    m_lastOVector.shrink(0);
-
     return -1;
 }
 
     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 {
         } 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
 
 #endif
 
+        printf("%-40.40s %16.16s %10d %10d\n", formattedPattern, jitAddr, m_rtMatchCallCount, m_rtMatchFoundCount);
+    }
+#endif
+    
 } // namespace JSC
 } // namespace JSC
index 04022bc9563850f2a1bb2499e066993523a2c12a..79f4694ee134bfd60ef396a31bdeeb44bc94e3e2 100644 (file)
 
 #include "UString.h"
 #include "ExecutableAllocator.h"
 
 #include "UString.h"
 #include "ExecutableAllocator.h"
+#include "Structure.h"
+#include "RegExpKey.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
-#include "yarr/RegexJIT.h"
-#include "yarr/RegexInterpreter.h"
-
-struct JSRegExp;
 
 namespace JSC {
 
 
 namespace JSC {
 
+    struct RegExpRepresentation;
     class JSGlobalData;
 
     class JSGlobalData;
 
-    class RegExp : public RefCounted<RegExp> {
+    RegExpFlags regExpFlags(const UString&);
+
+    class RegExp : public JSCell {
     public:
     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();
         ~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; }
 
         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; }
 
         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:
     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;
         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
 #endif
+
+        OwnPtr<RegExpRepresentation> m_representation;
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index 5e9d610c74bea4c9b93c79127e41a5c8602b0b5c..2dce19797b8e185f130455a4edaf211fa9f35a70 100644 (file)
 #include "config.h"
 
 #include "RegExpCache.h"
 #include "config.h"
 
 #include "RegExpCache.h"
+#include "RegExpObject.h"
 
 namespace JSC {
 
 
 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 "RegExp.h"
 #include "RegExpKey.h"
+#include "Strong.h"
 #include "UString.h"
 #include "UString.h"
+#include "Weak.h"
+#include <wtf/FixedArray.h>
+#include <wtf/HashMap.h>
 
 #ifndef RegExpCache_h
 #define RegExpCache_h
 
 namespace JSC {
 
 
 #ifndef RegExpCache_h
 #define RegExpCache_h
 
 namespace JSC {
 
-class RegExpCache {
+class RegExpCache : private WeakHandleOwner {
+friend class RegExp;
+typedef HashMap<RegExpKey, Weak<RegExp> > RegExpCacheMap;
+
 public:
 public:
-    PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags);
-    PassRefPtr<RegExp> create(const UString& patternString, const UString& flags);
     RegExpCache(JSGlobalData* globalData);
     RegExpCache(JSGlobalData* globalData);
-    
-    static bool isCacheable(const UString& patternString) { return patternString.size() < maxCacheablePatternLength; }
+    void invalidateCode();
 
 private:
 
 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;
     JSGlobalData* m_globalData;
-    int m_nextKeyToEvict;
-    bool m_isFull;
 };
 
 } // namespace JSC
 };
 
 } // namespace JSC
index 5332a874f74438f1ef162e8aaac794bfcb5b3aa2..3e499bacbec0d22ec9eb684afed89f7cbab0f581 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "ArrayPrototype.h"
 #include "Error.h"
 
 #include "ArrayPrototype.h"
 #include "Error.h"
+#include "ExceptionHelpers.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "JSString.h"
 #include "RegExpPrototype.h"
 #include "RegExp.h"
 #include "RegExpCache.h"
 #include "RegExpPrototype.h"
 #include "RegExp.h"
 #include "RegExpCache.h"
+#include "UStringConcatenate.h"
+#include <wtf/PassOwnPtr.h>
+
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -64,7 +69,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor);
 
 
 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
 
 /* Source for RegExpConstructor.lut.h
 @begin regExpConstructorTable
@@ -92,19 +97,21 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info,
 @end
 */
 
 @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
     // 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
 
     // 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)
 }
 
 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;
 {
     RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
     d->input = data->lastInput;
@@ -139,7 +146,7 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
     }
 
     PutPropertySlot slot;
     }
 
     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;
     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())
 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);
 }
     
     return jsEmptyString(exec);
 }
     
@@ -286,31 +293,42 @@ void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValu
 {
     asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
 }
 {
     asRegExpConstructor(baseObject)->setMultiline(value.toBoolean(exec));
 }
-  
+
 // ECMA 15.10.4
 // 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);
 
 {
     JSValue arg0 = args.at(0);
     JSValue arg1 = args.at(1);
 
-    if (arg0.inherits(&RegExpObject::info)) {
+    if (arg0.inherits(&RegExpObject::s_info)) {
         if (!arg1.isUndefined())
         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);
         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())
     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)
 }
 
 ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
@@ -320,9 +338,10 @@ ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
 }
 
 // ECMA 15.10.3
 }
 
 // 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)
 }
 
 CallType RegExpConstructor::getCallData(CallData& callData)
index 8f4be71687a0f3177738060bcdbb9bcea02fca65..1d02e6ff7cfc4155457931a11e925d164edb580b 100644 (file)
@@ -31,7 +31,9 @@ namespace JSC {
     class RegExpPrototype;
     struct RegExpConstructorPrivate;
 
     class RegExpPrototype;
     struct RegExpConstructorPrivate;
 
-    struct RegExpConstructorPrivate : FastAllocBase {
+    struct RegExpConstructorPrivate {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
         // Global search cache / settings
         RegExpConstructorPrivate()
             : lastNumSubPatterns(0)
         // Global search cache / settings
         RegExpConstructorPrivate()
             : lastNumSubPatterns(0)
@@ -55,20 +57,20 @@ namespace JSC {
 
     class RegExpConstructor : public InternalFunction {
     public:
 
     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&);
 
         }
 
         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&);
         JSObject* arrayOfMatches(ExecState*) const;
 
         void setInput(const UString&);
@@ -89,18 +91,16 @@ namespace JSC {
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
         virtual ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
 
-        virtual const ClassInfo* classInfo() const { return &info; }
-
         OwnPtr<RegExpConstructorPrivate> d;
     };
 
     RegExpConstructor* asRegExpConstructor(JSValue);
 
         OwnPtr<RegExpConstructorPrivate> d;
     };
 
     RegExpConstructor* asRegExpConstructor(JSValue);
 
-    JSObject* constructRegExp(ExecState*, const ArgList&);
+    JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&);
 
     inline RegExpConstructor* asRegExpConstructor(JSValue value)
     {
 
     inline RegExpConstructor* asRegExpConstructor(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
+        ASSERT(asObject(value)->inherits(&RegExpConstructor::s_info));
         return static_cast<RegExpConstructor*>(asObject(value));
     }
 
         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.
     */
       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();
 
         if (ovector)
             *ovector = d->tempOvector().data();
index e5ab43892d9b41a6adced5fe9429c973192b8bf5..b4847f97114d0039d50e2e25f529209e622edf26 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "UString.h"
-
 #ifndef RegExpKey_h
 #define RegExpKey_h
 
 #ifndef RegExpKey_h
 #define RegExpKey_h
 
+#include "UString.h"
+#include <wtf/text/StringHash.h>
+
 namespace JSC {
 
 namespace JSC {
 
+enum RegExpFlags {
+    NoFlags = 0,
+    FlagGlobal = 1,
+    FlagIgnoreCase = 2,
+    FlagMultiline = 4,
+    InvalidFlags = 8,
+    DeletedValueFlags = -1
+};
+
 struct RegExpKey {
 struct RegExpKey {
-    int flagsValue;
-    RefPtr<UString::Rep> pattern;
+    RegExpFlags flagsValue;
+    RefPtr<StringImpl> pattern;
 
     RegExpKey()
 
     RegExpKey()
-        : flagsValue(0)
+        : flagsValue(NoFlags)
     {
     }
 
     {
     }
 
-    RegExpKey(int flags)
+    RegExpKey(RegExpFlags flags)
         : flagsValue(flags)
     {
     }
 
         : flagsValue(flags)
     {
     }
 
-    RegExpKey(int flags, const UString& pattern)
+    RegExpKey(RegExpFlags flags, const UString& pattern)
         : flagsValue(flags)
         : 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)
     {
     }
 
         : 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;
 {
     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());
 }
 
     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; }
 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> {
 };
 
 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
 
 };
 } // namespace WTF
 
index bc74924d0dba433523627b8b463404b75c049441..fc3b2058c48f80de1ad30818cf99ff45484f1dad 100644 (file)
 #include "RegExpObject.h"
 
 #include "Error.h"
 #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 "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 {
 
 
 namespace JSC {
 
@@ -46,7 +51,7 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(RegExpObject);
 
 
 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
 
 /* Source for RegExpObject.lut.h
 @begin regExpTable
@@ -58,16 +63,29 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
 @end
 */
 
 @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()
 {
 }
 
 }
 
 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);
 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());
 }
 
     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)
 }
 
 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)
 {
 
 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();
 }
 
         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.
 // 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();
 {
     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;
     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;
     }
 
         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;
     }
 
     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) {
     if (position < 0) {
-        d->lastIndex = 0;
+        setLastIndex(0);
         return false;
     }
 
         return false;
     }
 
-    d->lastIndex = position + length;
+    setLastIndex(position + length);
     return true;
 }
 
     return true;
 }
 
index 4ad11ef7a5907264b281b850fef1a62e3ac6ee12..6fc6cb9a72f298527c3a654ef55b8248e7eb0740 100644 (file)
 #ifndef RegExpObject_h
 #define RegExpObject_h
 
 #ifndef RegExpObject_h
 #define RegExpObject_h
 
-#include "JSObject.h"
+#include "JSObjectWithGlobalObject.h"
 #include "RegExp.h"
 
 namespace JSC {
 #include "RegExp.h"
 
 namespace JSC {
-
-    class RegExpObject : public JSObject {
+    
+    class RegExpObject : public JSObjectWithGlobalObject {
     public:
     public:
-        RegExpObject(NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>);
+        typedef JSObjectWithGlobalObject Base;
+
+        RegExpObject(JSGlobalObject*, Structure*, RegExp*);
         virtual ~RegExpObject();
 
         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(); }
 
         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 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:
         }
 
     protected:
-        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | JSObjectWithGlobalObject::StructureFlags;
 
     private:
 
     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;
     };
 
         OwnPtr<RegExpObjectData> d;
     };
 
@@ -78,7 +93,7 @@ namespace JSC {
 
     inline RegExpObject* asRegExpObject(JSValue value)
     {
 
     inline RegExpObject* asRegExpObject(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&RegExpObject::info));
+        ASSERT(asObject(value)->inherits(&RegExpObject::s_info));
         return static_cast<RegExpObject*>(asObject(value));
     }
 
         return static_cast<RegExpObject*>(asObject(value));
     }
 
index 7c34b21a4d8811cafa3f744e2286fc63c53ae5e0..26f62330a0d5ec225e1538769ceb7a25e38870c1 100644 (file)
 #include "JSStringBuilder.h"
 #include "JSValue.h"
 #include "ObjectPrototype.h"
 #include "JSStringBuilder.h"
 #include "JSValue.h"
 #include "ObjectPrototype.h"
-#include "PrototypeFunction.h"
 #include "RegExpObject.h"
 #include "RegExp.h"
 #include "RegExpCache.h"
 #include "RegExpObject.h"
 #include "RegExp.h"
 #include "RegExpCache.h"
+#include "StringRecursionChecker.h"
+#include "UStringConcatenate.h"
 
 namespace JSC {
 
 
 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 ---------------------------
 }
 
 // ------------------------------ 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())
         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 {
         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())
     }
 
     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);
     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;
     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';
         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';
         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';
         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
     // 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
 }
 
 } // namespace JSC
index d3979bdd216ed7b8e70f8ab6fc675fc99d3cddb9..83e75be0252912d4d349cffab61492cd8abf5f5a 100644 (file)
 #ifndef RegExpPrototype_h
 #define RegExpPrototype_h
 
 #ifndef RegExpPrototype_h
 #define RegExpPrototype_h
 
+#include "RegExpObject.h"
 #include "JSObject.h"
 
 namespace JSC {
 
 #include "JSObject.h"
 
 namespace JSC {
 
-    class RegExpPrototype : public JSObject {
+    class RegExpPrototype : public RegExpObject {
     public:
     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
     };
 
 } // namespace JSC
index 25b9848177ed0c3df7354f76573b59696981caf0..09c24a9dd38e75b923de3a5484b0c958a2eb491a 100644 (file)
@@ -40,7 +40,7 @@ void RopeImpl::derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue)
             else
                 nextRope->deref();
         } else
             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
 
 #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.
 
 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.
     typedef StringImplBase* Fiber;
 
     // Creates a RopeImpl comprising of 'fiberCount' Fibers.
@@ -56,7 +56,7 @@ public:
         if (isRope(fiber))
             static_cast<RopeImpl*>(fiber)->deref();
         else
         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)
     }
 
     void initializeFiber(unsigned &index, Fiber fiber)
index 981794bee91c7faa2e1dad1558834ea539edf717..df4da41c021394270654c051c6f7c8e52885ec65 100644 (file)
@@ -31,11 +31,11 @@ namespace JSC {
 
 #ifndef NDEBUG
 
 
 #ifndef NDEBUG
 
-void ScopeChainNode::print() const
+void ScopeChainNode::print()
 {
     ScopeChainIterator scopeEnd = end();
     for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) {
 {
     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();
         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, "----- [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");
     }
         }
         fprintf(stderr, "\n");
     }
@@ -51,12 +51,14 @@ void ScopeChainNode::print() const
 
 #endif
 
 
 #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();
 {
     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;
         ++iter;
         if (iter == end)
             break;
@@ -65,4 +67,16 @@ int ScopeChain::localDepth() const
     return scopeDepth;
 }
 
     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
 } // namespace JSC
index 0b15b67b39a0381b2f27a53422bd2fc75461bcfd..7fbb888e3b4ae62114f9b9271e1e2cf2071167e3 100644 (file)
@@ -21,7 +21,9 @@
 #ifndef ScopeChain_h
 #define ScopeChain_h
 
 #ifndef ScopeChain_h
 #define ScopeChain_h
 
-#include "FastAllocBase.h"
+#include "JSCell.h"
+#include "Structure.h"
+#include <wtf/FastAllocBase.h>
 
 namespace JSC {
 
 
 namespace JSC {
 
@@ -30,110 +32,71 @@ namespace JSC {
     class JSObject;
     class MarkStack;
     class ScopeChainIterator;
     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)
     public:
         ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis)
-            : next(next)
-            , object(object)
+            : JSCell(*globalData, globalData->scopeChainNodeStructure.get())
             , globalData(globalData)
             , 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);
         }
         {
             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;
         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();
 
 
         ScopeChainNode* push(JSObject*);
         ScopeChainNode* pop();
 
-        ScopeChainIterator begin() const;
-        ScopeChainIterator end() const;
+        ScopeChainIterator begin();
+        ScopeChainIterator end();
+
+        int localDepth();
 
 #ifndef NDEBUG        
 
 #ifndef NDEBUG        
-        void print() const;
+        void print();
 #endif
 #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);
     };
 
     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);
     }
 
     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:
     }
 
     class ScopeChainIterator {
     public:
-        ScopeChainIterator(const ScopeChainNode* node)
+        ScopeChainIterator(ScopeChainNode* node)
             : m_node(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
 
 
         // postfix ++ intentionally omitted
 
@@ -141,99 +104,43 @@ namespace JSC {
         bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
 
     private:
         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); 
     }
 
     {
         return ScopeChainIterator(this); 
     }
 
-    inline ScopeChainIterator ScopeChainNode::end() const
+    inline ScopeChainIterator ScopeChainNode::end()
     { 
         return ScopeChainIterator(0); 
     }
 
     { 
         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;
     }
 
         return *this;
     }
 
index 984d101368a9bc9ca078da27accb02f75a1deed6..35701f11d05339ca04a2c1943277c73eef48dde7 100644 (file)
 
 namespace JSC {
 
 
 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
 } // 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
  *
  * 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 "JSGlobalObject.h"
 #include "JSString.h"
-
 #include <wtf/Noncopyable.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
 
 namespace JSC {
 
 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();
 
 public:
     SmallStringsStorage();
 
-    UString::Rep* rep(unsigned char character) { return m_reps[character].get(); }
+    StringImpl* rep(unsigned char character)
+    {
+        return m_reps[character].get();
+    }
 
 private:
 
 private:
-    RefPtr<UString::Rep> m_reps[numCharactersToStore];
+    static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
+
+    RefPtr<StringImpl> m_reps[singleCharacterStringCount];
 };
 
 SmallStringsStorage::SmallStringsStorage()
 {
     UChar* characterBuffer = 0;
 };
 
 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;
         characterBuffer[i] = i;
-        m_reps[i] = UStringImpl::create(baseString, i, 1);
+        m_reps[i] = StringImpl::create(baseString, i, 1);
     }
 }
 
 SmallStrings::SmallStrings()
 {
     }
 }
 
 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();
 }
 
     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
 {
     /*
        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);
      */
 
     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) {
         isAnyStringMarked = isMarked(m_singleCharacterStrings[i]);
     
     if (!isAnyStringMarked) {
@@ -91,17 +96,17 @@ void SmallStrings::markChildren(MarkStack& markStack)
     }
     
     if (m_emptyString)
     }
     
     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])
         if (m_singleCharacterStrings[i])
-            markStack.append(m_singleCharacterStrings[i]);
+            heapRootMarker.mark(&m_singleCharacterStrings[i]);
     }
 }
 
 void SmallStrings::clear()
 {
     m_emptyString = 0;
     }
 }
 
 void SmallStrings::clear()
 {
     m_emptyString = 0;
-    for (unsigned i = 0; i < numCharactersToStore; ++i)
+    for (unsigned i = 0; i < singleCharacterStringCount; ++i)
         m_singleCharacterStrings[i] = 0;
 }
 
         m_singleCharacterStrings[i] = 0;
 }
 
@@ -110,7 +115,7 @@ unsigned SmallStrings::count() const
     unsigned count = 0;
     if (m_emptyString)
         ++count;
     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;
     }
         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)
 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]);
     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)
 {
     if (!m_storage)
-        m_storage.set(new SmallStringsStorage);
+        m_storage = adoptPtr(new SmallStringsStorage);
     return m_storage->rep(character);
 }
 
     return m_storage->rep(character);
 }
 
index bc337c995806d35c1af111c5693760de122d3d54..e762e1f365c88c38d02cce2d775bd192e6c996c1 100644 (file)
 #define SmallStrings_h
 
 #include "UString.h"
 #define SmallStrings_h
 
 #include "UString.h"
+#include <wtf/FixedArray.h>
 #include <wtf/OwnPtr.h>
 
 namespace JSC {
 
 #include <wtf/OwnPtr.h>
 
 namespace JSC {
 
+    class HeapRootVisitor;
     class JSGlobalData;
     class JSString;
     class MarkStack;
     class SmallStringsStorage;
     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();
     public:
         SmallStrings();
         ~SmallStrings();
@@ -47,6 +53,7 @@ namespace JSC {
                 createEmptyString(globalData);
             return m_emptyString;
         }
                 createEmptyString(globalData);
             return m_emptyString;
         }
+
         JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
         {
             if (!m_singleCharacterStrings[character])
         JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character)
         {
             if (!m_singleCharacterStrings[character])
@@ -54,21 +61,23 @@ namespace JSC {
             return m_singleCharacterStrings[character];
         }
 
             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;
         void clear();
 
         unsigned count() const;
-#if ENABLE(JIT)
-        JSString** singleCharacterStrings() { return m_singleCharacterStrings; }
-#endif
+
+        JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; }
+
     private:
     private:
+        static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1;
+
         void createEmptyString(JSGlobalData*);
         void createSingleCharacterString(JSGlobalData*, unsigned char);
 
         JSString* m_emptyString;
         void createEmptyString(JSGlobalData*);
         void createSingleCharacterString(JSGlobalData*, unsigned char);
 
         JSString* m_emptyString;
-        JSString* m_singleCharacterStrings[0x100];
+        JSString* m_singleCharacterStrings[singleCharacterStringCount];
         OwnPtr<SmallStringsStorage> m_storage;
     };
 
         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 "config.h"
 #include "StringConstructor.h"
 
+#include "Executable.h"
+#include "JITCode.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
 #include "JSFunction.h"
 #include "JSGlobalObject.h"
-#include "PrototypeFunction.h"
 #include "StringPrototype.h"
 
 namespace JSC {
 
 #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)
 }
 
 ConstructType StringConstructor::getConstructData(ConstructData& constructData)
@@ -77,12 +97,11 @@ ConstructType StringConstructor::getConstructData(ConstructData& constructData)
     return ConstructTypeHost;
 }
 
     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)
 }
 
 CallType StringConstructor::getCallData(CallData& callData)
index e511f7bf2ea0a76ff5082bd30b66b7a2c66e972c..b2e3be60949d7c3d9ad2a662ac53530988f2af2f 100644 (file)
@@ -29,10 +29,24 @@ namespace JSC {
 
     class StringConstructor : public InternalFunction {
     public:
 
     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 ConstructType getConstructData(ConstructData&);
         virtual CallType getCallData(CallData&);
+
+        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
     };
 
 } // namespace JSC
     };
 
 } // namespace JSC
index f8e0e872b40c549006080e50f3228bedf98b91b3..67dc291b09ecf7d7eba88aaf296fa5348ec22cf9 100644 (file)
@@ -27,24 +27,27 @@ namespace JSC {
 
 ASSERT_CLASS_FITS_IN_CELL(StringObject);
 
 
 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)
 }
 
 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;
     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);
     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)
 {
     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);
     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:
 
     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&);
 
         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 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());}
 
 
         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:
         }
 
     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)
     {
 
     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));
     }
 
         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,
         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:
         }
 
     private:
-        StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string)
+        StringObjectThatMasqueradesAsUndefined(ExecState* exec, Structure* structure, const UString& string)
             : StringObject(exec, structure, 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;
         }
 
         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);
 
 
 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 {
 
 
 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
 
 /* 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
 */
 
 // ECMA 15.5.4
-StringPrototype::StringPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
+StringPrototype::StringPrototype(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
     : StringObject(exec, structure)
 {
     : StringObject(exec, structure)
 {
+    ASSERT(inherits(&s_info));
+
+    putAnonymousValue(exec->globalData(), 0, globalObject);
     // The constructor will be added later, after StringConstructor has been built
     // 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)
 }
 
 bool StringPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
@@ -152,19 +153,19 @@ bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier
 
 // ------------------------------ Functions --------------------------
 
 
 // ------------------------------ 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 {
 {
     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;
             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;
         }
             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 = 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;
         } 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';
                 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)
             continue;
 
         if (i - offset)
-            substitutedReplacement.append(replacement.data() + offset, i - offset);
+            substitutedReplacement.append(replacement.characters() + offset, i - offset);
         i += 1 + advance;
         offset = i + 1;
         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);
 
     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)
 {
 
 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 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 {
 }
 
 struct StringRange {
@@ -246,30 +248,29 @@ public:
     int length;
 };
 
     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) {
 {
     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
         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++)
     }
 
     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;
 
     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);
 
     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) {
     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) {
         }
         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);
 }
 
         }
     }
 
     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);
     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;
 
     UString replacementString;
     CallData callData;
-    CallType callType = replacement.getCallData(callData);
+    CallType callType = getCallData(replacement, callData);
     if (callType == CallTypeNone)
         replacementString = replacement.toString(exec);
 
     if (callType == CallTypeNone)
         replacementString = replacement.toString(exec);
 
-    if (pattern.inherits(&RegExpObject::info)) {
+    if (pattern.inherits(&RegExpObject::s_info)) {
         const UString& source = sourceVal->value(exec);
         const UString& source = sourceVal->value(exec);
+        unsigned sourceLen = source.length();
         if (exec->hadException())
         if (exec->hadException())
-            return JSValue();
+            return JSValue::encode(JSValue());
         RegExp* reg = asRegExpObject(pattern)->regExp();
         bool global = reg->global();
 
         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);
             // 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())
             if (exec->hadException())
-                return jsNull();
+                return JSValue::encode(jsNull());
             while (true) {
                 int matchIndex;
                 int matchLen = 0;
                 int* ovector;
             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;
                 if (matchIndex < 0)
                     break;
-                
+
                 sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
 
                 int completeMatchStart = ovector[0];
                 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, jsSubstring(exec, source, matchStart, matchLen));
                 }
 
-                cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart));
+                cachedCall.setArgument(i++, jsNumber(completeMatchStart));
                 cachedCall.setArgument(i++, sourceVal);
                 cachedCall.setArgument(i++, sourceVal);
-                
+
                 cachedCall.setThis(exec->globalThisValue());
                 JSValue result = cachedCall.call();
                 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;
 
                 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++;
                 // special case of empty match
                 if (matchLen == 0) {
                     startPosition++;
-                    if (startPosition > source.size())
+                    if (startPosition > sourceLen)
                         break;
                 }
                         break;
                 }
-            }            
+            }
         } else {
             do {
                 int matchIndex;
                 int matchLen = 0;
                 int* ovector;
         } 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;
 
                 if (matchIndex < 0)
                     break;
 
-                sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
-
                 if (callType != CallTypeNone) {
                 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;
                     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));
                     }
 
                         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;
                     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;
 
                 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++;
                 // special case of empty match
                 if (matchLen == 0) {
                     startPosition++;
-                    if (startPosition > source.size())
+                    if (startPosition > sourceLen)
                         break;
                 }
             } while (global);
         }
 
         if (!lastIndex && replacements.isEmpty())
                         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);
     }
 
     // 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);
     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));
     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);
         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 };
     
     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())
     // 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);
     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)
     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)
     }
     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);
     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)
     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)
     }
     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), 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);
     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())
     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);
     }
 
         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);
     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);
 
     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
 
         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);
     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 {
         /*
         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).
          */
          *  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* 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)
     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;
     }
 
     // return array of matches
     MarkedArgumentBuffer list;
-    int lastIndex = 0;
     while (pos >= 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;
         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.
     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);
     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 { 
         /*
         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).
          */
          *  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* 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);
     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);
 
     // 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;
             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);
     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);
 
     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();
         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
             // empty string matched by regexp -> empty array
-            return result;
+            return JSValue::encode(result);
         }
         unsigned pos = 0;
         }
         unsigned pos = 0;
-        while (i != limit && pos < s.size()) {
+        while (i != limit && pos < s.length()) {
             Vector<int, 32> ovector;
             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];
             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
         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 {
                 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));
                 result->put(exec, i++, jsSubstring(exec, s, p0, pos - p0));
-                p0 = pos + u2.size();
+                p0 = pos + u2.length();
             }
         }
     }
 
     // add remaining string
     if (i != limit)
             }
         }
     }
 
     // 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()) {
     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 = 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)
 
     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)
     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;
     }
     if (start + length > len)
         length = len - start;
-    
     unsigned substringStart = static_cast<unsigned>(start);
     unsigned substringLength = static_cast<unsigned>(length);
     if (jsString)
     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;
     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 = 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 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;
         start = 0;
-    if (end < 0)
-        end = 0;
-    if (start > len)
+    else if (start > len)
         start = len;
         start = len;
-    if (end > len)
-        end = len;
     if (a1.isUndefined())
         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;
     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)
     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);
 
     JSString* sVal = thisValue.toThisJSString(exec);
     const UString& s = sVal->value(exec);
 
-    int sSize = s.size();
+    int sSize = s.length();
     if (!sSize)
     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;
     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))
         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);
 
     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)
         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)
     }
     if (length == sSize) {
         if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-            return sVal;
+            return JSValue::encode(sVal);
     } else
         buffer.resize(length);
     } 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);
 
     JSString* sVal = thisValue.toThisJSString(exec);
     const UString& s = sVal->value(exec);
 
-    int sSize = s.size();
+    int sSize = s.length();
     if (!sSize)
     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;
     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))
         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);
 
     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)
         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)
     }
     if (length == sSize) {
         if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0)
-            return sVal;
+            return JSValue::encode(sVal);
     } else
         buffer.resize(length);
     } 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);
 
     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);
     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);
     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);
     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);
     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);
     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);
     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);
     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);
     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);
     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);
     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);
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
+    JSValue a0 = exec->argument(0);
 
     uint32_t smallInteger;
     if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
 
     uint32_t smallInteger;
     if (a0.getUInt32(smallInteger) && smallInteger <= 9) {
-        unsigned stringSize = s.size();
+        unsigned stringSize = s.length();
         unsigned bufferSize = 22 + stringSize;
         UChar* buffer;
         unsigned bufferSize = 22 + stringSize;
         UChar* buffer;
-        PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer);
+        PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(bufferSize, buffer);
         if (!impl)
         if (!impl)
-            return jsUndefined();
+            return JSValue::encode(jsUndefined());
         buffer[0] = '<';
         buffer[1] = 'f';
         buffer[2] = 'o';
         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] = '>';
         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';
         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] = '>';
         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);
     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);
     UString s = thisValue.toThisString(exec);
-    JSValue a0 = args.at(0);
+    JSValue a0 = exec->argument(0);
     UString linkText = a0.toString(exec);
 
     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;
     unsigned bufferSize = 15 + linkTextSize + stringSize;
     UChar* buffer;
-    PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer);
+    PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(bufferSize, buffer);
     if (!impl)
     if (!impl)
-        return jsUndefined();
+        return JSValue::encode(jsUndefined());
     buffer[0] = '<';
     buffer[1] = 'a';
     buffer[2] = ' ';
     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] = '"';
     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] = '>';
     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] = '>';
     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 {
 }
 
 enum {
@@ -1041,38 +1111,43 @@ static inline bool isTrimWhitespace(UChar c)
 
 static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKind)
 {
 
 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) {
     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++;
     }
             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 (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 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:
 
     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 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
     };
 
 } // 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;
 
 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
 
 #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
 
 
 #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();
         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;
         }
             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;
     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;
                 ++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;
         }
 
         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
 }
 
 #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_offset(noOffset)
     , m_dictionaryKind(NoneDictionaryKind)
     , m_isPinnedPropertyTable(false)
     , m_hasGetterSetterProperties(false)
+    , m_hasNonEnumerableProperties(false)
     , m_attributesInPrevious(0)
     , m_specificFunctionThrashCount(0)
     , m_anonymousSlotCount(anonymousSlotCount)
     , 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());
     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;
     ASSERT(!m_propertyTable);
 
     Vector<Structure*, 8> structures;
@@ -357,13 +262,13 @@ void Structure::materializePropertyMap()
 
     Structure* structure = this;
 
 
     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);
 
     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;
         }
 
             break;
         }
 
@@ -371,80 +276,46 @@ void Structure::materializePropertyMap()
     }
 
     if (!m_propertyTable)
     }
 
     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];
 
     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()
 {
     }
 }
 
 void Structure::growPropertyStorageCapacity()
 {
-    if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity)
-        m_propertyStorageCapacity = JSObject::nonInlineBaseStorageCapacity;
+    if (isUsingInlineStorage())
+        m_propertyStorageCapacity = JSObject::baseExternalStorageCapacity;
     else
         m_propertyStorageCapacity *= 2;
 }
 
     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);
 
 
     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);
 
 {
     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);
         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;
 }
 
     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));
     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) {
         specificValue = 0;
 
     if (structure->transitionCount() > s_maxTransitionLength) {
-        RefPtr<Structure> transition = toCacheableDictionaryTransition(structure);
+        Structure* transition = toCacheableDictionaryTransition(globalData, structure);
         ASSERT(structure != transition);
         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();
         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_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)
 
     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)
     } else {
         if (structure->m_previous)
-            transition->materializePropertyMap();
+            transition->materializePropertyMap(globalData);
         else
         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())
     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());
 
     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());
 
 {
     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);
 
 
     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.
 
 
     // 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());
     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);
 {
     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.
 
 
     // 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->m_isPinnedPropertyTable = true;
 
     if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
-        transition->despecifyAllFunctions();
+        transition->despecifyAllFunctions(globalData);
     else {
     else {
-        bool removed = transition->despecifyFunction(replaceFunction);
+        bool removed = transition->despecifyFunction(globalData, replaceFunction);
         ASSERT_UNUSED(removed, removed);
     }
     
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
         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.
 
 
     // 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());
     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());
     
 {
     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_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_isPinnedPropertyTable = true;
-    
+    transition->m_preventExtensions = true;
+
     ASSERT(structure->anonymousSlotCount() == transition->anonymousSlotCount());
     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);
 {
     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;
         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
             // 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++)
         }
         
         // 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;
 }
 
     }
 
     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;
 
 {
     ASSERT(!m_enumerationCache);
 
     if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount)
         specificValue = 0;
 
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
 
     m_isPinnedPropertyTable = true;
 
 
     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;
 }
 
     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);
 
 {
     ASSERT(isUncacheableDictionary());
     ASSERT(!m_enumerationCache);
 
-    materializePropertyMapIfNecessary();
+    materializePropertyMapIfNecessary(globalData);
 
     m_isPinnedPropertyTable = true;
     size_t offset = remove(propertyName);
 
     m_isPinnedPropertyTable = true;
     size_t offset = remove(propertyName);
@@ -695,11 +622,6 @@ size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName
 
 #if DUMP_PROPERTYMAP_STATS
 
 
 #if DUMP_PROPERTYMAP_STATS
 
-static int numProbes;
-static int numCollisions;
-static int numRehashes;
-static int numRemoves;
-
 struct PropertyMapStatisticsExitLogger {
     ~PropertyMapStatisticsExitLogger();
 };
 struct PropertyMapStatisticsExitLogger {
     ~PropertyMapStatisticsExitLogger();
 };
@@ -717,8 +639,6 @@ PropertyMapStatisticsExitLogger::~PropertyMapStatisticsExitLogger()
 
 #endif
 
 
 #endif
 
-static const unsigned deletedSentinelIndex = 1;
-
 #if !DO_PROPERTYMAP_CONSTENCY_CHECK
 
 inline void Structure::checkConsistency()
 #if !DO_PROPERTYMAP_CONSTENCY_CHECK
 
 inline void Structure::checkConsistency()
@@ -727,532 +647,208 @@ inline void Structure::checkConsistency()
 
 #endif
 
 
 #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)
     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;
 
     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;
 
         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;
     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(!propertyName.isNull());
-    ASSERT(get(propertyName) == notFound);
+    ASSERT(get(globalData, propertyName) == notFound);
 
     checkConsistency();
 
     checkConsistency();
-
     if (attributes & DontEnum)
         m_hasNonEnumerableProperties = true;
 
     if (attributes & DontEnum)
         m_hasNonEnumerableProperties = true;
 
-    UString::Rep* rep = propertyName._ustring.rep();
+    StringImpl* rep = propertyName.impl();
 
     if (!m_propertyTable)
 
     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;
 
     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);
     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;
 }
 
 
     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();
 
 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 (!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);
 
     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;
 }
 
 
     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(!m_propertyTable);
-    ASSERT(isPowerOf2(newTableSize));
 
     checkConsistency();
 
     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();
 }
 
     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
 
     }
 }
 
 #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;
 
     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;
             continue;
-        if (entryIndex == deletedSentinelIndex) {
+        if (entryIndex == deletedEntryIndex()) {
             ++deletedIndexCount;
             continue;
         }
             ++deletedIndexCount;
             continue;
         }
-        ASSERT(entryIndex > deletedSentinelIndex);
-        ASSERT(entryIndex - 1 <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount);
+        ASSERT(entryIndex < deletedEntryIndex());
+        ASSERT(entryIndex - 1 <= usedCount());
         ++indexCount;
 
         ++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;
 
     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) {
             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());
                 break;
             if (k == 0)
                 k = 1 | doubleHash(rep->existingHash());
@@ -1261,7 +857,23 @@ void Structure::checkConsistency()
         ASSERT(entryIndex == c + 1);
     }
 
         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
 }
 
 #endif // DO_PROPERTYMAP_CONSTENCY_CHECK
index 968443a828d1b2e8e7f2e58465f5109e5afe84d9..f71d23c12bc46bd6ff13a45b833f5ec26524b3fd 100644 (file)
 #define Structure_h
 
 #include "Identifier.h"
 #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 "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 "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>
 
 #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;
 
 namespace JSC {
 
     class MarkStack;
     class PropertyNameArray;
     class PropertyNameArrayData;
+    class StructureChain;
+    typedef MarkStack SlotVisitor;
+
+    struct ClassInfo;
 
     enum EnumerationMode {
         ExcludeDontEnumProperties,
         IncludeDontEnumProperties
     };
 
 
     enum EnumerationMode {
         ExcludeDontEnumProperties,
         IncludeDontEnumProperties
     };
 
-    class Structure : public RefCounted<Structure> {
+    class Structure : public JSCell {
     public:
     public:
-        friend class JIT;
         friend class StructureTransitionTable;
         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 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.  
 
         ~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; }
 
         
         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;
         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();
 
         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;
 
         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());
         {
             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; }
         }
 
         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 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 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.
         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:
     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;
         
         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);
 
         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();
 
         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
         }
 
         signed char transitionCount() const
@@ -180,24 +205,8 @@ namespace JSC {
             return m_offset == noOffset ? 0 : m_offset + 1;
         }
 
             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;
 
         bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const;
 
-        static const unsigned emptyEntryIndex = 0;
-    
         static const signed char s_maxTransitionLength = 64;
 
         static const signed char noOffset = -1;
         static const signed char s_maxTransitionLength = 64;
 
         static const signed char noOffset = -1;
@@ -206,22 +215,20 @@ namespace JSC {
 
         TypeInfo m_typeInfo;
 
 
         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;
 
 
         uint32_t m_propertyStorageCapacity;
 
@@ -242,53 +249,70 @@ namespace JSC {
 #endif
         unsigned m_specificFunctionThrashCount : 2;
         unsigned m_anonymousSlotCount : 5;
 #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)
         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
 #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
     }
 
 } // namespace JSC
index 085876c496b54ea5d5f0a072b1f07fd88677e65d..89a0ec0c2067b4696fa31e269b597d7c6b99baff 100644 (file)
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 #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;
     
 {
     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())
 
     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
 }
 
 } // namespace JSC
index 816b66d5051550bceb2b4efa27e51419e2d9a33f..4fc1212bc7a28eda127fcc939360b4000290fbb8 100644 (file)
@@ -26,6 +26,9 @@
 #ifndef StructureChain_h
 #define StructureChain_h
 
 #ifndef StructureChain_h
 #define StructureChain_h
 
+#include "JSCell.h"
+#include "Structure.h"
+
 #include <wtf/OwnArrayPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/OwnArrayPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
@@ -35,17 +38,22 @@ namespace JSC {
 
     class Structure;
 
 
     class Structure;
 
-    class StructureChain : public RefCounted<StructureChain> {
+    class StructureChain : public JSCell {
         friend class JIT;
 
     public:
         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
     };
 
 } // namespace JSC
index d1dc2d9c645499c9981203f5f8528b38265a6552..adebad28480c24db39a5015da6cdad4add0747d3 100644 (file)
 #define StructureTransitionTable_h
 
 #include "UString.h"
 #define StructureTransitionTable_h
 
 #include "UString.h"
+#include "WeakGCMap.h"
 #include <wtf/HashFunctions.h>
 #include <wtf/HashFunctions.h>
-#include <wtf/HashMap.h>
 #include <wtf/HashTraits.h>
 #include <wtf/OwnPtr.h>
 #include <wtf/RefPtr.h>
 
 namespace JSC {
 
 #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();
         static unsigned hash(const Key& p)
         {
             return p.first->existingHash();
@@ -52,8 +55,8 @@ namespace JSC {
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
 
         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;
 
         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); }
     };
 
         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
 } // namespace JSC
 
 #endif // StructureTransitionTable_h
index f5e266960d61840d71f92cfe1e1e2089b3b026b0..2635501e11eaa4b74b3b462ad1bc00a0498d21f7 100644 (file)
@@ -119,10 +119,14 @@ namespace JSC {
         static const bool needsDestruction = false;
     };
 
         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
     };
     
 } // 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 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
 }
 
 #endif
 }
 
index 7bfa6d08305dc8b5f1d6370e2e92e8222e66ea27..5925641f80a366ad34061b562c74cd822e3cfe9b 100644 (file)
@@ -40,6 +40,7 @@ namespace JSC {
         TimeoutChecker();
 
         void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; }
         TimeoutChecker();
 
         void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; }
+        unsigned timeoutInterval() const { return m_timeoutInterval; }
         
         unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; }
         
         
         unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; }
         
index 8fb0dfdd03d3011bf885da7dbb78ba416e9bbc8e..b70d505ce60cb193d3540451a1718d0db8ce31e3 100644 (file)
 #include "UString.h"
 
 #include "JSGlobalObjectFunctions.h"
 #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 "Identifier.h"
 #include "Operations.h"
 #include <ctype.h>
 #include <limits.h>
 #include <limits>
-#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/Assertions.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/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>
 
 #if HAVE(STRINGS_H)
 #include <strings.h>
@@ -57,37 +54,43 @@ namespace JSC {
 extern const double NaN;
 extern const double Inf;
 
 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 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)
     UChar* p = end;
 
     if (i == 0)
@@ -113,17 +116,21 @@ UString UString::from(int i)
     return UString(p, static_cast<unsigned>(end - p));
 }
 
     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 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];
     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());
         snprintf(minBuf, sizeof(minBuf), "%lld", std::numeric_limits<long long>::min());
+#endif
         return UString(minBuf);
     } else {
         bool negative = false;
         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));
 }
 
     return UString(p, static_cast<unsigned>(end - p));
 }
 
-UString UString::from(unsigned u)
+UString UString::number(unsigned u)
 {
     UChar buf[sizeof(u) * 3];
 {
     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)
     UChar* p = end;
 
     if (u == 0)
@@ -160,10 +167,10 @@ UString UString::from(unsigned u)
     return UString(p, static_cast<unsigned>(end - p));
 }
 
     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 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)
     UChar* p = end;
 
     if (l == 0)
@@ -189,329 +196,24 @@ UString UString::from(long l)
     return UString(p, end - p);
 }
 
     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);
 }
 
     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 *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)
 }
 
 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();
 
     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;
     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)
 {
 
 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 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++;
     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)
 {
 
 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 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++;
     unsigned l = 0;
     while (l < lmin && *c1 == *c2) {
         c1++;
@@ -569,45 +271,96 @@ bool operator>(const UString& s1, const UString& s2)
     return (l1 > l2);
 }
 
     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)
     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();
         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
 }
 
 } // 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
 
  *
  */
 
 #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 {
 
 
 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;
             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;
             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;
             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 {
 
 
 } // 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
 } // 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
 
 #ifndef WeakGCMap_h
 #define WeakGCMap_h
 
-#include "Collector.h"
+#include "Handle.h"
+#include "JSGlobalData.h"
 #include <wtf/HashMap.h>
 
 namespace JSC {
 
 #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:
 
 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(); }
     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;
         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
 
 
 } // 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);
     }
 
         return advance() / (UINT_MAX + 1.0);
     }
 
+    unsigned getUint32()
+    {
+        return advance();
+    }
+
 private:
     unsigned 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>
 <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>
 [ <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>
 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>
 </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>
 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>
  [ <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>
 <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>
  [ <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>
 <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>
 <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>
 </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>
 <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>
 <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>
 <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>
 } 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>
 <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>
 } 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>
 <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>
 <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>
 <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>
 (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>
 <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>
 (['$*'] == 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>
 <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>
 <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>
  [ <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>
 <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>
 '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>
 <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>
 <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>
 <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>
 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>
 <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>
 <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>
 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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 <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>
 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>
 <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>
 <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>
 <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>
 <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>
 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>
 <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>
 <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>
 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>
 <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>
 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>
 <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>
 <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>
 <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>
 <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.
 # 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/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/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
 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
 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/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
 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')));
 
        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";
     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";
     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('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";
     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";
     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";
     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";
     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()
        {
 
        function test()
        {
index a1ed113c742904994b6d534cc44f8f4e873d6da8..9afdb14edf452e3cff6d27ada7fe47d304aafa11 100644 (file)
        testcases[count++] = new TestCase ( SECTION, "RegExp['$_'] = 'abcd12357efg'; /\\d+/.exec('2345')",
                                            String(["2345"]), String(/\d+/.exec('2345')));
 
        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";
     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";
     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('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";
     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";
     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";
     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";
     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()
        {
 
        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 *
 
 
 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'):
 
     includes = common_includes + full_dirs
     if sys.platform.startswith('darwin'):
@@ -85,8 +64,8 @@ def build(bld):
         uselib_local = '',
         install_path = output_dir)
 
         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),
     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,
         )
         
         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:
     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')
 
     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(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'; }
 
     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(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'); }
 
     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(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'); }
 
     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(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'); }
 
     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(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'); }
 
     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(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'; }
 
     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(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'; }
 
     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(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:
 
     /*
         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(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); }
 
     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 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 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 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 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 <= '~'; }
 
     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(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;
 }
 
 using WTF::isASCII;
@@ -161,5 +179,7 @@ using WTF::isASCIIUpper;
 using WTF::toASCIIHexValue;
 using WTF::toASCIILower;
 using WTF::toASCIIUpper;
 using WTF::toASCIIHexValue;
 using WTF::toASCIILower;
 using WTF::toASCIIUpper;
+using WTF::lowerNibbleToASCIIHexDigit;
+using WTF::upperNibbleToASCIIHexDigit;
 
 #endif
 
 #endif
index d7470e7f956588eacbb6362efc591f4de74baeb6..ec8a63951d34663615b73d988a1c0efbf358adda 100644 (file)
@@ -33,6 +33,7 @@
 #define AVL_TREE_H_
 
 #include "Assertions.h"
 #define AVL_TREE_H_
 
 #include "Assertions.h"
+#include <wtf/FixedArray.h>
 
 namespace WTF {
 
 
 namespace WTF {
 
@@ -70,7 +71,7 @@ public:
     void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; }
 
 private:
     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:
 };
 
 // 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
 #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)
 #define UNLIKELY(x) __builtin_expect((x), 0)
 #else
 #define UNLIKELY(x) (x)
@@ -49,7 +49,7 @@
 #endif
 
 #ifndef LIKELY
 #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)
 #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.
  */
 
  * 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 "config.h"
 #include "Assertions.h"
 
 
 #include <CoreFoundation/CFString.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
 #ifndef WINVER
 #define WINVER 0x0500
 #endif
 #ifndef _WIN32_WINNT
 #define _WIN32_WINNT 0x0500
 #endif
-#include <windows.h>
 #include <crtdbg.h>
 #endif
 
 #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" {
 
 #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)
 {
 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);
         free(buffer);
         CFRelease(str);
         CFRelease(cfFormat);
-    } else
+        return;
+    }
 #if OS(SYMBIAN)
     vfprintf(stdout, format, args);
 #else
 #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)
 {
 
 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
     _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
 }
 
 #endif
 }
 
@@ -119,6 +166,34 @@ void WTFReportArgumentAssertionFailure(const char* file, int line, const char* f
     printCallSite(file, line, function);
 }
 
     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: ");
 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);
     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");
 }
 
         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);
     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");
         printf_stderr_common("\n");
+
     printCallSite(file, line, function);
 }
 
     printCallSite(file, line, function);
 }
 
index 168e8ba0e7c3e7efcea0bae150874cb6bf4ebdb2..f6187bbe359b0cdd531d7434d6e8fc8256caa537 100644 (file)
@@ -46,9 +46,9 @@
 
 #include <stdbool.h>
 
 
 #include <stdbool.h>
 
-#if COMPILER(MSVC)
 #include <stddef.h>
 #include <stddef.h>
-#else
+
+#if !COMPILER(MSVC)
 #include <inttypes.h>
 #endif
 
 #include <inttypes.h>
 #endif
 
 #include <e32debug.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
 #ifdef NDEBUG
 /* Disable ASSERT* macros in release mode. */
 #define ASSERTIONS_DISABLED_DEFAULT 1
 #define HAVE_VARIADIC_MACRO 1
 #endif
 
 #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
 #ifndef ASSERT_DISABLED
 #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT
 #endif
 #else
 #define CLANG_ANALYZER_NORETURN
 #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. */
 
 
 /* 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;
 
     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
 }
 
 #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)
     __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 { \
 #else
 #define CRASH() do { \
+    WTFReportBacktrace(); \
     *(int *)(uintptr_t)0xbbadbeef = 0; \
     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
 } while(false)
 #endif
 #endif
 
     *(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.
 /* 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)
 
 #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)
 #define ASSERT_UNUSED(variable, assertion) ((void)variable)
+#endif
 
 #else
 
 
 #else
 
@@ -247,6 +292,29 @@ while (0)
     } \
 while (0)
 #endif
     } \
 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 */
                         
                         
 /* 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
 
 #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 */
 #endif /* WTF_Assertions_h */
index 1d190a323516c5211b6d51b11d370b1dbef0a8be..1ebd4876fff179744f84fa24d9b443b77e548216 100644 (file)
@@ -78,7 +78,7 @@
 namespace WTF {
 
 #if OS(WINDOWS)
 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)); }
 
 #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)
 #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)); }
 
 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
 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; }
 
 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
 
 
 } // namespace WTF
 
-#if USE(LOCKFREE_THREADSAFESHARED)
+#if USE(LOCKFREE_THREADSAFEREFCOUNTED)
 using WTF::atomicDecrement;
 using WTF::atomicIncrement;
 #endif
 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 "config.h"
 #include "ByteArray.h"
+#include "StdLibExtras.h"
 
 namespace WTF {
 
 PassRefPtr<ByteArray> ByteArray::create(size_t size)
 {
 
 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));
 }
     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
 
 #ifndef ByteArray_h
 #define ByteArray_h
 
+#include <limits.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/PassRefPtr.h>
+#include <wtf/Platform.h>
 #include <wtf/RefCounted.h>
 
 namespace WTF {
 #include <wtf/RefCounted.h>
 
 namespace WTF {
@@ -86,8 +88,17 @@ namespace WTF {
         {
         }
         size_t m_size;
         {
         }
         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
 
 #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.
  */
 
  * 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>
 
 
 #include <complex>
 #include <wtf/MathExtras.h>
 
-namespace WebCore {
+namespace WTF {
 
 typedef std::complex<double> Complex;
 
 
 typedef std::complex<double> Complex;
 
@@ -41,6 +41,9 @@ inline Complex complexFromMagnitudePhase(double magnitude, double phase)
     return Complex(magnitude * cos(phase), magnitude * sin(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) 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
  *
  * 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
 
 #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 {
 
 
 #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.
     // (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>
     // 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)
         {
     public:
         static PassRefPtr<CrossThreadRefCounted<T> > create(T* data)
         {
@@ -73,13 +74,16 @@ namespace WTF {
         }
 
     private:
         }
 
     private:
-        CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter)
+        CrossThreadRefCounted(T* data, ThreadSafeRefCountedBase* threadedCounter)
             : m_threadSafeRefCounter(threadedCounter)
             , m_data(data)
 #ifndef NDEBUG
             , m_threadId(0)
 #endif
         {
             : 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()
         }
 
         ~CrossThreadRefCounted()
@@ -97,7 +101,7 @@ namespace WTF {
 #endif
 
         RefCountedBase m_refCounter;
 #endif
 
         RefCountedBase m_refCounter;
-        ThreadSafeSharedBase* m_threadSafeRefCounter;
+        ThreadSafeRefCountedBase* m_threadSafeRefCounter;
         T* m_data;
 #ifndef NDEBUG
         ThreadIdentifier m_threadId;
         T* m_data;
 #ifndef NDEBUG
         ThreadIdentifier m_threadId;
@@ -157,7 +161,7 @@ namespace WTF {
         if (m_threadSafeRefCounter)
             m_threadSafeRefCounter->ref();
         else
         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));
     }
 
         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)
 
 
 #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
 // 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.
     // 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;
     static double syncLowResUTCTime;
     static double syncHighResUpTime;
     static double lastUTCTime;
index dcb1f6c69d9b3f15ece01f15c5d1bf9c625c7fc0..5fcb63a81fdf203e9dbb9825699deec8617e0c3b 100644 (file)
 
 namespace WTF {
 
 
 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;
 
 } // namespace WTF
 
 using WTF::currentTime;
+using WTF::currentTimeMS;
 using WTF::getLocalTime;
 
 #endif // CurrentTime_h
 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) 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.
  *
  * The Original Code is Mozilla Communicator client code, released
  * March 31, 1998.
 #include "Assertions.h"
 #include "ASCIICType.h"
 #include "CurrentTime.h"
 #include "Assertions.h"
 #include "ASCIICType.h"
 #include "CurrentTime.h"
+#if USE(JSC)
+#include "JSObject.h"
+#endif
 #include "MathExtras.h"
 #include "MathExtras.h"
+#if USE(JSC)
+#include "ScopeChain.h"
+#endif
+#include "StdLibExtras.h"
 #include "StringExtras.h"
 
 #include <algorithm>
 #include "StringExtras.h"
 
 #include <algorithm>
@@ -377,7 +385,7 @@ int equivalentYearForDST(int year)
     return year;
 }
 
     return year;
 }
 
-static int32_t calculateUTCOffset()
+int32_t calculateUTCOffset()
 {
 #if PLATFORM(BREWMP)
     time_t localTime = static_cast<time_t>(currentTime());
 {
 #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
 }
 
 // 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
 {
     // 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.
 }
 
     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)
 {
     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;
 }
 
     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)
 {
 // 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).
 
     // 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 {
             }
             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);
                 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.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)
 }
 
 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) 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
  *
  *
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
 #define DateMath_h
 
 #include <math.h>
 #define DateMath_h
 
 #include <math.h>
+#include <stdint.h>
 #include <string.h>
 #include <time.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/Noncopyable.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);
 
 #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);
 
 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);
 
 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
 
 } // 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::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::msPerSecond;
 using WTF::msToYear;
 using WTF::secondsPerMinute;
+using WTF::parseDateFromNullTerminatedCharacters;
+using WTF::calculateUTCOffset;
+using WTF::calculateDSTOffset;
 
 #if USE(JSC)
 namespace JSC {
 
 #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.
 
 // 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)
     GregorianDateTime()
         : second(0)
         , minute(0)
@@ -119,13 +135,7 @@ struct GregorianDateTime : Noncopyable {
         , year(0)
         , isDST(0)
         , utcOffset(0)
         , year(0)
         , isDST(0)
         , utcOffset(0)
-        , timeZone(0)
-    {
-    }
-
-    ~GregorianDateTime()
     {
     {
-        delete [] timeZone;
     }
 
     GregorianDateTime(ExecState* exec, const tm& inTm)
     }
 
     GregorianDateTime(ExecState* exec, const tm& inTm)
@@ -148,10 +158,10 @@ struct GregorianDateTime : Noncopyable {
 
 #if HAVE(TM_ZONE)
         int inZoneSize = strlen(inTm.tm_zone) + 1;
 
 #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
 #else
-        timeZone = 0;
+        timeZone = nullptr;
 #endif
     }
 
 #endif
     }
 
@@ -174,7 +184,7 @@ struct GregorianDateTime : Noncopyable {
         ret.tm_gmtoff = static_cast<long>(utcOffset);
 #endif
 #if HAVE(TM_ZONE)
         ret.tm_gmtoff = static_cast<long>(utcOffset);
 #endif
 #if HAVE(TM_ZONE)
-        ret.tm_zone = timeZone;
+        ret.tm_zone = timeZone.get();
 #endif
 
         return ret;
 #endif
 
         return ret;
@@ -193,11 +203,11 @@ struct GregorianDateTime : Noncopyable {
         isDST = rhs.isDST;
         utcOffset = rhs.utcOffset;
         if (rhs.timeZone) {
         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
         } else
-            timeZone = 0;
+            timeZone = nullptr;
     }
 
     int second;
     }
 
     int second;
@@ -210,7 +220,7 @@ struct GregorianDateTime : Noncopyable {
     int year;
     int isDST;
     int utcOffset;
     int year;
     int isDST;
     int utcOffset;
-    char* timeZone;
+    OwnArrayPtr<char> timeZone;
 };
 
 static inline int gmtoffset(const GregorianDateTime& t)
 };
 
 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.
 
 // 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 {
 
 #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:
     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();
-        Deque(const Deque<T>&);
-        Deque& operator=(const Deque<T>&);
+        Deque(const Deque<T, inlineCapacity>&);
+        Deque& operator=(const Deque<T, inlineCapacity>&);
         ~Deque();
 
         ~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; }
 
         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]; }
 
         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&);
 
         template<typename U> void append(const U&);
         template<typename U> void prepend(const U&);
@@ -85,11 +90,11 @@ namespace WTF {
         iterator findIf(Predicate&);
 
     private:
         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 VectorTypeOperations<T> TypeOperations;
-        typedef DequeIteratorBase<T> IteratorBase;
+        typedef DequeIteratorBase<T, inlineCapacity> IteratorBase;
 
         void remove(size_t position);
         void invalidateIterators();
 
         void remove(size_t position);
         void invalidateIterators();
@@ -107,14 +112,14 @@ namespace WTF {
 #endif
     };
 
 #endif
     };
 
-    template<typename T>
+    template<typename T, size_t inlineCapacity = 0>
     class DequeIteratorBase {
     private:
     class DequeIteratorBase {
     private:
-        typedef DequeIteratorBase<T> Base;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
 
     protected:
         DequeIteratorBase();
 
     protected:
         DequeIteratorBase();
-        DequeIteratorBase(const Deque<T>*, size_t);
+        DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t);
         DequeIteratorBase(const Base&);
         Base& operator=(const Base&);
         ~DequeIteratorBase();
         DequeIteratorBase(const Base&);
         Base& operator=(const Base&);
         ~DequeIteratorBase();
@@ -135,10 +140,10 @@ namespace WTF {
         void checkValidity() const;
         void checkValidity(const Base&) const;
 
         void checkValidity() const;
         void checkValidity(const Base&) const;
 
-        Deque<T>* m_deque;
+        Deque<T, inlineCapacity>* m_deque;
         size_t m_index;
 
         size_t m_index;
 
-        friend class Deque<T>;
+        friend class Deque<T, inlineCapacity>;
 
 #ifndef NDEBUG
         mutable DequeIteratorBase* m_next;
 
 #ifndef NDEBUG
         mutable DequeIteratorBase* m_next;
@@ -146,14 +151,14 @@ namespace WTF {
 #endif
     };
 
 #endif
     };
 
-    template<typename T>
-    class DequeIterator : public DequeIteratorBase<T> {
+    template<typename T, size_t inlineCapacity = 0>
+    class DequeIterator : public DequeIteratorBase<T, inlineCapacity> {
     private:
     private:
-        typedef DequeIteratorBase<T> Base;
-        typedef DequeIterator<T> Iterator;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
+        typedef DequeIterator<T, inlineCapacity> Iterator;
 
     public:
 
     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; }
 
         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
     };
 
         // 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:
     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:
 
     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) { }
 
         DequeConstIterator(const Iterator& other) : Base(other) { }
         DequeConstIterator(const NonConstIterator& other) : Base(other) { }
@@ -197,14 +202,14 @@ namespace WTF {
         // postfix -- intentionally omitted
     };
 
         // 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:
     private:
-        typedef DequeIteratorBase<T> Base;
-        typedef DequeReverseIterator<T> Iterator;
+        typedef DequeIteratorBase<T, inlineCapacity> Base;
+        typedef DequeReverseIterator<T, inlineCapacity> Iterator;
 
     public:
 
     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; }
 
         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
     };
 
         // 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:
     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:
 
     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) { }
 
         DequeConstReverseIterator(const Iterator& other) : Base(other) { }
         DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { }
@@ -249,13 +254,17 @@ namespace WTF {
     };
 
 #ifdef NDEBUG
     };
 
 #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
 #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);
         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) {
     {
         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) {
     {
         IteratorBase* next;
         for (IteratorBase* p = m_iterators; p; p = next) {
@@ -291,8 +300,8 @@ namespace WTF {
     }
 #endif
 
     }
 #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
         : m_start(0)
         , m_end(0)
 #ifndef NDEBUG
@@ -302,8 +311,8 @@ namespace WTF {
         checkValidity();
     }
 
         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())
         : 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;
     }
 
         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;
     }
 
         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);
     {
         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();
     }
 
     {
         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();
     {
         checkValidity();
         other.checkValidity();
@@ -369,8 +380,8 @@ namespace WTF {
         other.checkValidity();
     }
 
         other.checkValidity();
     }
 
-    template<typename T>
-    inline void Deque<T>::clear()
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::clear()
     {
         checkValidity();
         invalidateIterators();
     {
         checkValidity();
         invalidateIterators();
@@ -380,9 +391,9 @@ namespace WTF {
         checkValidity();
     }
 
         checkValidity();
     }
 
-    template<typename T>
+    template<typename T, size_t inlineCapacity>
     template<typename Predicate>
     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) {
     {
         iterator end_iterator = end();
         for (iterator it = begin(); it != end_iterator; ++it) {
@@ -392,8 +403,8 @@ namespace WTF {
         return end_iterator;
     }
 
         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)
     {
         if (m_start) {
             if (m_end + 1 != m_start)
@@ -407,8 +418,8 @@ namespace WTF {
         expandCapacity();
     }
 
         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();
     {
         checkValidity();
         size_t oldCapacity = m_buffer.capacity();
@@ -427,8 +438,16 @@ namespace WTF {
         checkValidity();
     }
 
         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();
     {
         checkValidity();
         expandCapacityIfNeeded();
@@ -440,8 +459,8 @@ namespace WTF {
         checkValidity();
     }
 
         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();
     {
         checkValidity();
         expandCapacityIfNeeded();
@@ -453,8 +472,8 @@ namespace WTF {
         checkValidity();
     }
 
         checkValidity();
     }
 
-    template<typename T>
-    inline void Deque<T>::removeFirst()
+    template<typename T, size_t inlineCapacity>
+    inline void Deque<T, inlineCapacity>::removeFirst()
     {
         checkValidity();
         invalidateIterators();
     {
         checkValidity();
         invalidateIterators();
@@ -467,22 +486,22 @@ namespace WTF {
         checkValidity();
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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;
     {
         if (position == m_end)
             return;
@@ -505,28 +524,28 @@ namespace WTF {
     }
 
 #ifdef NDEBUG
     }
 
 #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
 #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);
     }
 
     {
         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);
     }
 
     {
         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;
     {
         if (!m_deque)
             m_next = 0;
@@ -539,8 +558,8 @@ namespace WTF {
         m_previous = 0;
     }
 
         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);
     {
         if (!m_deque) {
             ASSERT(!m_next);
@@ -564,23 +583,23 @@ namespace WTF {
     }
 #endif
 
     }
 #endif
 
-    template<typename T>
-    inline DequeIteratorBase<T>::DequeIteratorBase()
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase()
         : m_deque(0)
     {
     }
 
         : 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();
     }
 
         , 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)
     {
         : m_deque(other.m_deque)
         , m_index(other.m_index)
     {
@@ -588,8 +607,8 @@ namespace WTF {
         checkValidity();
     }
 
         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();
     {
         checkValidity();
         other.checkValidity();
@@ -602,8 +621,8 @@ namespace WTF {
         return *this;
     }
 
         return *this;
     }
 
-    template<typename T>
-    inline DequeIteratorBase<T>::~DequeIteratorBase()
+    template<typename T, size_t inlineCapacity>
+    inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase()
     {
 #ifndef NDEBUG
         removeFromIteratorsList();
     {
 #ifndef NDEBUG
         removeFromIteratorsList();
@@ -611,15 +630,15 @@ namespace WTF {
 #endif
     }
 
 #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;
     }
 
     {
         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);
     {
         checkValidity();
         ASSERT(m_index != m_deque->m_end);
@@ -631,8 +650,8 @@ namespace WTF {
         checkValidity();
     }
 
         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);
     {
         checkValidity();
         ASSERT(m_index != m_deque->m_start);
@@ -644,16 +663,16 @@ namespace WTF {
         checkValidity();
     }
 
         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];
     }
 
     {
         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);
     {
         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:
 // Provides customizable overrides of fastMalloc/fastFree and operator new/delete
 //
 // Provided functionality:
+//    Macro: WTF_MAKE_FAST_ALLOCATED
 //    namespace WTF {
 //    namespace WTF {
-//        class FastAllocBase;
 //
 //        T*    fastNew<T>();
 //        T*    fastNew<T>(arg);
 //
 //        T*    fastNew<T>();
 //        T*    fastNew<T>(arg);
 // FastDelete assumes that the underlying
 //
 // Example usage:
 // 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);
 //
 //    char* charPtr = fastNew<char>();
 //    fastDelete(charPtr);
 #include "FastMalloc.h"
 #include "TypeTraits.h"
 
 #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
 
 
     // fastNew / fastDelete
 
@@ -407,7 +416,6 @@ namespace WTF {
 
 } // namespace WTF
 
 
 } // namespace WTF
 
-using WTF::FastAllocBase;
 using WTF::fastDeleteSkippingDestructor;
 
 #endif // FastAllocBase_h
 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, 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
 // 
 // 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>
 
 #include "Assertions.h"
 #include <limits>
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
 #include <pthread.h>
 #endif
 #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
 
 #ifndef NO_TCMALLOC_SAMPLES
 #ifdef WTF_CHANGES
 #endif
 
 // Use a background thread to periodically scavenge memory to release back to the system
 #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 {
 
 #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()
 static pthread_key_t isForbiddenKey;
 static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT;
 static void initializeIsForbiddenKey()
@@ -150,7 +147,7 @@ void fastMallocAllow()
 {
     staticIsForbidden = false;
 }
 {
     staticIsForbidden = false;
 }
-#endif // ENABLE(JSC_MULTIPLE_THREADS)
+#endif // ENABLE(WTF_MULTIPLE_THREADS)
 
 } // namespace WTF
 #endif // NDEBUG
 
 } // namespace WTF
 #endif // NDEBUG
@@ -159,10 +156,13 @@ void fastMallocAllow()
 
 namespace WTF {
 
 
 namespace WTF {
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
 
 namespace Internal {
 
 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();
 void fastMallocMatchFailed(void*)
 {
     CRASH();
@@ -170,7 +170,6 @@ void fastMallocMatchFailed(void*)
 
 } // namespace Internal
 
 
 } // namespace Internal
 
-#endif
 
 void* fastZeroedMalloc(size_t n) 
 {
 
 void* fastZeroedMalloc(size_t n) 
 {
@@ -181,15 +180,12 @@ void* fastZeroedMalloc(size_t n)
 
 char* fastStrDup(const char* src)
 {
 
 char* fastStrDup(const char* src)
 {
-    int len = strlen(src) + 1;
+    size_t len = strlen(src) + 1;
     char* dup = static_cast<char*>(fastMalloc(len));
     char* dup = static_cast<char*>(fastMalloc(len));
-
-    if (dup)
-        memcpy(dup, src, len);
-
+    memcpy(dup, src, len);
     return dup;
 }
     return dup;
 }
-    
+
 TryMallocReturnValue tryFastZeroedMalloc(size_t n) 
 {
     void* result;
 TryMallocReturnValue tryFastZeroedMalloc(size_t n) 
 {
     void* result;
@@ -209,7 +205,7 @@ TryMallocReturnValue tryFastZeroedMalloc(size_t n)
 
 #if OS(DARWIN)
 #include <malloc/malloc.h>
 
 #if OS(DARWIN)
 #include <malloc/malloc.h>
-#elif COMPILER(MSVC)
+#elif OS(WINDOWS)
 #include <malloc.h>
 #endif
 
 #include <malloc.h>
 #endif
 
@@ -219,17 +215,20 @@ TryMallocReturnValue tryFastMalloc(size_t n)
 {
     ASSERT(!isForbidden());
 
 {
     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;
 
         return 0;
 
-    void* result = malloc(n + sizeof(AllocAlignmentInteger));
+    void* result = malloc(n + Internal::ValidationBufferSize);
     if (!result)
         return 0;
     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);
     return result;
 #else
     return malloc(n);
@@ -240,10 +239,11 @@ void* fastMalloc(size_t n)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     TryMallocReturnValue returnValue = tryFastMalloc(n);
     void* result;
     TryMallocReturnValue returnValue = tryFastMalloc(n);
     void* result;
-    returnValue.getValue(result);
+    if (!returnValue.getValue(result))
+        CRASH();
 #else
     void* result = malloc(n);
 #endif
 #else
     void* result = malloc(n);
 #endif
@@ -265,19 +265,17 @@ TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     size_t totalBytes = n_elements * element_size;
     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;
 
         return 0;
 
-    totalBytes += sizeof(AllocAlignmentInteger);
-    void* result = malloc(totalBytes);
-    if (!result)
+    TryMallocReturnValue returnValue = tryFastMalloc(totalBytes);
+    void* result;
+    if (!returnValue.getValue(result))
         return 0;
         return 0;
-
     memset(result, 0, totalBytes);
     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);
     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());
 
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     TryMallocReturnValue returnValue = tryFastCalloc(n_elements, element_size);
     void* result;
     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
 #else
     void* result = calloc(n_elements, element_size);
 #endif
@@ -313,13 +312,13 @@ void fastFree(void* p)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     if (!p)
         return;
     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);
     free(header);
 #else
     free(p);
@@ -330,20 +329,18 @@ TryMallocReturnValue tryFastRealloc(void* p, size_t n)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     if (p) {
     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;
             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;
         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);
         return result;
     } else {
         return fastMalloc(n);
@@ -357,10 +354,11 @@ void* fastRealloc(void* p, size_t n)
 {
     ASSERT(!isForbidden());
 
 {
     ASSERT(!isForbidden());
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     TryMallocReturnValue returnValue = tryFastRealloc(p, n);
     void* result;
     TryMallocReturnValue returnValue = tryFastRealloc(p, n);
     void* result;
-    returnValue.getValue(result);
+    if (!returnValue.getValue(result))
+        CRASH();
 #else
     void* result = realloc(p, n);
 #endif
 #else
     void* result = realloc(p, n);
 #endif
@@ -380,9 +378,12 @@ FastMallocStatistics fastMallocStatistics()
 
 size_t fastMallocSize(const void* p)
 {
 
 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);
     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;
     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 "TCSpinLock.h"
 #include "TCSystemAlloc.h"
 #include <algorithm>
-#include <errno.h>
 #include <limits>
 #include <pthread.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.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 OS(UNIX)
 #include <unistd.h>
 #endif
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
 #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
 #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(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"
 
 #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.
 // 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 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)
 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
 
 #endif
 #endif
 
@@ -1019,7 +1034,7 @@ class PageHeapAllocator {
         if (!new_allocation)
           CRASH();
 
         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;
         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)
   {
   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
 };
   }
 #endif
 };
@@ -1286,6 +1298,8 @@ static const size_t kMinimumFreeCommittedPageCount = kMinSpanListsWithSpans * ((
 
 #endif
 
 
 #endif
 
+static SpinLock pageheap_lock = SPINLOCK_INITIALIZER;
+
 class TCMalloc_PageHeap {
  public:
   void init();
 class TCMalloc_PageHeap {
  public:
   void init();
@@ -1343,7 +1357,7 @@ class TCMalloc_PageHeap {
   }
 
   bool Check();
   }
 
   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();
 
   // 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;
 
   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();
 
   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;
 
   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
 #endif
 
 #endif  // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
@@ -1489,50 +1512,122 @@ void TCMalloc_PageHeap::init()
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 
 
 #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY
 
-#if !HAVE(DISPATCH_H)
+#if HAVE(DISPATCH_H)
 
 void TCMalloc_PageHeap::initializeScavenger()
 {
 
 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()
 {
 
 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()
 {
 }
 
 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
 }
 
 #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);
 
     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) {
     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.
         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);
             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);
             }
         }
                 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_;
     }
 
     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);
 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++) {
   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
   }
   return true;
 }
 
 #if ASSERT_DISABLED
-bool TCMalloc_PageHeap::CheckList(Span*, Length, Length) {
+bool TCMalloc_PageHeap::CheckList(Span*, Length, Length, bool) {
   return true;
 }
 #else
   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);
   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;
 }
   }
   return true;
 }
@@ -2047,6 +2150,7 @@ static void ReleaseFreeList(Span* list, Span* returned) {
   while (!DLL_IsEmpty(list)) {
     Span* s = list->prev;
     DLL_Remove(s);
   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));
     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)
   {
   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
           finder.visit(nextObject);
   }
 #endif
@@ -2133,7 +2237,7 @@ class TCMalloc_ThreadCache_FreeList {
 class TCMalloc_ThreadCache {
  private:
   typedef TCMalloc_ThreadCache_FreeList FreeList;
 class TCMalloc_ThreadCache {
  private:
   typedef TCMalloc_ThreadCache_FreeList FreeList;
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
   typedef DWORD ThreadIdentifier;
 #else
   typedef pthread_t ThreadIdentifier;
   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)) {
     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);
     }
   }
         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 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)];
 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
 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 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()
 {
 
 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
 
 
 #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)
 // 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
 #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)
 {
 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);
     pthread_setspecific(heap_key, heap);
-#if COMPILER(MSVC)
+
+#if OS(WINDOWS)
     TlsSetValue(tlsIndex, heap);
 #endif
 }
     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 (span) pageheap->RegisterSizeClass(span, size_class_);
   }
   if (span == NULL) {
+#if HAVE(ERRNO_H)
     MESSAGE("allocation failed: %d\n", errno);
     MESSAGE("allocation failed: %d\n", errno);
+#elif OS(WINDOWS)
+    MESSAGE("allocation failed: %d\n", ::GetLastError());
+#else
+    MESSAGE("allocation failed\n");
+#endif
     lock_.Lock();
     return;
   }
     lock_.Lock();
     return;
   }
@@ -2721,7 +2835,7 @@ ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() {
   char* nptr;
   while ((nptr = ptr + size) <= limit) {
     *tail = ptr;
   char* nptr;
   while ((nptr = ptr + size) <= limit) {
     *tail = ptr;
-    tail = reinterpret_cast<void**>(ptr);
+    tail = reinterpret_cast_ptr<void**>(ptr);
     ptr = nptr;
     num++;
   }
     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;
     // __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));
     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
 #else
   pthread_key_create(&heap_key, DestroyThreadCache);
 #endif
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
   tlsIndex = TlsAlloc();
 #endif
   tsd_inited = true;
     
   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));
   // 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_) {
   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();
     }
     if (h->tid_ == 0) {
       h->tid_ = GetCurrentThreadId();
     }
@@ -3017,7 +3131,7 @@ TCMalloc_ThreadCache* TCMalloc_ThreadCache::CreateCacheIfNecessary() {
   {
     SpinLockHolder h(&pageheap_lock);
 
   {
     SpinLockHolder h(&pageheap_lock);
 
-#if COMPILER(MSVC)
+#if OS(WINDOWS)
     DWORD me;
     if (!tsd_inited) {
       me = 0;
     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_) {
     // 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)) {
       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;
   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;
 #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) {
 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;
         return 0;
-    size += sizeof(AllocAlignmentInteger);
-    void* result = do_malloc(size);
+    void* result = do_malloc(size + Internal::ValidationBufferSize);
     if (!result)
         return 0;
 
     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
 #else
     void* result = do_malloc(size);
 #endif
@@ -3740,13 +3858,13 @@ void free(void* ptr) {
   MallocHook::InvokeDeleteHook(ptr);
 #endif
 
   MallocHook::InvokeDeleteHook(ptr);
 #endif
 
-#if ENABLE(FAST_MALLOC_MATCH_VALIDATION)
+#if ENABLE(WTF_MALLOC_VALIDATION)
     if (!ptr)
         return;
 
     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);
     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)
 {
 
 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)
 {
 }
 
 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>
 }
 
 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 (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);
     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) {
 #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)
 {
 
 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)
 {
 }
 
 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>
 }
 
 template <bool crashOnFailure>
@@ -3838,8 +3973,8 @@ ALWAYS_INLINE
 #endif
 void* realloc(void* old_ptr, size_t new_size) {
   if (old_ptr == NULL) {
 #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
 #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;
   }
 
     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;
         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;
     old_ptr = header;
+    header->m_size = new_size;
+    new_size += Internal::ValidationBufferSize;
 #endif
 
   // Get the size of the old entry
 #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);
     // 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 {
 #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;
   }
 #endif
     return old_ptr;
   }
@@ -4169,6 +4306,9 @@ FastMallocStatistics fastMallocStatistics()
 
 size_t fastMallocSize(const void* ptr)
 {
 
 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);
 
     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;
         return ByteSizeForClass(cl);
 
     return span->length << kPageShift;
+#endif
 }
 
 #if OS(DARWIN)
 }
 
 #if OS(DARWIN)
@@ -4229,12 +4370,15 @@ public:
             return 1;
 
         Span* span = m_reader(reinterpret_cast<Span*>(ptr));
             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
         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;
                 m_freeObjectFinder.visit(nextObject);
         }
         return span->length;
@@ -4318,7 +4462,7 @@ public:
             return 1;
 
         Span* span = m_reader(reinterpret_cast<Span*>(ptr));
             return 1;
 
         Span* span = m_reader(reinterpret_cast<Span*>(ptr));
-        if (!span->start)
+        if (!span || !span->start)
             return 1;
 
         if (m_seenPointers.contains(ptr))
             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
 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.
     , 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[].
         };
             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.
 
     // 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 {
     // 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)
         {
         }
 
         // 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.
     } // 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.
     }
 
     // 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;
     {
         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::fastMallocMatchFailed(p);
+
         Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc);  // Set it to this so that fastFree thinks it's OK.
     }
 
         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)
 #else
 
     inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType)
@@ -207,7 +247,7 @@ using WTF::fastMallocAllow;
 #define WTF_PRIVATE_INLINE inline
 #endif
 
 #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.
 
 // 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
  *
  *  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 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;
     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::ListRefPtr;
 using WTF::OwnArrayPtr;
 using WTF::OwnPtr;
+using WTF::PassOwnArrayPtr;
 using WTF::PassOwnPtr;
 using WTF::PassRefPtr;
 using WTF::RefPtr;
 using WTF::Vector;
 
 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
 #endif // WTF_Forward_h
index 4ed75c517906fcc2efc97ed2fdd16fb227a999cb..b97d8c8fd0f97a21bbeabeb5114beb752b74979f 100644 (file)
 #define WTF_HashCountedSet_h
 
 #include "Assertions.h"
 #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,
 #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:
     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;
 
         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(); }
         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;
 
         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(); }
         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> >
 
     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;
     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,
     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;
     private:
         typedef HashArg HashFunctions;
         typedef TraitsArg ValueTraits;
@@ -48,7 +49,7 @@ namespace WTF {
             HashFunctions, ValueTraits, ValueTraits> HashTableType;
 
     public:
             HashFunctions, ValueTraits, ValueTraits> HashTableType;
 
     public:
-        typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator;
+        typedef HashTableConstIteratorAdapter<HashTableType, ValueType> iterator;
         typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
 
         void swap(HashSet&);
         typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator;
 
         void swap(HashSet&);
@@ -57,13 +58,10 @@ namespace WTF {
         int capacity() const;
         bool isEmpty() const;
 
         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
         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&);
         // 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, 
         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>
     }
 
     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>
     {
         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>
     {
         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); 
     }
     {
         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
     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;
     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>
     }
 
     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>
     {
         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;
     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()
         {
     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
         }
 
         // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0
@@ -259,19 +259,21 @@ namespace WTF {
 
     using std::swap;
 
 
     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);
     }
     {
         swap(a.first, b.first);
         swap(a.second, b.second);
     }
-#endif
 
     template<typename T, bool useSwap> struct Mover;
 
     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 {
     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 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(); }
         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));
     }
 
         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)
     {
     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 {
     // 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(); }
         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 {
     };
 
     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(); }
         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); }
     };
 
         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 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>
     // 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) 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
  *
  * 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 "Assertions.h"
 #include "HashSet.h"
 #include "OwnPtr.h"
+#include "PassOwnPtr.h"
+#include "StdLibExtras.h"
 
 namespace WTF {
 
 
 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> 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;
     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;
 
         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;
 
         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&);
         // 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:
         }
 
     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)
         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)
     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)
     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)
     {
         const_iterator end = other.end();
         for (const_iterator it = other.begin(); it != end; ++it)
@@ -439,6 +457,42 @@ namespace WTF {
         return makeConstIterator(0); 
     }
 
         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)
     {
     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);
     }
 
         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
     {
     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 {
 
 
 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(); }
 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 "StringExtras.h"
 #include "text/CString.h"
 #endif
+#include <wtf/StdLibExtras.h>
 
 namespace WTF {
 
 
 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());
 {
     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;
     }
     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()
 }
 
 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");
     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);
 }
         buf += 4;
     } while (--longs);
 }
@@ -201,6 +203,7 @@ static void MD5Transform(uint32_t buf[4], const uint32_t in[16])
 
 MD5::MD5()
 {
 
 MD5::MD5()
 {
+    // FIXME: Move unit tests somewhere outside the constructor. See bug 55853.
     testMD5();
     m_buf[0] = 0x67452301;
     m_buf[1] = 0xefcdab89;
     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);
         }
         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;
     }
         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);
     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;
     }
         buf += 64;
         length -= 64;
     }
@@ -256,7 +259,7 @@ void MD5::addBytes(const uint8_t* input, size_t length)
     memcpy(m_in, buf, 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;
 {
     // 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);
         // 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);
 
         // 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.
 
     // 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);
     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));
     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
 }
 
 } // 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.
     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];
 
 private:
     uint32_t m_buf[4];
index 1a0682bb6b60c267b40319c3aa6e40cbdb86579d..3229e5b06f315b0c2ec5b4cc860984bca930560a 100644 (file)
@@ -34,6 +34,8 @@
 #include "StdLibExtras.h"
 #include "Threading.h"
 
 #include "StdLibExtras.h"
 #include "Threading.h"
 
+#include <wtf/iphone/WebCoreThread.h>
+
 #if PLATFORM(CHROMIUM)
 #error Chromium uses a different main thread implementation
 #endif
 #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;
             MutexLocker locker(mainThreadFunctionQueueMutex());
             if (!functionQueue().size())
                 break;
-            invocation = functionQueue().first();
-            functionQueue().removeFirst();
+            invocation = functionQueue().takeFirst();
         }
 
         invocation.function(invocation.context);
         }
 
         invocation.function(invocation.context);
-        if (invocation.syncFlag)
+        if (invocation.syncFlag) {
+            MutexLocker locker(mainThreadFunctionQueueMutex());
             invocation.syncFlag->signal();
             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.
 
         // 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)
 {
 
 void setMainThreadCallbacksPaused(bool paused)
 {
-    ASSERT(isMainThread());
+    ASSERT((isMainThread() || pthread_main_np()) && WebCoreWebThreadIsLockedOrDisabled());
 
     if (callbacksPaused == paused)
         return;
 
     if (callbacksPaused == paused)
         return;
@@ -230,7 +233,7 @@ void setMainThreadCallbacksPaused(bool paused)
         scheduleDispatchFunctionsOnMainThread();
 }
 
         scheduleDispatchFunctionsOnMainThread();
 }
 
-#if !PLATFORM(MAC) && !PLATFORM(QT)
+#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(BREWMP)
 bool isMainThread()
 {
     return currentThread() == mainThreadIdentifier;
 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));
     {
         void* output;
         kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output));
-        ASSERT(!err);
         if (err)
             output = 0;
         return output;
         if (err)
             output = 0;
         return output;
@@ -58,6 +57,15 @@ public:
     {
         return static_cast<T*>((*this)(reinterpret_cast<vm_address_t>(address), size));
     }
     {
         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
 };
 
 } // namespace WTF
index 1f77b61364459a94cf509840a6548c4560c62eda..54983161103d63462604f63fd2569345c97c4850 100644 (file)
 #ifndef WTF_MathExtras_h
 #define WTF_MathExtras_h
 
 #ifndef WTF_MathExtras_h
 #define WTF_MathExtras_h
 
+#include <algorithm>
 #include <cmath>
 #include <float.h>
 #include <cmath>
 #include <float.h>
+#include <limits>
 #include <stdlib.h>
 
 #if OS(SOLARIS)
 #include <stdlib.h>
 
 #if OS(SOLARIS)
@@ -54,6 +56,14 @@ const double piDouble = M_PI;
 const float piFloat = static_cast<float>(M_PI);
 #endif
 
 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;
 #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 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
 #endif
 
 #endif
@@ -96,7 +106,7 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x
 
 #endif
 
 
 #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)
 
 // 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); }
 
 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)
 {
 // 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; }
 
 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;
 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.
     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>
     };
 
     // 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();
     public:
         MessageQueue() : m_killed(false) { }
         ~MessageQueue();
@@ -92,7 +93,7 @@ namespace WTF {
     inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
     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();
     }
 
         m_condition.signal();
     }
 
@@ -102,7 +103,7 @@ namespace WTF {
     {
         MutexLocker lock(m_mutex);
         bool wasEmpty = m_queue.isEmpty();
     {
         MutexLocker lock(m_mutex);
         bool wasEmpty = m_queue.isEmpty();
-        m_queue.append(message.release());
+        m_queue.append(message.leakPtr());
         m_condition.signal();
         return wasEmpty;
     }
         m_condition.signal();
         return wasEmpty;
     }
@@ -111,7 +112,7 @@ namespace WTF {
     inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message)
     {
         MutexLocker lock(m_mutex);
     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();
     }
 
         m_condition.signal();
     }
 
@@ -119,9 +120,9 @@ namespace WTF {
     inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage()
     {
         MessageQueueWaitResult exitReason; 
     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);
         ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived);
-        return result;
+        return result.release();
     }
 
     template<typename DataType>
     }
 
     template<typename DataType>
@@ -139,19 +140,19 @@ namespace WTF {
 
         if (m_killed) {
             result = MessageQueueTerminated;
 
         if (m_killed) {
             result = MessageQueueTerminated;
-            return 0;
+            return nullptr;
         }
 
         if (timedOut) {
             result = MessageQueueTimeout;
         }
 
         if (timedOut) {
             result = MessageQueueTimeout;
-            return 0;
+            return nullptr;
         }
 
         ASSERT(found != m_queue.end());
         }
 
         ASSERT(found != m_queue.end());
-        DataType* message = *found;
+        OwnPtr<DataType> message = adoptPtr(*found);
         m_queue.remove(found);
         result = MessageQueueMessageReceived;
         m_queue.remove(found);
         result = MessageQueueMessageReceived;
-        return message;
+        return message.release();
     }
 
     template<typename DataType>
     }
 
     template<typename DataType>
@@ -159,13 +160,11 @@ namespace WTF {
     {
         MutexLocker lock(m_mutex);
         if (m_killed)
     {
         MutexLocker lock(m_mutex);
         if (m_killed)
-            return 0;
+            return nullptr;
         if (m_queue.isEmpty())
         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>
     }
 
     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
  *
  *  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
 
 #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
 
 #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
  *
  *  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
 
 #ifndef WTF_OwnArrayPtr_h
 #define WTF_OwnArrayPtr_h
 
+#include "Assertions.h"
+#include "Noncopyable.h"
+#include "NullPtr.h"
+#include "PassOwnArrayPtr.h"
 #include <algorithm>
 #include <algorithm>
-#include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
 
 namespace WTF {
 
 
 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)
 #if COMPILER(WINSCW)
-        operator bool() const { return m_ptr; }
+    operator bool() const { return m_ptr; }
 #else
 #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
 
 #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
 
 
 } // namespace WTF
 
index 8b6cbf45e7acd24831843d1c734266b985407ea9..9d4841a8e299f4a13f036da7280eb67571a34aec 100644 (file)
 #define OwnFastMallocPtr_h
 
 #include "FastMalloc.h"
 #define OwnFastMallocPtr_h
 
 #include "FastMalloc.h"
-#include "Noncopyable.h"
 
 namespace WTF {
 
 
 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)
         {
     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
  *
  *  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"
 #define WTF_OwnPtr_h
 
 #include "Assertions.h"
-#include "Noncopyable.h"
+#include "NullPtr.h"
 #include "OwnPtrCommon.h"
 #include "TypeTraits.h"
 #include <algorithm>
 #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.
 
 
     // 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;
 
     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.
         // 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
 
         // 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.
         // 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; }
 
         ~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; }
 
         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>&);
         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); }
 
 
         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:
     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;
     };
 
         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);
         ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
+        deleteOwnedPtr(ptr);
         return *this;
     }
 
         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);
         ASSERT(!ptr || m_ptr != ptr);
-        if (ptr)
-            deleteOwnedPtr(ptr);
+        deleteOwnedPtr(ptr);
         return *this;
     }
 
         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);
     }
 
     {
         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; 
     }
 
     {
         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(); 
     }
 
     {
         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; 
     }
 
     {
         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(); 
     }
 
     {
         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();
     }
     {
         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.
 #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 _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 {
 #endif
 
 namespace WTF {
@@ -69,6 +73,10 @@ namespace WTF {
     void deleteOwnedPtr(IFileMgr*);
     void deleteOwnedPtr(IFile*);
     void deleteOwnedPtr(IBitmap*);
     void deleteOwnedPtr(IFileMgr*);
     void deleteOwnedPtr(IFile*);
     void deleteOwnedPtr(IBitmap*);
+    void deleteOwnedPtr(ISSL*);
+    void deleteOwnedPtr(ISocket*);
+    void deleteOwnedPtr(IMemGroup*);
+    void deleteOwnedPtr(IMemSpace*);
 #endif
 
 } // namespace WTF
 #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
  *
  * 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"
 #define WTF_PassOwnPtr_h
 
 #include "Assertions.h"
+#include "NullPtr.h"
 #include "OwnPtrCommon.h"
 #include "TypeTraits.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.
 
 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;
 
     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
         // 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; }
 
 
         ~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; }
 
         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; }
 
         typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
         operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
 
-        PassOwnPtr& operator=(T*);
         PassOwnPtr& operator=(const PassOwnPtr<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:
 
     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;
     };
 
         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;
     }
         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;
     }
 
         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;
     }
 
         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(); 
     }
 
     {
         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(); 
     }
     
     {
         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(); 
     }
     
     {
         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; 
     }
     
     {
         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(); 
     }
     
     {
         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(); 
     }
     
     {
         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(); 
     }
     
     {
         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(); 
     }
     
     {
         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; 
     }
     
     {
         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(); 
     }
 
     {
         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();
     }
     {
         return p.get();
     }
@@ -171,6 +221,7 @@ namespace WTF {
 } // namespace WTF
 
 using WTF::PassOwnPtr;
 } // namespace WTF
 
 using WTF::PassOwnPtr;
+using WTF::adoptPtr;
 using WTF::const_pointer_cast;
 using WTF::static_pointer_cast;
 
 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
  *
  *  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"
 #define WTF_PassRefPtr_h
 
 #include "AlwaysInline.h"
+#include "NullPtr.h"
 
 namespace WTF {
 
     template<typename T> class RefPtr;
     template<typename T> class PassRefPtr;
 
 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)
 #if !COMPILER(WINSCW)
 #if !PLATFORM(QT)
-    ALWAYS_INLINE
+    #define REF_DEREF_INLINE ALWAYS_INLINE
 #else
 #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
 #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
 #endif
-    void refIfNotNull(T* ptr)
+
+    template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr)
     {
         if (LIKELY(ptr != 0))
             ptr->ref();
     }
 
     {
         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();
     }
 
     {
         if (LIKELY(ptr != 0))
             ptr->deref();
     }
 
+    #undef REF_DEREF_INLINE
+
     template<typename T> class PassRefPtr {
     public:
     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
         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); }
 
 
         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; }
 
         
         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; }
 
         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.
         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&);
 
         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*);
 
         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
     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
         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.
     // 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)
     public:
         NonNullPassRefPtr(T* ptr)
             : m_ptr(ptr)
@@ -125,7 +126,7 @@ namespace WTF {
             m_ptr->ref();
         }
 
             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);
             : m_ptr(o.get())
         {
             ASSERT(m_ptr);
@@ -133,19 +134,19 @@ namespace WTF {
         }
 
         NonNullPassRefPtr(const NonNullPassRefPtr& o)
         }
 
         NonNullPassRefPtr(const NonNullPassRefPtr& o)
-            : m_ptr(o.releaseRef())
+            : m_ptr(o.leakRef())
         {
             ASSERT(m_ptr);
         }
 
         {
             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);
         }
 
         {
             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);
         }
         {
             ASSERT(m_ptr);
         }
@@ -154,17 +155,41 @@ namespace WTF {
 
         T* get() const { return m_ptr; }
 
 
         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; }
 
 
         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;
     };
 
     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);
     {
         T* optr = o.get();
         refIfNotNull(optr);
@@ -174,7 +199,7 @@ namespace WTF {
         return *this;
     }
     
         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;
     {
         refIfNotNull(optr);
         T* ptr = m_ptr;
@@ -183,92 +208,100 @@ namespace WTF {
         return *this;
     }
 
         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;
     {
         T* ptr = m_ptr;
-        m_ptr = ref.releaseRef();
+        m_ptr = ref.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
     
         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;
     {
         T* ptr = m_ptr;
-        m_ptr = ref.releaseRef();
+        m_ptr = ref.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
     
         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(); 
     }
 
     { 
         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(); 
     }
 
     { 
         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(); 
     }
 
     { 
         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; 
     }
     
     { 
         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(); 
     }
     
     {
         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(); 
     }
 
     { 
         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(); 
     }
 
     { 
         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(); 
     }
 
     { 
         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; 
     }
 
     {
         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(); 
     }
     
     { 
         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);
     }
 
         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();
     }
 
     {
         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;
 } // 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) 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
  *
  * 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 */
 #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
 #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 */
 #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__)
 #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 */
 #endif
 
 /* COMPILER(MINGW) - MinGW GCC */
 #undef _WIN32
 #endif
 
 #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() - the target CPU architecture ==== */
 
 
 /* CPU(MIPS) - MIPS 32-bit */
 /* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now.  */
 
 /* 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__)
     && 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_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 */
 #endif /* MIPS */
 
 /* CPU(PPC) - PowerPC 32-bit */
 #define WTF_CPU_SPARC 1
 #endif
 
 #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)     \
 /* CPU(X86) - i386 / x86 32-bit */
 #if   defined(__i386__) \
     || defined(i386)     \
     || defined(_ARM_)
 #define WTF_CPU_ARM 1
 
     || 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__) \
 #define WTF_CPU_BIG_ENDIAN 1
 
 #elif !defined(__ARM_EABI__) \
 
 #elif defined(__ARM_ARCH_5__) \
     || defined(__ARM_ARCH_5T__) \
 
 #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
 
     || 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__) \
 #elif defined(__ARM_ARCH_6__) \
     || defined(__ARM_ARCH_6J__) \
     || defined(__ARM_ARCH_6K__) \
 #define WTF_ARM_ARCH_VERSION 6
 
 #elif defined(__ARM_ARCH_7A__) \
 #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
 
 #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
 
 #else
 #define WTF_ARM_ARCH_VERSION 0
 
 #elif defined(__ARM_ARCH_6T2__) \
     || defined(__ARM_ARCH_7__) \
     || defined(__ARM_ARCH_7A__) \
 #elif defined(__ARM_ARCH_6T2__) \
     || defined(__ARM_ARCH_7__) \
     || defined(__ARM_ARCH_7A__) \
+    || defined(__ARM_ARCH_7F__) \
     || defined(__ARM_ARCH_7R__) \
     || 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 */
 #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) */
 
 #  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 ==== */
 
 /* ==== 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>
 
 /* 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
 #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
 #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
 
 
 #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))
 #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 */
 #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
 
 #define WTF_OS_FREEBSD 1
 #endif
 
 
 /* OS(NETBSD) - NetBSD */
 #if defined(__NetBSD__)
 
 /* OS(NETBSD) - NetBSD */
 #if defined(__NetBSD__)
-#define WTF_PLATFORM_NETBSD 1
+#define WTF_OS_NETBSD 1
 #endif
 
 /* OS(OPENBSD) - OpenBSD */
 #endif
 
 /* OS(OPENBSD) - OpenBSD */
 #define WTF_PLATFORM_WIN 1
 #endif
 
 #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)
 /* 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
 
 #endif
 
-/* PLATFORM(IPHONE_SIMULATOR) */
+/* PLATFORM(IOS_SIMULATOR) */
 #if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_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
 #else
-#define WTF_PLATFORM_IPHONE_SIMULATOR 0
+#define WTF_PLATFORM_IOS_SIMULATOR 0
 #endif
 
 #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 */
 
 #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)
 #if PLATFORM(CHROMIUM)
-#define ENABLE_HISTORY_ALWAYS_ASYNC 1
 #if OS(DARWIN)
 #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_ATSUI 1
 #define WTF_USE_CORE_TEXT 1
+#define WTF_USE_ICCJPEG 1
 #else
 #else
-#define WTF_PLATFORM_SKIA 1
+#define WTF_USE_SKIA 1
+#define WTF_USE_CHROMIUM_NET 1
 #endif
 #endif
 
 #endif
 #endif
 
+#if PLATFORM(BREWMP)
+#define WTF_USE_SKIA 1
+#endif
+
 #if PLATFORM(GTK)
 #if PLATFORM(GTK)
-#define WTF_PLATFORM_CAIRO 1
+#define WTF_USE_CAIRO 1
 #endif
 
 
 #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
 
 #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
 
 #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)
 /* 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 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)
 
 #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
 #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 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
 #elif PLATFORM(GTK)
 /* The GTK+ Unicode backend is configurable */
 #else
 #endif
 
 
 #endif
 
 
-
 #if PLATFORM(CHROMIUM) && OS(DARWIN)
 #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_PTHREADS 1
 #define HAVE_PTHREAD_RWLOCK 1
-#define WTF_USE_CARBON_SECURE_INPUT_MODE 1
 #endif
 
 #define DONT_FINALIZE_ON_MAIN_THREAD 1
 
 #endif
 
 #define DONT_FINALIZE_ON_MAIN_THREAD 1
 
+#if PLATFORM(BREWMP)
+#define ENABLE_SINGLE_THREADED 1
+#endif
+
 #if PLATFORM(QT) && OS(DARWIN)
 #if PLATFORM(QT) && OS(DARWIN)
-#define WTF_PLATFORM_CF 1
+#define WTF_USE_CF 1
 #endif
 
 #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_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_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_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_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 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 WTF_USE_PTHREADS 1
 #define WTF_USE_WEB_THREAD 1
 
 #define ENABLE_PURGEABLE_MEMORY 1
 #endif
 
 #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
 #if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION >= 7
     // ARMv7;
     #define WTF_USE_JSVALUE32_64 1
     #endif
 #endif
 
     #endif
 #endif
 
-#undef ENABLE_3D_CANVAS
+#undef ENABLE_WEBGL
 #if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6
 #if defined(WTF_ARM_ARCH_VERSION) && WTF_ARM_ARCH_VERSION == 6
-#define ENABLE_3D_CANVAS 0
+#define ENABLE_WEBGL 0
 #else
 #else
-#define ENABLE_3D_CANVAS 1
+#define ENABLE_WEBGL 1
 #endif
 
 
 #if PLATFORM(ANDROID)
 #define WTF_USE_PTHREADS 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
 #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
    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
 
 #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)
 #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
 #define WTF_USE_CORE_TEXT 1
-#else
-#define WTF_USE_ATSUI 1
-#endif
+#define ENABLE_WEB_ARCHIVE 1
 #endif
 #endif
 
 #endif
 #endif
 
 #define USE_SYSTEM_MALLOC 1
 #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) */
 #if !defined(HAVE_ACCESSIBILITY)
 #define HAVE_ACCESSIBILITY 1
 #endif /* !defined(HAVE_ACCESSIBILITY) */
 #define HAVE_SIGNAL_H 1
 #endif
 
 #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)
 #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 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_DISPATCH_H 1
+#define HAVE_HOSTED_CORE_ANIMATION 1
 
 
 #endif
 
 
 #endif
 #define HAVE_ERRNO_H 0
 #else
 #define HAVE_SYS_TIMEB_H 1
 #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
 
 #endif
 #define HAVE_VIRTUALALLOC 1
 
 /* ENABLE macro defaults */
 
 #if PLATFORM(QT)
 /* 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
 #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
 #endif
 
 /* fastMalloc match validation allows for runtime verification that
 #define ENABLE_DRAG_SUPPORT 1
 #endif
 
 #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
 
 #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)
 #endif
 
 #if !defined(ENABLE_GEOLOCATION_PERMISSION_CACHE)
 #define ENABLE_NETSCAPE_PLUGIN_API 1
 #endif
 
 #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
 #if !defined(ENABLE_PURGEABLE_MEMORY)
 #define ENABLE_PURGEABLE_MEMORY 0
 #endif
 #define ENABLE_RESPECT_EXIF_ORIENTATION 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
 #if !defined(ENABLE_OPCODE_STATS)
 #define ENABLE_OPCODE_STATS 0
 #endif
 #define ENABLE_GEOLOCATION 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
 #if !defined(ENABLE_NOTIFICATIONS)
 #define ENABLE_NOTIFICATIONS 0
 #endif
 #define ENABLE_ON_FIRST_TEXTAREA_FOCUS_SELECT_ALL 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
 
 #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) \
 #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
 #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
 #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_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
 
 #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
-#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
 #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
 
 #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
 
 #endif
 
+/* Configure the JIT */
 #if ENABLE(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)
 #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
 
 #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
 #define HAVE_COMPUTED_GOTO 1
 #endif
-
 #if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER)
 #define ENABLE_COMPUTED_GOTO_INTERPRETER 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
 #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)
 #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
 
 #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
 
 /* 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 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
 #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
 
 #endif
 
+/* Accelerated compositing */
+#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !OS(WINCE) &&!defined(WIN_CAIRO))
 #define WTF_USE_ACCELERATED_COMPOSITING 1
 #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
 
 #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
 
 #define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1
 #endif
 
+
 #if COMPILER(GCC)
 #define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result))
 #else
 #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
 
 
 #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 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 */
 #endif /* WTF_Platform_h */
index fc4826307a13c45549864d8ee22d67aa95658cb5..490c5914a72373c30f63df4f4127c4bb72133be6 100644 (file)
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "RandomNumber.h"
 
 #include "config.h"
 #include "RandomNumber.h"
 
+#include "CryptographicallyRandomNumber.h"
 #include "RandomNumberSeed.h"
 
 #include <limits>
 #include "RandomNumberSeed.h"
 
 #include <limits>
@@ -34,9 +35,9 @@
 #include <stdint.h>
 #include <stdlib.h>
 
 #include <stdint.h>
 #include <stdlib.h>
 
-#if OS(WINCE)
+#if USE(MERSENNE_TWISTER_19937)
 extern "C" {
 extern "C" {
-#include "wince/mt19937ar.c"
+#include "mt19937ar.c"
 }
 #endif
 
 }
 #endif
 
@@ -44,79 +45,41 @@ extern "C" {
 #include <AEEAppGen.h>
 #include <AEESource.h>
 #include <AEEStdLib.h>
 #include <AEEAppGen.h>
 #include <AEESource.h>
 #include <AEEStdLib.h>
+#include <wtf/brew/RefPtrBrew.h>
+#include <wtf/brew/ShellBrew.h>
 #endif
 
 namespace WTF {
 
 #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 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
     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();
     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;
 #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
 
     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
     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();
 
     // 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;
 }
 
 using WTF::randomNumber;
index ae414c0e32a7f5f395138935fe26f496c9039613..0703abfe9b632c808fd711f774fc70bf9ca116e5 100644 (file)
@@ -38,7 +38,7 @@
 #include <unistd.h>
 #endif
 
 #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);
 }
 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()
     // 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 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;
 #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
 #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
 }
+
 }
 
 #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
  *
  * 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
 
 #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 {
 
 
 namespace WTF {
 
@@ -34,6 +35,7 @@ public:
     void ref()
     {
         ASSERT(!m_deletionHasBegun);
     void ref()
     {
         ASSERT(!m_deletionHasBegun);
+        ASSERT(!m_adoptionIsRequired);
         ++m_refCount;
     }
 
         ++m_refCount;
     }
 
@@ -48,23 +50,43 @@ public:
         return m_refCount;
     }
 
         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)
 protected:
     RefCountedBase()
         : m_refCount(1)
 #ifndef NDEBUG
         , m_deletionHasBegun(false)
+        , m_adoptionIsRequired(true)
 #endif
     {
     }
 
     ~RefCountedBase()
     {
 #endif
     {
     }
 
     ~RefCountedBase()
     {
+        ASSERT(m_deletionHasBegun);
+        ASSERT(!m_adoptionIsRequired);
     }
 
     // Returns whether the pointer should be freed or not.
     bool derefBase()
     {
         ASSERT(!m_deletionHasBegun);
     }
 
     // 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
         ASSERT(m_refCount > 0);
         if (m_refCount == 1) {
 #ifndef NDEBUG
@@ -77,12 +99,6 @@ protected:
         return false;
     }
 
         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
     {
 #ifndef NDEBUG
     bool deletionHasBegun() const
     {
@@ -91,17 +107,33 @@ protected:
 #endif
 
 private:
 #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;
 
     int m_refCount;
 #ifndef NDEBUG
     bool m_deletionHasBegun;
+    bool m_adoptionIsRequired;
 #endif
 };
 
 #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()
     {
 public:
     void deref()
     {
@@ -110,12 +142,15 @@ public:
     }
 
 protected:
     }
 
 protected:
+    RefCounted() { }
     ~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()
     {
 public:
     void deref()
     {
index 80922d3367b04e3765b520478fc1b21795a58710..08b32ab3249c611d331ecd3b1a30a21a82ad83b4 100644 (file)
@@ -79,7 +79,7 @@ RefCountedLeakCounter::~RefCountedLeakCounter()
 
 void RefCountedLeakCounter::increment()
 {
 
 void RefCountedLeakCounter::increment()
 {
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
     atomicIncrement(&m_count);
 #else
     ++m_count;
     atomicIncrement(&m_count);
 #else
     ++m_count;
@@ -88,7 +88,7 @@ void RefCountedLeakCounter::increment()
 
 void RefCountedLeakCounter::decrement()
 {
 
 void RefCountedLeakCounter::decrement()
 {
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
     atomicDecrement(&m_count);
 #else
     --m_count;
     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
  *
  *  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>
 #define WTF_RefPtr_h
 
 #include <algorithm>
-#include "AlwaysInline.h"
 #include "FastAllocBase.h"
 #include "PassRefPtr.h"
 
 #include "FastAllocBase.h"
 #include "PassRefPtr.h"
 
@@ -32,34 +31,35 @@ namespace WTF {
 
     enum PlacementNewAdoptType { PlacementNewAdopt };
 
 
     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 };
 
 
     enum HashTableDeletedValueType { HashTableDeletedValue };
 
-    template <typename T> class RefPtr : public FastAllocBase {
+    template<typename T> class RefPtr {
+        WTF_MAKE_FAST_ALLOCATED;
     public:
     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.
 
         // 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(); }
 
 
         // 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; }
         
         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; }
         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>&);
         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&);
 
 
         void swap(RefPtr&);
 
@@ -87,17 +90,24 @@ namespace WTF {
         T* m_ptr;
     };
     
         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);
     {
         T* optr = o.get();
         refIfNotNull(optr);
@@ -107,7 +117,7 @@ namespace WTF {
         return *this;
     }
     
         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);
     {
         T* optr = o.get();
         refIfNotNull(optr);
@@ -117,7 +127,7 @@ namespace WTF {
         return *this;
     }
     
         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;
     {
         refIfNotNull(optr);
         T* ptr = m_ptr;
@@ -126,89 +136,89 @@ namespace WTF {
         return *this;
     }
 
         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;
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
         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;
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
         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;
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
         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;
     {
         T* ptr = m_ptr;
-        m_ptr = o.releaseRef();
+        m_ptr = o.leakRef();
         derefIfNotNull(ptr);
         return *this;
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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(); 
     }
 
     { 
         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; 
     }
     
     { 
         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(); 
     }
     
     {
         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(); 
     }
 
     { 
         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; 
     }
 
     {
         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(); 
     }
     
     { 
         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())); 
     }
 
     { 
         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())); 
     }
 
     { 
         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();
     }
     {
         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
 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>
     };
 
     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;
     private:
         typedef KeyTraitsArg KeyTraits;
         typedef MappedTraitsArg MappedTraits;
@@ -334,3 +338,5 @@ namespace WTF {
     }
 
 } // 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
  *
  *  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
 
 #ifndef RetainPtr_h
 #define RetainPtr_h
 
+#include "HashTraits.h"
+#include "NullPtr.h"
 #include "TypeTraits.h"
 #include <algorithm>
 #include "TypeTraits.h"
 #include <algorithm>
+
+#if USE(CF)
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CoreFoundation.h>
+#endif
 
 #ifdef __OBJC__
 #import <Foundation/Foundation.h>
 
 #ifdef __OBJC__
 #import <Foundation/Foundation.h>
@@ -47,7 +52,7 @@ namespace WTF {
     }
 #endif
 
     }
 #endif
 
-    template <typename T> class RetainPtr {
+    template<typename T> class RetainPtr {
     public:
         typedef typename RemovePointer<T>::Type ValueType;
         typedef ValueType* PtrType;
     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); }
 
         
         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); }
         
         ~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 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; }
         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&);
         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);
         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&);
 
 
         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:
     private:
+        static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); }
+
         PtrType m_ptr;
     };
     
         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)
     {
         PtrType optr = o.get();
         if (optr)
@@ -102,7 +142,7 @@ namespace WTF {
         return *this;
     }
     
         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)
     {
         PtrType optr = o.get();
         if (optr)
@@ -114,7 +154,7 @@ namespace WTF {
         return *this;
     }
     
         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);
     {
         if (optr)
             CFRetain(optr);
@@ -125,7 +165,7 @@ namespace WTF {
         return *this;
     }
 
         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;
     {
         PtrType ptr = m_ptr;
         m_ptr = optr;
@@ -133,7 +173,7 @@ namespace WTF {
             CFRelease(ptr);
     }
 
             CFRelease(ptr);
     }
 
-    template <typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
+    template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr)
     {
         adoptNSReference(optr);
         
     {
         adoptNSReference(optr);
         
@@ -143,7 +183,7 @@ namespace WTF {
             CFRelease(ptr);
     }
     
             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);
     {
         if (optr)
             CFRetain(optr);
@@ -154,45 +194,58 @@ namespace WTF {
         return *this;
     }
 
         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);
     }
 
     {
         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);
     }
 
     {
         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(); 
     }
 
     { 
         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; 
     }
     
     { 
         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(); 
     }
     
     {
         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(); 
     }
 
     { 
         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; 
     }
 
     {
         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(); 
     }
     { 
         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
 
 
 } // 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)
 
 #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 {
 
 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
 
 
 } // 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
  *
  * 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 <stdarg.h>
 #include <stdio.h>
+#include <string.h>
 
 #if HAVE(STRINGS_H) 
 #include <strings.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);
     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;
 }
 
     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)
 
 
 #if OS(WINCE)
 
@@ -86,8 +100,7 @@ inline int strcasecmp(const char* s1, const char* s2)
 
 #endif
 
 
 #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)
 {
 
 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.
 
   // 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;
   }
     // 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) 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
 // All rights reserved.
 // 
 // Redistribution and use in source and binary forms, with or without
@@ -37,8 +38,6 @@
 
 #include <time.h>       /* For nanosleep() */
 
 
 #include <time.h>       /* For nanosleep() */
 
-#include <sched.h>      /* For sched_yield() */
-
 #if HAVE(STDINT_H)
 #include <stdint.h>
 #elif HAVE(INTTYPES_H)
 #if HAVE(STDINT_H)
 #include <stdint.h>
 #elif HAVE(INTTYPES_H)
@@ -52,6 +51,8 @@
 #define WIN32_LEAN_AND_MEAN
 #endif
 #include <windows.h>
 #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);
 #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) {
 #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)
   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>
 #else
 
 #include <pthread.h>
index c46ff311f1cfd29bd11d1b5768de3908ae824d7f..3cb59e8808ecee7b041427233e7925d9c7b71150 100644 (file)
 // Author: Sanjay Ghemawat
 
 #include "config.h"
 // Author: Sanjay Ghemawat
 
 #include "config.h"
+#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC)
 #include "TCSystemAlloc.h"
 
 #include <algorithm>
 #include "TCSystemAlloc.h"
 
 #include <algorithm>
-#include <fcntl.h>
 #include "Assertions.h"
 #include "TCSpinLock.h"
 #include "UnusedParam.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
 // 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
 
 #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.
 #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();
 
 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>
 #include <pthread.h>
 #elif PLATFORM(QT)
 #include <QThreadStorage>
+#elif PLATFORM(GTK)
+#include <glib.h>
 #elif OS(WINDOWS)
 #include <windows.h>
 #endif
 
 namespace WTF {
 
 #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
 
 // 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*();
 public:
     ThreadSpecific();
     T* operator->();
     operator T*();
     T& operator*();
-    ~ThreadSpecific();
+
+    void replace(T*);
 
 private:
 
 private:
-#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK) && OS(WINDOWS)
     friend void ThreadSpecificThreadExit();
 #endif
     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);
 
     
     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); }
         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;
 
         T* value;
         ThreadSpecific<T>* owner;
-#if !USE(PTHREADS) && !PLATFORM(QT)
+#if !USE(PTHREADS) && !PLATFORM(QT) && !PLATFORM(GTK)
         void (*destructor)(void*);
 #endif
     };
         void (*destructor)(void*);
 #endif
     };
@@ -98,6 +110,8 @@ private:
     pthread_key_t m_key;
 #elif PLATFORM(QT)
     QThreadStorage<Data*> m_key;
     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
 #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()
 {
 template<typename T>
 inline T* ThreadSpecific<T>::get()
 {
@@ -138,12 +147,6 @@ inline ThreadSpecific<T>::ThreadSpecific()
         CRASH();
 }
 
         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()
 {
 template<typename T>
 inline T* ThreadSpecific<T>::get()
 {
@@ -166,15 +169,32 @@ inline ThreadSpecific<T>::ThreadSpecific()
 }
 
 template<typename T>
 }
 
 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()
 {
 }
 
 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;
 }
 
     return data ? data->value : 0;
 }
 
@@ -183,7 +203,7 @@ inline void ThreadSpecific<T>::set(T* ptr)
 {
     ASSERT(!get());
     Data* data = new Data(ptr, this);
 {
     ASSERT(!get());
     Data* data = new Data(ptr, this);
-    m_key.setLocalData(data);
+    g_static_private_set(&m_key, data, destroy);
 }
 
 #elif OS(WINDOWS)
 }
 
 #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);
     // 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
 #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
     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
 #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.
     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;
     }
         set(ptr);
         new (ptr) T;
     }
@@ -304,6 +329,17 @@ inline T& ThreadSpecific<T>::operator*()
     return *operator T*();
 }
 
     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
 }
 
 #endif
index f2c0cad95766558f0f69e2457490fea8bf558e45..d72996a7a0ca0239a146118d3e05b1e681ad5631 100644 (file)
@@ -21,7 +21,6 @@
 #include "config.h"
 
 #include "ThreadSpecific.h"
 #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.
 
 #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 {
 
 
 namespace WTF {
 
-struct NewThreadContext : FastAllocBase {
+struct NewThreadContext {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
     NewThreadContext(ThreadFunction entryPoint, void* data, const char* name)
         : entryPoint(entryPoint)
         , data(data)
     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/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).
 #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);
 
 int waitForThreadCompletion(ThreadIdentifier, void**);
 void detachThread(ThreadIdentifier);
 
+void yield();
 
 void lockAtomicallyInitializedStaticMutex();
 void unlockAtomicallyInitializedStaticMutex();
 
 void lockAtomicallyInitializedStaticMutex();
 void unlockAtomicallyInitializedStaticMutex();
@@ -112,5 +113,6 @@ using WTF::createThread;
 using WTF::currentThread;
 using WTF::detachThread;
 using WTF::waitForThreadCompletion;
 using WTF::currentThread;
 using WTF::detachThread;
 using WTF::waitForThreadCompletion;
+using WTF::yield;
 
 #endif // Threading_h
 
 #endif // Threading_h
index 66801c0b8466baf112f05cec7812ab9515c60c9b..831a99e26ff5e43e98b9b88435d41a0284acdab0 100644 (file)
@@ -34,6 +34,7 @@
 #include "Platform.h"
 
 #include <wtf/Assertions.h>
 #include "Platform.h"
 
 #include <wtf/Assertions.h>
+#include <wtf/FastAllocBase.h>
 #include <wtf/Locker.h>
 #include <wtf/Noncopyable.h>
 
 #include <wtf/Locker.h>
 #include <wtf/Noncopyable.h>
 
@@ -45,8 +46,6 @@
 #include <pthread.h>
 #elif PLATFORM(GTK)
 #include "GOwnPtr.h"
 #include <pthread.h>
 #elif PLATFORM(GTK)
 #include "GOwnPtr.h"
-typedef struct _GMutex GMutex;
-typedef struct _GCond GCond;
 #endif
 
 #if PLATFORM(QT)
 #endif
 
 #if PLATFORM(QT)
@@ -98,7 +97,8 @@ typedef void* PlatformReadWriteLock;
 typedef void* PlatformCondition;
 #endif
     
 typedef void* PlatformCondition;
 #endif
     
-class Mutex : public Noncopyable {
+class Mutex {
+    WTF_MAKE_NONCOPYABLE(Mutex); WTF_MAKE_FAST_ALLOCATED;
 public:
     Mutex();
     ~Mutex();
 public:
     Mutex();
     ~Mutex();
@@ -115,7 +115,8 @@ private:
 
 typedef Locker<Mutex> MutexLocker;
 
 
 typedef Locker<Mutex> MutexLocker;
 
-class ReadWriteLock : public Noncopyable {
+class ReadWriteLock {
+    WTF_MAKE_NONCOPYABLE(ReadWriteLock);
 public:
     ReadWriteLock();
     ~ReadWriteLock();
 public:
     ReadWriteLock();
     ~ReadWriteLock();
@@ -132,7 +133,8 @@ private:
     PlatformReadWriteLock m_readWriteLock;
 };
 
     PlatformReadWriteLock m_readWriteLock;
 };
 
-class ThreadCondition : public Noncopyable {
+class ThreadCondition {
+    WTF_MAKE_NONCOPYABLE(ThreadCondition);
 public:
     ThreadCondition();
     ~ThreadCondition();
 public:
     ThreadCondition();
     ~ThreadCondition();
@@ -148,10 +150,20 @@ private:
     PlatformCondition m_condition;
 };
 
     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;
 
 } // namespace WTF
 
 using WTF::Mutex;
 using WTF::MutexLocker;
 using WTF::ThreadCondition;
 
+#if OS(WINDOWS)
+using WTF::absoluteTimeToWaitTimeoutInterval;
+#endif
+
 #endif // ThreadingPrimitives_h
 #endif // ThreadingPrimitives_h
index f468ce2d72350e6f13483e48f6a7e73105c423e4..916aa3656dbac7f383f63e743ffeb6e2810ddec5 100644 (file)
 
 #if !COMPILER(MSVC)
 #include <limits.h>
 
 #if !COMPILER(MSVC)
 #include <limits.h>
+#include <sched.h>
 #include <sys/time.h>
 #endif
 
 #if OS(ANDROID)
 #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 {
 #endif
 
 namespace WTF {
@@ -135,38 +143,34 @@ void clearPthreadHandleForIdentifier(ThreadIdentifier id)
 }
 
 #if OS(ANDROID)
 }
 
 #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)
 {
 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) {
     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();
     }
         vm->DetachCurrentThread();
     }
-    delete data;
     return ret;
 }
 
 ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*)
 {
     pthread_t threadHandle;
     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);
         LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data);
-        delete threadData;
         return 0;
     }
         return 0;
     }
+
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
+
     return establishIdentifierForPthreadHandle(threadHandle);
 }
 #else
     return establishIdentifierForPthreadHandle(threadHandle);
 }
 #else
@@ -190,6 +194,12 @@ void initializeCurrentThreadInternal(const char* threadName)
     UNUSED_PARAM(threadName);
 #endif
 
     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);
     ThreadIdentifier id = identifierByPthreadHandle(pthread_self());
     ASSERT(id);
     ThreadIdentifierData::initialize(id);
@@ -221,6 +231,11 @@ void detachThread(ThreadIdentifier threadID)
     pthread_detach(pthreadHandle);
 }
 
     pthread_detach(pthreadHandle);
 }
 
+void yield()
+{
+    sched_yield();
+}
+
 ThreadIdentifier currentThread()
 {
     ThreadIdentifier id = ThreadIdentifierData::identifier();
 ThreadIdentifier currentThread()
 {
     ThreadIdentifier id = ThreadIdentifierData::identifier();
@@ -235,7 +250,13 @@ ThreadIdentifier currentThread()
 
 Mutex::Mutex()
 {
 
 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()
 }
 
 Mutex::~Mutex()
index c16be5aa86de3c8b1ad7de92bbfe19568bd7a8ee..c452205c55cc213a6f91e9ab5c6cc6824d19cf26 100644 (file)
 #include "Threading.h"
 
 #include "MainThread.h"
 #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 !USE(PTHREADS) && OS(WINDOWS)
 #include "ThreadSpecific.h"
 #endif
+
 #if !OS(WINCE)
 #include <process.h>
 #endif
 #if !OS(WINCE)
 #include <process.h>
 #endif
+
 #if HAVE(ERRNO_H)
 #include <errno.h>
 #if HAVE(ERRNO_H)
 #include <errno.h>
-#else
-#define NO_ERRNO
 #endif
 #endif
-#include <windows.h>
-#include <wtf/CurrentTime.h>
-#include <wtf/HashMap.h>
-#include <wtf/MathExtras.h>
-#include <wtf/RandomNumberSeed.h>
 
 namespace WTF {
 
 
 namespace WTF {
 
@@ -187,19 +191,10 @@ static void clearThreadHandleForIdentifier(ThreadIdentifier id)
     threadMap().remove(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)
 {
 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.
 
 #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;
 {
     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
 #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
 #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());
 #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);
         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;
     }
 
         return 0;
     }
 
+    // The thread will take ownership of invocation.
+    invocation.leakPtr();
+
     threadID = static_cast<ThreadIdentifier>(threadIdentifier);
     storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
 
     threadID = static_cast<ThreadIdentifier>(threadIdentifier);
     storeThreadHandleByIdentifier(threadIdentifier, threadHandle);
 
@@ -266,6 +264,11 @@ void detachThread(ThreadIdentifier threadID)
     clearThreadHandleForIdentifier(threadID);
 }
 
     clearThreadHandleForIdentifier(threadID);
 }
 
+void yield()
+{
+    ::Sleep(1);
+}
+
 ThreadIdentifier currentThread()
 {
     return static_cast<ThreadIdentifier>(GetCurrentThreadId());
 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);
 
     res = ReleaseSemaphore(m_blockLock, 1, 0);
     ASSERT(res);
 
+    --mutex.m_recursionCount;
     LeaveCriticalSection(&mutex.m_internalMutex);
 
     // Main wait - use timeout.
     LeaveCriticalSection(&mutex.m_internalMutex);
 
     // Main wait - use timeout.
@@ -362,6 +366,7 @@ bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMillisecon
     }
 
     EnterCriticalSection (&mutex.m_internalMutex);
     }
 
     EnterCriticalSection (&mutex.m_internalMutex);
+    ++mutex.m_recursionCount;
 
     return !timedOut;
 }
 
     return !timedOut;
 }
@@ -455,20 +460,15 @@ void ThreadCondition::wait(Mutex& mutex)
 
 bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime)
 {
 
 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;
         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()
 }
 
 void ThreadCondition::signal()
@@ -481,4 +481,19 @@ void ThreadCondition::broadcast()
     m_condition.signal(true); // Unblock all threads.
 }
 
     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
 } // 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(!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);
 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, 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
 } // 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(__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 {
 #endif
 
 namespace WTF {
@@ -39,6 +42,7 @@ namespace WTF {
     //   IsSameType<T, U>::value
     //
     //   RemovePointer<T>::Type
     //   IsSameType<T, U>::value
     //
     //   RemovePointer<T>::Type
+    //   RemoveReference<T>::Type
     //   RemoveConst<T>::Type
     //   RemoveVolatile<T>::Type
     //   RemoveConstVolatile<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<> 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.
     // 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 {
     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;
     };
 
         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.
 #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. */
 
 /* 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 */
 
 #endif /* WTF_UnusedParam_h */
index 6600050a1827996453e2379662df117810ecf6c0..117bc3721eacfdde13b6495f43696398f5ad8c7e 100644 (file)
@@ -32,8 +32,6 @@
 
 #include <mach/vm_statistics.h>
 
 
 #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
 #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)
 
 #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
 #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 "FastAllocBase.h"
 #include "Noncopyable.h"
 #include "NotFound.h"
+#include "StdLibExtras.h"
 #include "ValueCheck.h"
 #include "VectorTraits.h"
 #include <limits>
 #include <utility>
 #include "ValueCheck.h"
 #include "VectorTraits.h"
 #include <limits>
 #include <utility>
+#include <wtf/Alignment.h>
 
 #if PLATFORM(QT)
 #include <QDataStream>
 
 #if PLATFORM(QT)
 #include <QDataStream>
@@ -38,18 +40,7 @@ namespace WTF {
     using std::min;
     using std::max;
 
     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; 
         typedef char __attribute__((__may_alias__)) AlignedBufferChar; 
     #else
         typedef char AlignedBufferChar; 
@@ -128,7 +119,11 @@ namespace WTF {
         {
             while (src != srcEnd) {
                 new (dst) T(*src);
         {
             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();
                 src->~T();
+#endif
                 ++dst;
                 ++src;
             }
                 ++dst;
                 ++src;
             }
@@ -276,10 +271,12 @@ namespace WTF {
     };
 
     template<typename T>
     };
 
     template<typename T>
-    class VectorBufferBase : public Noncopyable {
+    class VectorBufferBase {
+        WTF_MAKE_NONCOPYABLE(VectorBufferBase);
     public:
         void allocateBuffer(size_t newCapacity)
         {
     public:
         void allocateBuffer(size_t newCapacity)
         {
+            ASSERT(newCapacity);
             m_capacity = newCapacity;
             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
                 CRASH();
             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)
         {
 
         bool tryAllocateBuffer(size_t newCapacity)
         {
+            ASSERT(newCapacity);
             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
                 return false;
 
             if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T))
                 return false;
 
@@ -358,7 +356,10 @@ namespace WTF {
 
         VectorBuffer(size_t capacity)
         {
 
         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()
         }
 
         ~VectorBuffer()
@@ -390,6 +391,7 @@ namespace WTF {
 
     template<typename T, size_t inlineCapacity>
     class VectorBuffer : private VectorBufferBase<T> {
 
     template<typename T, size_t inlineCapacity>
     class VectorBuffer : private VectorBufferBase<T> {
+        WTF_MAKE_NONCOPYABLE(VectorBuffer);
     private:
         typedef VectorBufferBase<T> Base;
     public:
     private:
         typedef VectorBufferBase<T> Base;
     public:
@@ -412,6 +414,7 @@ namespace WTF {
 
         void allocateBuffer(size_t newCapacity)
         {
 
         void allocateBuffer(size_t newCapacity)
         {
+            // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
             if (newCapacity > inlineCapacity)
                 Base::allocateBuffer(newCapacity);
             else {
             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);
         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>
 
         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;
     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); }
 
         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 find(const U&) const;
+        template<typename U> size_t reverseFind(const U&) const;
 
         void shrink(size_t size);
         void grow(size_t size);
 
         void shrink(size_t size);
         void grow(size_t size);
@@ -618,6 +619,8 @@ namespace WTF {
             m_buffer.swap(other.m_buffer);
         }
 
             m_buffer.swap(other.m_buffer);
         }
 
+        void reverse();
+
         void checkConsistency();
 
     private:
         void checkConsistency();
 
     private:
@@ -691,6 +694,12 @@ namespace WTF {
                 return *this;
         }
         
                 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();
         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;
     }
 
         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)
     {
     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()) {
         if (size() > other.size())
             shrink(other.size());
         else if (other.size() > capacity()) {
@@ -714,6 +727,12 @@ namespace WTF {
                 return *this;
         }
         
                 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();
         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;
     }
 
         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
     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;
     }
 
         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)
     {
     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;
     }
 
         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()
     {
     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> { };
 
     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 canInitializeWithMemset = true;
         static const bool canMoveWithMemcpy = true;
-        static const bool canCopyWithMemcpy = false;
-        static const bool canFillWithMemset = false;
         static const bool canCompareWithMemcmp = true;
     };
 
         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)
 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;
     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;
         m_defaultIdentifierTable = new JSC::IdentifierTable();
 
     m_currentIdentifierTable = m_defaultIdentifierTable;
+#endif
 }
 
 WTFThreadData::~WTFThreadData()
 {
     if (m_atomicStringTableDestructor)
         m_atomicStringTableDestructor(m_atomicStringTable);
 }
 
 WTFThreadData::~WTFThreadData()
 {
     if (m_atomicStringTableDestructor)
         m_atomicStringTableDestructor(m_atomicStringTable);
+#if USE(JSC)
     delete m_defaultIdentifierTable;
     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/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/text/StringHash.h>
 
 // This was ENABLE(WORKERS) in WebCore, but this is not defined when compiling JSC.
 #include <wtf/Threading.h>
 #endif
 
 #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;
 
 #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();
 
 public:
     ~IdentifierTable();
 
@@ -68,7 +61,14 @@ public:
     template<typename U, typename V>
     std::pair<HashSet<StringImpl*>::iterator, bool> add(U value);
 
     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; }
 
 
     LiteralIdentifierTable& literalTable() { return m_literalTable; }
 
@@ -82,18 +82,22 @@ private:
 
 namespace WTF {
 
 
 namespace WTF {
 
-class WTFThreadData : public Noncopyable {
+class AtomicStringTable;
+
+typedef void (*AtomicStringTableDestructor)(AtomicStringTable*);
+
+class WTFThreadData {
+    WTF_MAKE_NONCOPYABLE(WTFThreadData);
 public:
     WTFThreadData();
     ~WTFThreadData();
 
 public:
     WTFThreadData();
     ~WTFThreadData();
 
-    WebCore::AtomicStringTable* atomicStringTable()
+    AtomicStringTable* atomicStringTable()
     {
         return m_atomicStringTable;
     }
 
 #if USE(JSC)
     {
         return m_atomicStringTable;
     }
 
 #if USE(JSC)
-
     JSC::IdentifierTable* currentIdentifierTable()
     {
         return m_currentIdentifierTable;
     JSC::IdentifierTable* currentIdentifierTable()
     {
         return m_currentIdentifierTable;
@@ -110,15 +114,21 @@ public:
     {
         m_currentIdentifierTable = m_defaultIdentifierTable;
     }
     {
         m_currentIdentifierTable = m_defaultIdentifierTable;
     }
+
+    const StackBounds& stack() const
+    {
+        return m_stackBounds;
+    }
 #endif
 
 private:
 #endif
 
 private:
-    WebCore::AtomicStringTable* m_atomicStringTable;
+    AtomicStringTable* m_atomicStringTable;
     AtomicStringTableDestructor m_atomicStringTableDestructor;
 
 #if USE(JSC)
     JSC::IdentifierTable* m_defaultIdentifierTable;
     JSC::IdentifierTable* m_currentIdentifierTable;
     AtomicStringTableDestructor m_atomicStringTableDestructor;
 
 #if USE(JSC)
     JSC::IdentifierTable* m_defaultIdentifierTable;
     JSC::IdentifierTable* m_currentIdentifierTable;
+    StackBounds m_stackBounds;
 #endif
 
 #if WTFTHREADDATA_MULTITHREADED
 #endif
 
 #if WTFTHREADDATA_MULTITHREADED
@@ -127,7 +137,7 @@ private:
     static JS_EXPORTDATA WTFThreadData* staticData;
 #endif
     friend WTFThreadData& wtfThreadData();
     static JS_EXPORTDATA WTFThreadData* staticData;
 #endif
     friend WTFThreadData& wtfThreadData();
-    friend class WebCore::AtomicStringTable;
+    friend class AtomicStringTable;
 };
 
 inline WTFThreadData& wtfThreadData()
 };
 
 inline WTFThreadData& wtfThreadData()
index c8384e1d0aa56f7269006c8ed313123bbe84d525..ce10fc3646365776f2346b9b9c8636087f1b0c2d 100644 (file)
 
 #include <AEEBitmap.h>
 #include <AEEFile.h>
 
 #include <AEEBitmap.h>
 #include <AEEFile.h>
+#include <AEEIMemGroup.h>
+#include <AEEIMemSpace.h>
+#include <AEENet.h>
+#include <AEESSL.h>
 #include <AEEStdLib.h>
 
 namespace WTF {
 #include <AEEStdLib.h>
 
 namespace WTF {
@@ -50,4 +54,28 @@ void deleteOwnedPtr(IBitmap* ptr)
         IBitmap_Release(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/Assertions.h>
 #include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
 
 namespace WTF {
 
 
 namespace WTF {
 
@@ -49,8 +50,21 @@ static inline PassOwnPtr<T> createInstance(AEECLSID cls)
     return instance;
 }
 
     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;
 } // namespace WTF
 
 using WTF::createInstance;
+using WTF::createRefPtrInstance;
 
 #endif // ShellBrew_h
 
 #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.
  * 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
  *
  * 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
 
 /* On a machine with IEEE extended-precision registers, it is
  * necessary to specify double-precision (53-bit) rounding precision
@@ -50,7 +44,7 @@
  *
  * Modifications:
  *
  *
  * 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
  *    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).
  */
 
  *        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>
 #include "config.h"
 #include "dtoa.h"
 
 #if HAVE(ERRNO_H)
 #include <errno.h>
-#else
-#define NO_ERRNO
 #endif
 #endif
+#include <float.h>
 #include <math.h>
 #include <stdint.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 <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/FastMalloc.h>
 #include <wtf/MathExtras.h>
-#include <wtf/Vector.h>
 #include <wtf/Threading.h>
 #include <wtf/Threading.h>
-
-#include <stdio.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
 
 #if COMPILER(MSVC)
 #pragma warning(disable: 4244)
 
 #if COMPILER(MSVC)
 #pragma warning(disable: 4244)
 #pragma warning(disable: 4554)
 #endif
 
 #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 {
 
 namespace WTF {
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
 Mutex* s_dtoaP5Mutex;
 #endif
 
 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
 #else
-#ifdef IEEE_8087
 #define word0(x) (x)->L[1]
 #define word1(x) (x)->L[0]
 #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
 #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
 
 /* 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
 #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
 #endif
+    return p + 1;
+}
 
 #define Exp_shift  20
 #define Exp_shift1 20
 
 #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
 
 #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
 
 
 #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
 
 #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;
 struct BigInt {
     BigInt() : sign(0) { }
     int sign;
@@ -291,7 +171,7 @@ struct BigInt {
         sign = 0;
         m_words.clear();
     }
         sign = 0;
         m_words.clear();
     }
-    
+
     size_t size() const
     {
         return m_words.size();
     size_t size() const
     {
         return m_words.size();
@@ -301,7 +181,7 @@ struct BigInt {
     {
         m_words.resize(s);
     }
     {
         m_words.resize(s);
     }
-            
+
     uint32_t* words()
     {
         return m_words.data();
     uint32_t* words()
     {
         return m_words.data();
@@ -311,12 +191,12 @@ struct BigInt {
     {
         return m_words.data();
     }
     {
         return m_words.data();
     }
-    
+
     void append(uint32_t w)
     {
         m_words.append(w);
     }
     void append(uint32_t w)
     {
         m_words.append(w);
     }
-    
+
     Vector<uint32_t, 16> m_words;
 };
 
     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
         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);
         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);
 
 #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)
 {
 
 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;
     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) {
 
     int i = 9;
     if (9 < nd0) {
@@ -414,7 +277,7 @@ static int hi0bits(uint32_t x)
     return k;
 }
 
     return k;
 }
 
-static int lo0bits (uint32_t* y)
+static int lo0bits(uint32_t* y)
 {
     int k;
     uint32_t x = *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)) {
         k++;
         x >>= 1;
-        if (!x & 1)
+        if (!x)
             return 32;
     }
     *y = 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 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;
     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;
     }
         a = b;
         b = tmp;
     }
-    
+
     wa = a->size();
     wb = b->size();
     wc = wa + wb;
     wa = a->size();
     wb = b->size();
     wc = wa + wb;
@@ -511,7 +379,6 @@ static void mult(BigInt& aRef, const BigInt& bRef)
         }
     }
 #else
         }
     }
 #else
-#ifdef Pack_32
     for (; xb < xbe; xb++, xc0++) {
         if ((y = *xb & 0xffff)) {
             x = xa;
     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;
                 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;
         }
             } 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;
             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;
         }
     }
                 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;
 }
 
 #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;
 };
     BigInt val;
     P5Node* next;
 };
-    
+
 static P5Node* p5s;
 static P5Node* p5s;
-static int p5s_count;
+static int p5sCount;
 
 static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
 {
 
 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 (!(k >>= 2))
         return;
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
+#if ENABLE(WTF_MULTIPLE_THREADS)
     s_dtoaP5Mutex->lock();
 #endif
     P5Node* p5 = p5s;
     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;
         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
     s_dtoaP5Mutex->unlock();
 #endif
-    int p5s_used = 0;
+    int p5sUsed = 0;
 
     for (;;) {
         if (k & 1)
 
     for (;;) {
         if (k & 1)
@@ -607,21 +462,21 @@ static ALWAYS_INLINE void pow5mult(BigInt& b, int k)
         if (!(k >>= 1))
             break;
 
         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
             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);
                 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
         }
             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)
 {
 
 static ALWAYS_INLINE void lshift(BigInt& b, int k)
 {
-#ifdef Pack_32
     int n = k >> 5;
     int n = k >> 5;
-#else
-    int n = k >> 4;
-#endif
 
     int origSize = b.size();
     int n1 = n + origSize + 1;
 
     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;
     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;
     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);
 
         *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--;
     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;
     const BigInt* a = &aRef;
     const BigInt* b = &bRef;
     int i, wa, wb;
-    uint32_t *xc;
+    uint32_txc;
 
     i = cmp(*a, *b);
     if (!i) {
 
     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;
     }
 #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;
     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;
     } 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--;
 #endif
     while (!*--xc)
         wa--;
@@ -795,28 +619,8 @@ static double ulp(U *x)
     U u;
 
     L = (word0(x) & Exp_mask) - (P - 1) * Exp_msk1;
     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;
         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);
 }
 
     return dval(&u);
 }
 
@@ -839,12 +643,11 @@ static double b2d(const BigInt& a, int* e)
     ASSERT(y);
     k = hi0bits(y);
     *e = 32 - k;
     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));
     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) {
     }
     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;
     }
         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);
 #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;
 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;
     int i;
-#endif
 #define d0 word0(d)
 #define d1 word1(d)
 
     b.sign = 0;
 #define d0 word0(d)
 #define d1 word1(d)
 
     b.sign = 0;
-#ifdef Pack_32
     b.resize(1);
     b.resize(1);
-#else
-    b.resize(2);
-#endif
     x = b.words();
 
     z = d0 & Frac_mask;
     d0 &= 0x7fffffff;    /* clear sign bit, which we ignore */
     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;
     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 ((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();
         i = b.size();
-#endif
     } else {
         k = lo0bits(&z);
         x[0] = z;
     } else {
         k = lo0bits(&z);
         x[0] = z;
-#ifndef Sudden_Underflow
         i = 1;
         i = 1;
-#endif
         b.resize(1);
         k += 32;
     }
         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) {
     if (de) {
-#endif
         *e = de - Bias - (P - 1) + k;
         *bits = P - k;
         *e = de - Bias - (P - 1) + k;
         *bits = P - k;
-#ifndef Sudden_Underflow
     } else {
         *e = de - Bias - (P - 1) + 1 + k;
     } else {
         *e = de - Bias - (P - 1) + 1 + k;
-#ifdef Pack_32
         *bits = (32 * i) - hi0bits(x[i - 1]);
         *bits = (32 * i) - hi0bits(x[i - 1]);
-#else
-        *bits = (i + 2) * 16 - hi0bits(x[i]);
-#endif
     }
     }
-#endif
 }
 #undef d0
 #undef d1
 }
 #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);
 
     dval(&da) = b2d(a, &ka);
     dval(&db) = b2d(b, &kb);
-#ifdef Pack_32
     k = ka - kb + 32 * (a.size() - b.size());
     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 {
     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[] = {
 }
 
 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,
 };
 
 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 */
 };
 
 /* 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
 
 #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)
 {
 double strtod(const char* s00, char** se)
 {
-#ifdef Avoid_Underflow
     int scale;
     int scale;
-#endif
     int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
     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;
     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;
 
     sign = nz0 = nz = 0;
     dval(&rv) = 0;
-    for (s = s00; ; s++)
+    for (s = s00; ; s++) {
         switch (*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;
                 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;
 break2:
     if (*s == '0') {
         nz0 = 1;
@@ -1161,12 +805,12 @@ break2:
                 s0 = s;
                 nf += nz;
                 nz = 0;
                 s0 = s;
                 nf += nz;
                 nz = 0;
-                goto have_dig;
+                goto haveDig;
             }
             }
-            goto dig_done;
+            goto digDone;
         }
         for (; c >= '0' && c <= '9'; c = *++s) {
         }
         for (; c >= '0' && c <= '9'; c = *++s) {
-have_dig:
+haveDig:
             nz++;
             if (c -= '0') {
                 nf += nz;
             nz++;
             if (c -= '0') {
                 nf += nz;
@@ -1183,19 +827,18 @@ have_dig:
             }
         }
     }
             }
         }
     }
-dig_done:
+digDone:
     e = 0;
     if (c == 'e' || c == 'E') {
     e = 0;
     if (c == 'e' || c == 'E') {
-        if (!nd && !nz && !nz0) {
+        if (!nd && !nz && !nz0)
             goto ret0;
             goto ret0;
-        }
         s00 = s;
         esign = 0;
         switch (c = *++s) {
         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')
         }
         if (c >= '0' && c <= '9') {
             while (c == '0')
@@ -1221,33 +864,6 @@ dig_done:
     }
     if (!nd) {
         if (!nz && !nz0) {
     }
     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;
 ret0:
             s = s00;
             sign = 0;
@@ -1265,14 +881,9 @@ ret0:
         nd0 = nd;
     k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
     dval(&rv) = y;
         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;
         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) {
         if (!e)
             goto ret;
         if (e > 0) {
@@ -1290,24 +901,14 @@ ret0:
                 /* rv = */ rounded_product(dval(&rv), tens[e]);
                 goto ret;
             }
                 /* 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;
         }
             /* rv = */ rounded_quotient(dval(&rv), tens[-e]);
             goto ret;
         }
-#endif
     }
     e1 += nd - k;
 
     }
     e1 += nd - k;
 
-#ifdef SET_INEXACT
-    inexact = 1;
-    if (k <= DBL_DIG)
-        oldinexact = get_inexact();
-#endif
-#ifdef Avoid_Underflow
     scale = 0;
     scale = 0;
-#endif
 
     /* Get starting approximation = rv * 10**e1 */
 
 
     /* Get starting approximation = rv * 10**e1 */
 
@@ -1317,17 +918,12 @@ ret0:
         if (e1 &= ~15) {
             if (e1 > DBL_MAX_10_EXP) {
 ovfl:
         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;
                 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;
                 goto ret;
             }
             e1 >>= 4;
@@ -1354,50 +950,30 @@ ovfl:
         if (e1 >>= 4) {
             if (e1 >= 1 << n_bigtens)
                 goto undfl;
         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) {
             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)
                 if (j >= 32) {
                     word1(&rv) = 0;
                     if (j >= 53)
-                       word0(&rv) = (P + 2) * Exp_msk1;
+                        word0(&rv) = (P + 2) * Exp_msk1;
                     else
                     else
-                       word0(&rv) &= 0xffffffff << (j - 32);
+                        word0(&rv) &= 0xffffffff << (j - 32);
                 } else
                     word1(&rv) &= 0xffffffff << j;
             }
                 } 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.;
                 if (!dval(&rv)) {
 undfl:
                     dval(&rv) = 0.;
-#ifndef NO_ERRNO
+#if HAVE(ERRNO_H)
                     errno = ERANGE;
 #endif
                     goto ret;
                 }
                     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;
         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;
         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;
         bb2 += j;
         bd2 += j;
-#ifdef Avoid_Underflow
         bd2 += scale;
         bd2 += scale;
-#endif
         i = bb2 < bd2 ? bb2 : bd2;
         if (i > bs2)
             i = bs2;
         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
              * 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
              || (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 */
                 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)
                 break;
             }
             lshift(delta, Log2P);
             if (cmp(delta, bs) > 0)
-                goto drop_down;
+                goto dropDown;
             break;
         }
             break;
         }
-        if (i == 0) {
+        if (!i) {
             /* exactly half-way between */
             if (dsign) {
                 if ((word0(&rv) & Bndry_mask1) == Bndry_mask1
                  &&  word1(&rv) == (
             /* 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)))) :
             (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;
                            0xffffffff)) {
                     /*boundary case -- increment exponent*/
                     word0(&rv) = (word0(&rv) & Exp_mask) + Exp_msk1;
                     word1(&rv) = 0;
-#ifdef Avoid_Underflow
                     dsign = 0;
                     dsign = 0;
-#endif
                     break;
                 }
             } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
                     break;
                 }
             } else if (!(word0(&rv) & Bndry_mask) && !word1(&rv)) {
-drop_down:
+dropDown:
                 /* boundary case -- decrement exponent */
                 /* 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) {
                 if (scale) {
                     L = word0(&rv) & Exp_mask;
                     if (L <= (2 * P + 1) * Exp_msk1) {
@@ -1545,9 +1080,7 @@ drop_down:
                         goto undfl;
                     }
                 }
                         goto undfl;
                     }
                 }
-#endif /*Avoid_Underflow*/
                 L = (word0(&rv) & Exp_mask) - Exp_msk1;
                 L = (word0(&rv) & Exp_mask) - Exp_msk1;
-#endif /*Sudden_Underflow}}*/
                 word0(&rv) = L | Bndry_mask1;
                 word1(&rv) = 0xffffffff;
                 break;
                 word0(&rv) = L | Bndry_mask1;
                 word1(&rv) = 0xffffffff;
                 break;
@@ -1558,24 +1091,18 @@ drop_down:
                 dval(&rv) += ulp(&rv);
             else {
                 dval(&rv) -= ulp(&rv);
                 dval(&rv) += ulp(&rv);
             else {
                 dval(&rv) -= ulp(&rv);
-#ifndef Sudden_Underflow
                 if (!dval(&rv))
                     goto undfl;
                 if (!dval(&rv))
                     goto undfl;
-#endif
             }
             }
-#ifdef Avoid_Underflow
             dsign = 1 - dsign;
             dsign = 1 - dsign;
-#endif
             break;
         }
         if ((aadj = ratio(delta, bs)) <= 2.) {
             if (dsign)
                 aadj = aadj1 = 1.;
             else if (word1(&rv) || word0(&rv) & Bndry_mask) {
             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;
                 if (word1(&rv) == Tiny1 && !word0(&rv))
                     goto undfl;
-#endif
                 aadj = 1.;
                 aadj1 = -1.;
             } else {
                 aadj = 1.;
                 aadj1 = -1.;
             } else {
@@ -1591,19 +1118,6 @@ drop_down:
         } else {
             aadj *= 0.5;
             aadj1 = dsign ? aadj : -aadj;
         } 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;
 
         }
         y = word0(&rv) & Exp_mask;
 
@@ -1620,10 +1134,9 @@ drop_down:
                 word0(&rv) = Big0;
                 word1(&rv) = Big1;
                 goto cont;
                 word0(&rv) = Big0;
                 word1(&rv) = Big1;
                 goto cont;
-            } else
-                word0(&rv) += P * Exp_msk1;
+            }
+            word0(&rv) += P * Exp_msk1;
         } else {
         } else {
-#ifdef Avoid_Underflow
             if (scale && y <= 2 * P * Exp_msk1) {
                 if (aadj <= 0x7fffffff) {
                     if ((z = (uint32_t)aadj) <= 0)
             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;
             }
             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;
         }
         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;
             /* Can we stop now? */
             L = (int32_t)aadj;
             aadj -= L;
@@ -1692,39 +1163,19 @@ drop_down:
             } else if (aadj < .4999999 / FLT_RADIX)
                 break;
         }
             } else if (aadj < .4999999 / FLT_RADIX)
                 break;
         }
-#endif
 cont:
 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);
     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 */
         /* 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
     }
             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);
 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;
 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 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;
     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]);
 #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
             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);
             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;
             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) {
 #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
             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);
             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;
             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();
 #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
 /* 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
  *
  * 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.
  *       "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,
 
     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;
     int32_t L;
-#ifndef Sudden_Underflow
     int denorm;
     uint32_t x;
     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;
     U d2, eps, u;
     double ds;
-    char *s, *s0;
-#ifdef SET_INEXACT
-    int inexact, oldinexact;
-#endif
+    char* s;
+    char* s0;
 
     u.d = dd;
 
     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)) {
     if (!dval(&u)) {
-        *decpt = 1;
+        signOut = false;
+        exponentOut = 0;
+        precisionOut = 1;
         result[0] = '0';
         result[1] = '\0';
         result[0] = '0';
         result[1] = '\0';
-        if (rve)
-            *rve = result + 1;
         return;
     }
 
         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);
 
     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)))) {
     if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) {
-#endif
         dval(&d2) = dval(&u);
         word0(&d2) &= Frac_mask1;
         word0(&d2) |= Exp_11;
         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;
          */
 
         i -= Bias;
-#ifndef Sudden_Underflow
         denorm = 0;
     } else {
         /* d is denormalized */
         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;
     }
         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)
     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;
     }
 
         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;
 
     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;
         /* 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)
         }
         if (k_check && dval(&u) < 1. && ilim > 0) {
             if (ilim1 <= 0)
-                goto fast_failed;
+                goto fastFailed;
             ilim = ilim1;
             k--;
             dval(&u) *= 10.;
             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;
         }
         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))
             S.clear();
             mhi.clear();
             dval(&u) -= 5.;
             if (dval(&u) > dval(&eps))
-                goto one_digit;
+                goto oneDigit;
             if (dval(&u) < -dval(&eps))
             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.
         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))
                 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 {
                 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.) {
             /* 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))
                 *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;
                         while (*--s == '0') { }
                         s++;
                         goto ret;
@@ -2117,10 +1531,8 @@ void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char
                     break;
                 }
             }
                     break;
                 }
             }
-#ifndef No_leftright
         }
         }
-#endif
-fast_failed:
+fastFailed:
         s = s0;
         dval(&u) = dval(&d2);
         k = k0;
         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)
             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;
         }
         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)) {
             *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))) {
                 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++;
                     while (*--s == '9')
                         if (s == s0) {
                             k++;
@@ -2179,11 +1581,7 @@ bump_up:
     mhi.clear();
     mlo.clear();
     if (leftright) {
     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);
         b2 += i;
         s2 += i;
         i2b(mhi, 1);
@@ -2204,7 +1602,7 @@ bump_up:
                 pow5mult(b, j);
         } else
             pow5mult(b, b5);
                 pow5mult(b, j);
         } else
             pow5mult(b, b5);
-        }
+    }
     i2b(S, 1);
     if (s5 > 0)
         pow5mult(S, s5);
     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;
     /* 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;
         /* 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.
      */
      * 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;
     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;
     if (i > 4) {
         i -= 4;
         b2 += i;
@@ -2253,7 +1642,7 @@ bump_up:
     if (s2 > 0)
         lshift(S, s2);
     if (k_check) {
     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)
             k--;
             multadd(b, 10, 0);    /* we botched the k estimate */
             if (leftright)
@@ -2261,7 +1650,15 @@ bump_up:
             ilim = ilim1;
         }
     }
             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);
     if (leftright) {
         if (m2 > 0)
             lshift(mhi, m2);
@@ -2271,51 +1668,60 @@ bump_up:
          */
 
         mlo = mhi;
          */
 
         mlo = mhi;
-        if (spec_case) {
-            mhi = mlo;
+        if (spec_case)
             lshift(mhi, Log2P);
             lshift(mhi, Log2P);
-        }
 
         for (i = 1;;i++) {
 
         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);
             /* 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')
                 if (dig == '9')
-                    goto round_9_up;
+                    goto round9up;
                 if (j > 0)
                     dig++;
                 if (j > 0)
                     dig++;
-#ifdef SET_INEXACT
-                else if (!b->x[0] && b->wds <= 1)
-                    inexact = 0;
-#endif
                 *s++ = dig;
                 goto ret;
             }
                 *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
 #endif
-                    goto accept_dig;
-                }
-                if (j1 > 0) {
+                if ((b.words()[0] || b.size() > 1) && (j1 > 0)) {
                     lshift(b, 1);
                     j1 = cmp(b, S);
                     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 */
                 *s++ = dig;
                 goto ret;
             }
             if (j1 > 0) {
                 if (dig == '9') { /* possible if i == 1 */
-round_9_up:
+round9up:
                     *s++ = '9';
                     goto roundoff;
                 }
                     *s++ = '9';
                     goto roundoff;
                 }
@@ -2329,25 +1735,25 @@ round_9_up:
             multadd(mlo, 10, 0);
             multadd(mhi, 10, 0);
         }
             multadd(mlo, 10, 0);
             multadd(mhi, 10, 0);
         }
-    } else
+    } else {
         for (i = 1;; i++) {
         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;
                 goto ret;
-            }
             if (i >= ilim)
                 break;
             multadd(b, 10, 0);
         }
             if (i >= ilim)
                 break;
             multadd(b, 10, 0);
         }
+    }
 
     /* Round off last digit */
 
     lshift(b, 1);
     j = cmp(b, S);
 
     /* 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) {
 roundoff:
         while (*--s == '9')
             if (s == s0) {
@@ -2361,107 +1767,68 @@ roundoff:
         s++;
     }
     goto ret;
         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:
     *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;
     *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
 }
 
 } // namespace WTF
index 6127f53972a3180bd3b8c03c7ed3768bb9b26338..3924a1cc405db293b01f6d4bdae657595258172c 100644 (file)
 #ifndef WTF_dtoa_h
 #define WTF_dtoa_h
 
 #ifndef WTF_dtoa_h
 #define WTF_dtoa_h
 
-namespace WTF {
-    class Mutex;
-}
+#include <wtf/unicode/Unicode.h>
 
 namespace WTF {
 
 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
 
 
 } // namespace WTF
 
-using WTF::DtoaBuffer;
-using WTF::doubleToStringInJavaScriptFormat;
+using WTF::NumberToStringBuffer;
+using WTF::numberToString;
 
 #endif // WTF_dtoa_h
 
 #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;
 {
     dispatchFunctionsFromMainThread();
     return ECORE_CALLBACK_CANCEL;
index da0d83996edf75651c63f5368fd208ae81f03501..7c51ee1bd6f3b53bac64bab4846d86c2403fecf0 100644 (file)
@@ -19,6 +19,8 @@
 #include "config.h"
 #include "GOwnPtr.h"
 
 #include "config.h"
 #include "GOwnPtr.h"
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include <gio/gio.h>
 #include <glib.h>
 
 #include <gio/gio.h>
 #include <glib.h>
 
@@ -59,9 +61,6 @@ template <> void freeOwnedGPtr<GDir>(GDir* ptr)
         g_dir_close(ptr);
 }
 
         g_dir_close(ptr);
 }
 
-template <> void freeOwnedGPtr<GFile>(GFile* ptr)
-{
-    if (ptr)
-        g_object_unref(ptr);
-}
 } // namespace WTF
 } // namespace WTF
+
+#endif // ENABLE(GLIB_SUPPORT)
index 1fc594c9fa42c246af104bf84012876b6bf7db7e..8c7e8372f73ff790841b59a8f914d0d9a655f8b2 100644 (file)
 #ifndef GOwnPtr_h
 #define GOwnPtr_h
 
 #ifndef GOwnPtr_h
 #define GOwnPtr_h
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include <algorithm>
 #include <wtf/Assertions.h>
 #include <wtf/Noncopyable.h>
 
 #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 {
 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<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); }
 public:
     explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { }
     ~GOwnPtr() { freeOwnedGPtr(m_ptr); }
@@ -78,8 +69,9 @@ public:
 
     void clear()
     {
 
     void clear()
     {
-        freeOwnedGPtr(m_ptr);
+        T* ptr = m_ptr;
         m_ptr = 0;
         m_ptr = 0;
+        freeOwnedGPtr(ptr);
     }
 
     T& operator*() const
     }
 
     T& operator*() const
@@ -145,4 +137,7 @@ template <typename T> inline void freeOwnedGPtr(T* ptr)
 
 using WTF::GOwnPtr;
 
 
 using WTF::GOwnPtr;
 
+#endif // ENABLE(GLIB_SUPPORT)
+
 #endif // GOwnPtr_h
 #endif // GOwnPtr_h
+
index e7cf34bd4ee3bac87405a2f6ee9721d425d68661..1cd22c532b674d902ebd5c308c0bb4aeaef5020c 100644 (file)
@@ -19,6 +19,8 @@
 #include "config.h"
 #include "GRefPtr.h"
 
 #include "config.h"
 #include "GRefPtr.h"
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include <glib.h>
 
 namespace WTF {
 #include <glib.h>
 
 namespace WTF {
@@ -35,4 +37,50 @@ template <> void derefGPtr(GHashTable* ptr)
     g_hash_table_unref(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
 } // namespace WTF
+
+#endif // ENABLE(GLIB_SUPPORT)
index 3a33605c29746675af5083902c062513bc44285b..10ebf0753dea9b9bd50c2779e7551f1a1a56c435 100644 (file)
 #ifndef WTF_GRefPtr_h
 #define WTF_GRefPtr_h
 
 #ifndef WTF_GRefPtr_h
 #define WTF_GRefPtr_h
 
+#if ENABLE(GLIB_SUPPORT)
+
 #include "AlwaysInline.h"
 #include "AlwaysInline.h"
+#include "GRefPtr.h"
+#include "RefPtr.h"
 #include <algorithm>
 
 #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 {
 
 
 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 <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) { }
 
 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);
     {
         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;
         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; }
     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);
 }
 
     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)
 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;
 } // namespace WTF
 
 using WTF::GRefPtr;
-using WTF::refGPtr;
-using WTF::derefGPtr;
 using WTF::adoptGRef;
 using WTF::adoptGRef;
-using WTF::static_pointer_cast;
-using WTF::const_pointer_cast;
+
+#endif // ENABLE(GLIB_SUPPORT)
 
 #endif // WTF_GRefPtr_h
 
 #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 "HashMap.h"
 #include "MainThread.h"
 #include "RandomNumberSeed.h"
+#include <wtf/StdLibExtras.h>
 
 #include <glib.h>
 #include <limits.h>
 
 namespace WTF {
 
 
 #include <glib.h>
 #include <limits.h>
 
 namespace WTF {
 
+typedef HashMap<ThreadIdentifier, GThread*> ThreadMap;
+
 static Mutex* atomicallyInitializedStaticMutex;
 
 static Mutex& threadMapMutex()
 {
 static Mutex* atomicallyInitializedStaticMutex;
 
 static Mutex& threadMapMutex()
 {
-    static Mutex mutex;
+    DEFINE_STATIC_LOCAL(Mutex, mutex, ());
     return mutex;
 }
 
     return mutex;
 }
 
@@ -74,9 +77,9 @@ void unlockAtomicallyInitializedStaticMutex()
     atomicallyInitializedStaticMutex->unlock();
 }
 
     atomicallyInitializedStaticMutex->unlock();
 }
 
-static HashMap<ThreadIdentifier, GThread*>& threadMap()
+static ThreadMap& threadMap()
 {
 {
-    static HashMap<ThreadIdentifier, GThread*> map;
+    DEFINE_STATIC_LOCAL(ThreadMap, map, ());
     return map;
 }
 
     return map;
 }
 
@@ -84,7 +87,7 @@ static ThreadIdentifier identifierByGthreadHandle(GThread*& thread)
 {
     MutexLocker locker(threadMapMutex());
 
 {
     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;
     for (; i != threadMap().end(); ++i) {
         if (i->second == thread)
             return i->first;
@@ -164,6 +167,11 @@ ThreadIdentifier currentThread()
     return establishIdentifierForThread(currentThread);
 }
 
     return establishIdentifierForThread(currentThread);
 }
 
+void yield()
+{
+    g_thread_yield();
+}
+
 Mutex::Mutex()
     : m_mutex(g_mutex_new())
 {
 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()
 {
 
 void initializeMainThreadPlatform()
 {
-#if !defined(BUILDING_ON_TIGER)
     ASSERT(!staticMainThreadCaller);
     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
 
     mainThreadEstablishedAsPthreadMain = false;
     mainThreadPthread = pthread_self();
     mainThreadNSThread = [[NSThread currentThread] retain];
     ASSERT(!staticMainThreadCaller);
     staticMainThreadCaller = [[WTFMainThreadCaller alloc] init];
 
     mainThreadEstablishedAsPthreadMain = false;
     mainThreadPthread = pthread_self();
     mainThreadNSThread = [[NSThread currentThread] retain];
-#else
-    ASSERT_NOT_REACHED();
-#endif
 }
 
 void initializeMainThreadToProcessMainThreadPlatform()
 }
 
 void initializeMainThreadToProcessMainThreadPlatform()
@@ -117,12 +113,8 @@ void scheduleDispatchFunctionsOnMainThread()
         return;
     }
 
         return;
     }
 
-#if !defined(BUILDING_ON_TIGER)
     ASSERT(mainThreadNSThread);
     [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
     ASSERT(mainThreadNSThread);
     [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO];
-#else
-    ASSERT_NOT_REACHED();
-#endif
 }
 
 bool isMainThread()
 }
 
 bool isMainThread()
@@ -132,13 +124,8 @@ bool isMainThread()
         return pthread_main_np();
     }
 
         return pthread_main_np();
     }
 
-#if !defined(BUILDING_ON_TIGER)
     ASSERT(mainThreadPthread);
     return pthread_equal(pthread_self(), mainThreadPthread);
     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
 }
 
 // This function is the same as isMainThread() above except that it does not do
index b2c621ac3be48511a2b30a2e9d33da4ec2abdb29..16dd439e3bcf1b85a66bb1d509722545063668dc 100644 (file)
 
 #include "config.h"
 
 
 #include "config.h"
 
+#include <wtf/StdLibExtras.h>
 #include <wtf/text/WTFString.h>
 
 #include <QString>
 
 #include <wtf/text/WTFString.h>
 
 #include <QString>
 
-namespace WebCore {
+namespace WTF {
 
 // String conversions
 String::String(const QString& qstr)
 {
     if (qstr.isNull())
         return;
 
 // 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;
 }
 
 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
 }
 
 String::operator QString() const
index 7f81646af55acdfcb6763d8b0364f769ee60f142..8041dea531a3a0995a551501948e75a27a2ee4be 100644 (file)
@@ -208,6 +208,11 @@ ThreadIdentifier currentThread()
     return establishIdentifierForThread(currentThread);
 }
 
     return establishIdentifierForThread(currentThread);
 }
 
+void yield()
+{
+    QThread::yieldCurrentThread();
+}
+
 Mutex::Mutex()
     : m_mutex(new QMutex())
 {
 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) 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
  *
  * 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 "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 "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);
 
 
 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();
 }
 
     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)
     {
 struct CStringTranslator {
     static unsigned hash(const char* c)
     {
-        return StringImpl::computeHash(c);
+        return StringHasher::computeHash(c);
     }
 
     static bool equal(StringImpl* r, const char* s)
     }
 
     static bool equal(StringImpl* r, const char* s)
@@ -102,12 +116,12 @@ struct CStringTranslator {
             if (d[i] != c)
                 return false;
         }
             if (d[i] != c)
                 return false;
         }
-        return s[length] == 0;
+        return !s[length];
     }
 
     static void translate(StringImpl*& location, const char* const& c, unsigned hash)
     {
     }
 
     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);
     }
         location->setHash(hash);
         location->setIsAtomic(true);
     }
@@ -128,12 +142,10 @@ PassRefPtr<StringImpl> AtomicString::add(const char* c)
     if (!c)
         return 0;
     if (!*c)
     if (!c)
         return 0;
     if (!*c)
-        return StringImpl::empty();    
+        return StringImpl::empty();
+
     AtomicStringTableLocker locker;
     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 {
 }
 
 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
 
     // 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++)
     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
 }
 
 #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)
     {
 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)
     {
     }
 
     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)
     {
     }
 
     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);
     }
         location->setHash(hash);
         location->setIsAtomic(true);
     }
@@ -202,18 +219,65 @@ struct HashAndCharacters {
 struct HashAndCharactersTranslator {
     static unsigned hash(const HashAndCharacters& buffer)
     {
 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 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)
     {
     }
 
     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);
     }
         location->setHash(hash);
         location->setIsAtomic(true);
     }
@@ -224,16 +288,12 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length)
     if (!s)
         return 0;
 
     if (!s)
         return 0;
 
-    if (length == 0)
+    if (!length)
         return StringImpl::empty();
     
         return StringImpl::empty();
     
-    UCharBuffer buf = { s, length }; 
+    UCharBuffer buffer = { s, length };
     AtomicStringTableLocker locker;
     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)
 }
 
 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);
 
     ASSERT(s);
     ASSERT(existingHash);
 
-    if (length == 0)
+    if (!length)
         return StringImpl::empty();
         return StringImpl::empty();
-    
-    HashAndCharacters buffer = { existingHash, s, length }; 
+
+    HashAndCharacters buffer = { existingHash, s, length };
     AtomicStringTableLocker locker;
     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)
 }
 
 PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
@@ -261,16 +318,12 @@ PassRefPtr<StringImpl> AtomicString::add(const UChar* s)
     while (s[length] != UChar(0))
         length++;
 
     while (s[length] != UChar(0))
         length++;
 
-    if (length == 0)
+    if (!length)
         return StringImpl::empty();
 
         return StringImpl::empty();
 
-    UCharBuffer buf = {s, length}; 
+    UCharBuffer buffer = { s, length };
     AtomicStringTableLocker locker;
     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)
 }
 
 PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
@@ -278,7 +331,7 @@ PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r)
     if (!r || r->isAtomic())
         return r;
 
     if (!r || r->isAtomic())
         return r;
 
-    if (r->length() == 0)
+    if (!r->length())
         return StringImpl::empty();
 
     AtomicStringTableLocker locker;
         return StringImpl::empty();
 
     AtomicStringTableLocker locker;
@@ -293,7 +346,7 @@ AtomicStringImpl* AtomicString::find(const UChar* s, unsigned length, unsigned e
     ASSERT(s);
     ASSERT(existingHash);
 
     ASSERT(s);
     ASSERT(existingHash);
 
-    if (length == 0)
+    if (!length)
         return static_cast<AtomicStringImpl*>(StringImpl::empty());
 
     HashAndCharacters buffer = { existingHash, s, 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);
 }
     AtomicStringTableLocker locker;
     stringTable().remove(r);
 }
-    
+
 AtomicString AtomicString::lower() const
 {
     // Note: This is a hot function in the Dromaeo benchmark.
     StringImpl* impl = this->impl();
 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);
 }
 
     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
 
 #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;
 
 
 struct AtomicStringHash;
 
@@ -73,10 +71,10 @@ public:
     bool contains(const String& s, bool caseSensitive = true) const
         { return m_string.contains(s, caseSensitive); }
 
     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); }
         { 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
         { 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*);
     
 
     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    
     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
 
     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;
     
 private:
     String m_string;
     
@@ -124,19 +127,24 @@ private:
         return addSlowCase(r);
     }
     static PassRefPtr<StringImpl> addSlowCase(StringImpl*);
         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);
 };
 
 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 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 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 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); }
 
 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
 // 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
 
 #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
 
 
 } // 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
 #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"
 
 
 #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
 {
 
 class AtomicStringImpl : public StringImpl
 {
@@ -35,4 +33,6 @@ public:
 
 }
 
 
 }
 
+using WTF::AtomicStringImpl;
+
 #endif
 #endif
index 3ce3053eaed67c58f1c4a33d332e4d6c0ff62358..981d77a1db2e456faad927efe29a0641015fad37 100644 (file)
@@ -33,21 +33,27 @@ namespace WTF {
 
 CString::CString(const char* str)
 {
 
 CString::CString(const char* str)
 {
+    if (!str)
+        return;
+
     init(str, strlen(str));
 }
 
     init(str, strlen(str));
 }
 
-CString::CString(const char* str, unsigned length)
+CString::CString(const char* str, size_t length)
 {
     init(str, 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 (!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); 
 
     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;
 
 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;
     char* mutableData() { return m_vector.data(); }
 
     Vector<char> m_vector;
@@ -53,7 +53,7 @@ class CString {
 public:
     CString() { }
     CString(const char*);
 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);
 
     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();
         return m_buffer ? m_buffer->data() : 0;
     }
     char* mutableData();
-    unsigned length() const
+    size_t length() const
     {
         return m_buffer ? m_buffer->length() - 1 : 0;
     }
     {
         return m_buffer ? m_buffer->length() - 1 : 0;
     }
@@ -73,7 +73,7 @@ public:
 
 private:
     void copyBufferIfNeeded();
 
 private:
     void copyBufferIfNeeded();
-    void init(const char*, unsigned length);
+    void init(const char*, size_t length);
     RefPtr<CStringBuffer> m_buffer;
 };
 
     RefPtr<CStringBuffer> m_buffer;
 };
 
index cf732e31732d74de4eaae49b4d4269ba09677e06..e73d38e56d097c9edc036371d4d43ae283d5c3ee 100644 (file)
 #define StringBuffer_h
 
 #include <wtf/Assertions.h>
 #define StringBuffer_h
 
 #include <wtf/Assertions.h>
-#include <wtf/Noncopyable.h>
 #include <wtf/unicode/Unicode.h>
 #include <limits>
 
 #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)
 public:
     explicit StringBuffer(unsigned length)
         : m_length(length)
@@ -81,4 +81,6 @@ private:
 
 } // namespace WTF
 
 
 } // namespace WTF
 
+using WTF::StringBuffer;
+
 #endif // StringBuffer_h
 #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 "AtomicString.h"
 #include "WTFString.h"
+#include <wtf/Forward.h>
 #include <wtf/HashTraits.h>
 #include <wtf/HashTraits.h>
-#include <wtf/StringHashFunctions.h>
+#include <wtf/StringHasher.h>
 #include <wtf/unicode/Unicode.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>
 
     // 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
 
             // 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) {
             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:
 
     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)
         {
         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(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)
         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
 #endif
index 9d5333f98ca03a2ea1e6c27cd6c3ffebad282286..ec0c094636bdfdf0cda93fc92f6535e42b745276 100644 (file)
 #include <wtf/StdLibExtras.h>
 #include <wtf/WTFThreadData.h>
 
 #include <wtf/StdLibExtras.h>
 #include <wtf/WTFThreadData.h>
 
-using namespace WTF;
-using namespace Unicode;
 using namespace std;
 
 using namespace std;
 
-namespace WebCore {
+namespace WTF {
+
+using namespace Unicode;
 
 static const unsigned minLengthToShare = 20;
 
 
 static const unsigned minLengthToShare = 20;
 
+COMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*), StringImpl_should_stay_small);
+
 StringImpl::~StringImpl()
 {
     ASSERT(!isStatic());
 StringImpl::~StringImpl()
 {
     ASSERT(!isStatic());
@@ -46,8 +48,10 @@ StringImpl::~StringImpl()
     if (isAtomic())
         AtomicString::remove(this);
 #if USE(JSC)
     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();
 #endif
 
     BufferOwnership ownership = bufferOwnership();
@@ -143,7 +147,7 @@ SharedUChar* StringImpl::sharedBuffer()
         return m_substringBuffer->sharedBuffer();
     if (ownership == BufferOwned) {
         ASSERT(!m_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;
     }
 
         m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared;
     }
 
@@ -266,16 +270,17 @@ PassRefPtr<StringImpl> StringImpl::upper()
     return newImpl.release();
 }
 
     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);
     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();
 }
 
     return newImpl.release();
 }
 
@@ -453,14 +458,14 @@ intptr_t StringImpl::toIntPtr(bool* ok)
     return charactersToIntPtr(m_data, m_length, 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)
 }
 
 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;
 }
 
     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();
         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;
 }
 
     return false;
 }
 
@@ -715,12 +821,12 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
     if (!replacement)
         return this;
         
     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
     unsigned matchCount = 0;
     
     // Count the matches
-    while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) {
+    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
         ++matchCount;
         ++srcSegmentStart;
     }
         ++matchCount;
         ++srcSegmentStart;
     }
@@ -743,12 +849,12 @@ PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacemen
     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
 
     // Construct the new data
     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
 
     // Construct the new data
-    int srcSegmentEnd;
-    int srcSegmentLength;
+    size_t srcSegmentEnd;
+    unsigned srcSegmentLength;
     srcSegmentStart = 0;
     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;
         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));
 
     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();
 }
 
     return newImpl.release();
 }
@@ -770,16 +876,16 @@ PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* repl
     if (!pattern || !replacement)
         return this;
 
     if (!pattern || !replacement)
         return this;
 
-    int patternLength = pattern->length();
+    unsigned patternLength = pattern->length();
     if (!patternLength)
         return this;
         
     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
     unsigned matchCount = 0;
     
     // Count the matches
-    while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) {
+    while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) {
         ++matchCount;
         srcSegmentStart += patternLength;
     }
         ++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
     RefPtr<StringImpl> newImpl = createUninitialized(newSize, data);
     
     // Construct the new data
-    int srcSegmentEnd;
-    int srcSegmentLength;
+    size_t srcSegmentEnd;
+    unsigned srcSegmentLength;
     srcSegmentStart = 0;
     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;
         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));
 
     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();
 }
 
     return newImpl.release();
 }
@@ -899,29 +1005,23 @@ bool equalIgnoringNullity(StringImpl* a, StringImpl* b)
     return false;
 }
 
     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]);
 {
     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;
             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;
             return WTF::Unicode::RightToLeft;
+        }
     }
     }
+    if (hasStrongDirectionality)
+        *hasStrongDirectionality = false;
     return WTF::Unicode::LeftToRight;
 }
 
     return WTF::Unicode::LeftToRight;
 }
 
@@ -996,4 +1096,4 @@ PassRefPtr<StringImpl> StringImpl::crossThreadString()
     return threadsafeCopy();
 }
 
     return threadsafeCopy();
 }
 
-} // namespace WebCore
+} // namespace WTF
index 4354cabaf2ba3736a188e2110fa7ce74e6ff69ae..239ab491e3e03b9927c332ab8f7c85f6deeed553 100644 (file)
 #include <limits.h>
 #include <wtf/ASCIICType.h>
 #include <wtf/CrossThreadRefCounted.h>
 #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/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>
 
 #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
 
 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 {
 // 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;
 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 CStringTranslator;
 struct HashAndCharactersTranslator;
-struct StringHash;
+struct HashAndUTF8CharactersTranslator;
 struct UCharBufferTranslator;
 
 enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive };
 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;
 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.
     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)
     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);
         , 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)
     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);
         , m_hash(0)
     {
         ASSERT(m_data);
@@ -140,7 +136,7 @@ private:
     {
         ASSERT(!isStatic());
         ASSERT(!m_hash);
     {
         ASSERT(!isStatic());
         ASSERT(!m_hash);
-        ASSERT(hash == computeHash(m_data, m_length));
+        ASSERT(hash == StringHasher::computeHash(m_data, m_length));
         m_hash = hash;
     }
 
         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(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());
     {
         ASSERT(rep);
         ASSERT(length <= rep->length());
@@ -164,7 +160,7 @@ public:
     }
 
     static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data);
     }
 
     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;
     {
         if (!length) {
             output = 0;
@@ -239,11 +235,8 @@ public:
             m_refCountAndFlags &= ~s_refCountFlagIsAtomic;
     }
 
             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; }
     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; }
 
     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
 
     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> 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();
     PassRefPtr<StringImpl> foldCase();
 
     PassRefPtr<StringImpl> stripWhiteSpace();
@@ -298,15 +294,18 @@ public:
 
     PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr);
 
 
     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);
     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*);
 
     PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*);
     PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*);
 
-    Vector<char> ascii();
     int wordCount(int maxWordsToCount = INT_MAX);
 
     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__
     CFStringRef createCFString();
 #endif
 #ifdef __OBJC__
@@ -355,6 +353,18 @@ inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) {
 
 bool equalIgnoringNullity(StringImpl*, StringImpl*);
 
 
 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.
 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);
 }
 
     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
 #endif
index 65676725eb583158a7569d0d1a0bb685b83bd019..26bc1d90ce524e5233f3e47c0e86ccccb1cfbb91 100644 (file)
 #ifndef StringImplBase_h
 #define StringImplBase_h
 
 #ifndef StringImplBase_h
 #define StringImplBase_h
 
-#include <wtf/Noncopyable.h>
 #include <wtf/unicode/Unicode.h>
 
 namespace WTF {
 
 #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; }
 public:
     bool isStringImpl() { return (m_refCountAndFlags & s_refCountInvalidForStringImpl) != s_refCountInvalidForStringImpl; }
     unsigned length() const { return m_length; }
@@ -45,9 +45,6 @@ protected:
         BufferShared,
     };
 
         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() { }
 
     // 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"
 #endif
 
 #include "AtomicString.h"
+#include "DynamicAnnotations.h"
 #include "StaticConstructors.h"
 #include "StringImpl.h"
 
 #include "StaticConstructors.h"
 #include "StringImpl.h"
 
-namespace WebCore {
+namespace WTF {
 
 StringImpl* StringImpl::empty()
 {
 
 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));
     // 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;
 }
 
     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>
 
 #include <wtf/unicode/UTF8.h>
 #include <wtf/unicode/Unicode.h>
 
-using namespace WTF;
-using namespace WTF::Unicode;
 using namespace std;
 
 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)
 String::String(const UChar* str)
 {
     if (!str)
@@ -52,6 +60,18 @@ String::String(const UChar* str)
     m_impl = StringImpl::create(str, len);
 }
 
     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())
 void String::append(const String& str)
 {
     if (str.isEmpty())
@@ -111,25 +131,9 @@ void String::append(UChar c)
         m_impl = StringImpl::create(&c, 1);
 }
 
         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)
 }
 
 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);
 }
 
     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)
 String String::lower() const
 {
     if (!m_impl)
@@ -306,7 +323,8 @@ String String::format(const char *format, ...)
 
     va_end(args);
 
 
     va_end(args);
 
-    return buffer;
+    QByteArray ba = buffer.toUtf8();
+    return StringImpl::create(ba.constData(), ba.length());
 
 #elif OS(WINCE)
     va_list args;
 
 #elif OS(WINCE)
     va_list args;
@@ -522,24 +540,28 @@ intptr_t String::toIntPtr(bool* ok) const
     return m_impl->toIntPtr(ok);
 }
 
     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 (!m_impl) {
         if (ok)
             *ok = false;
+        if (didReadNumber)
+            *didReadNumber = false;
         return 0.0;
     }
         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 (!m_impl) {
         if (ok)
             *ok = false;
+        if (didReadNumber)
+            *didReadNumber = false;
         return 0.0f;
     }
         return 0.0f;
     }
-    return m_impl->toFloat(ok);
+    return m_impl->toFloat(ok, didReadNumber);
 }
 
 String String::threadsafeCopy() const
 }
 
 String String::threadsafeCopy() const
@@ -560,54 +582,59 @@ void String::split(const String& separator, bool allowEmptyEntries, Vector<Strin
 {
     result.clear();
 
 {
     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 != 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
 {
         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();
 
 }
 
 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 != 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
 {
         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
 }
 
 CString String::latin1() const
@@ -623,7 +650,7 @@ CString String::latin1() const
 
     for (unsigned i = 0; i < length; ++i) {
         UChar ch = characters[i];
 
     for (unsigned i = 0; i < length; ++i) {
         UChar ch = characters[i];
-        characterBuffer[i] = ch > 255 ? '?' : ch;
+        characterBuffer[i] = ch > 0xff ? '?' : ch;
     }
 
     return result;
     }
 
     return result;
@@ -638,7 +665,7 @@ static inline void putUTF8Triple(char*& buffer, UChar ch)
     *buffer++ = static_cast<char>((ch & 0x3F) | 0x80);
 }
 
     *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();
 {
     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();
     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
 
     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) {
     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()));
         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);
 }
 
     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 (!length) {
         if (ok)
             *ok = false;
+        if (didReadNumber)
+            *didReadNumber = false;
         return 0.0;
     }
 
         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';
     for (unsigned i = 0; i < length; ++i)
         bytes[i] = data[i] < 0x7F ? data[i] : '?';
     bytes[length] = '\0';
+    char* start = bytes.data();
     char* end;
     char* end;
-    double val = WTF::strtod(bytes.data(), &end);
+    double val = WTF::strtod(start, &end);
     if (ok)
         *ok = (end == 0 || *end == '\0');
     if (ok)
         *ok = (end == 0 || *end == '\0');
+    if (didReadNumber)
+        *didReadNumber = end - start;
     return val;
 }
 
     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.
 {
     // 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
 
 #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
 #endif
index 493e793d3b1eb7c26548b7e81d08175f1e548a0d..71176b2b54b1e00ad3dddb4d95780bbb968faac5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * (C) 1999 Lars Knoll (knoll@kde.org)
 /*
  * (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
  *
  * 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
 
 #include <objc/objc.h>
 #endif
 
-#if PLATFORM(CF)
+#if USE(CF)
 typedef const struct __CFString * CFStringRef;
 #endif
 
 typedef const struct __CFString * CFStringRef;
 #endif
 
@@ -50,21 +50,23 @@ class wxString;
 class BString;
 #endif
 
 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);
 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);
 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
 
 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:
 
 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(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;
     {
         if (!m_impl)
             return 0;
@@ -132,34 +139,67 @@ public:
         return m_impl->characters();
     }
 
         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 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
     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 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;
 
     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); }
 
     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;
     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;
 
 
     // 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);
     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.
 
     // 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;
     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;
 
 
     bool percentage(int& percentage) const;
 
@@ -246,12 +286,14 @@ public:
     // to ever prefer copy() over plain old assignment.
     String threadsafeCopy() const;
 
     // 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
     String(CFStringRef);
     CFStringRef createCFString() const;
 #endif
@@ -280,11 +322,12 @@ public:
     operator BString() const;
 #endif
 
     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*);
 
     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.
     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 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;
 
 private:
     RefPtr<StringImpl> m_impl;
@@ -305,10 +360,6 @@ QDataStream& operator<<(QDataStream& stream, const String& str);
 QDataStream& operator>>(QDataStream& stream, String& str);
 #endif
 
 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()); }
 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()); }
 
 
 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
 
 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
 #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);
 }
 
     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)
 }
 
 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
 #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
 
 #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>
 #include <wtf/Noncopyable.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/unicode/Unicode.h>
@@ -39,7 +40,8 @@ struct UCollator;
 
 namespace WTF {
 
 
 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 };
 
     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()
 {
 
 PassOwnPtr<Collator> Collator::userDefault()
 {
-    return new Collator(0);
+    return adoptPtr(new Collator(0));
 }
 
 // A default implementation for platforms that lack Unicode-aware collation.
 }
 
 // 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) 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
  *
  * 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 "config.h"
 #include "UTF8.h"
 
+#include "ASCIICType.h"
+#include <wtf/StringHasher.h>
+#include <wtf/unicode/CharacterNames.h>
+
 namespace WTF {
 namespace Unicode {
 
 namespace WTF {
 namespace Unicode {
 
@@ -44,12 +49,12 @@ inline int inlineUTF8SequenceLengthNonASCII(char b0)
 
 inline int inlineUTF8SequenceLength(char b0)
 {
 
 inline int inlineUTF8SequenceLength(char b0)
 {
-    return (b0 & 0x80) == 0 ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
+    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
 }
 
 int UTF8SequenceLength(char b0)
 {
 }
 
 int UTF8SequenceLength(char b0)
 {
-    return (b0 & 0x80) == 0 ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
+    return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0);
 }
 
 int decodeUTF8Sequence(const char* sequence)
 }
 
 int decodeUTF8Sequence(const char* sequence)
@@ -172,7 +177,7 @@ ConversionResult convertUTF16ToUTF8(
             bytesToWrite = 4;
         } else {
             bytesToWrite = 3;
             bytesToWrite = 4;
         } else {
             bytesToWrite = 3;
-            ch = 0xFFFD;
+            ch = replacementCharacter;
         }
 
         target += bytesToWrite;
         }
 
         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 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)
 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) {
     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
             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;
         }
             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) {
 
         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
             // UTF-16 surrogate values are illegal in UTF-32
-            if (ch >= 0xD800 && ch <= 0xDFFF) {
+            if (U_IS_SURROGATE(character)) {
                 if (strict) {
                 if (strict) {
-                    source -= (extraBytesToRead + 1); // return to the illegal value itself
+                    source -= utf8SequenceLength; // return to the illegal value itself
                     result = sourceIllegal;
                     break;
                 } else
                     result = sourceIllegal;
                     break;
                 } else
-                    *target++ = 0xFFFD;
+                    *target++ = replacementCharacter;
             } else
             } 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) {
             // 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;
             }
                 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;
         }
     }
     *sourceStart = source;
@@ -300,5 +314,94 @@ ConversionResult convertUTF8ToUTF16(
     return result;
 }
 
     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 {
 #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.
 
     // 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);
     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
 
 #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)
 #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
 #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) 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
  *
  *  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 "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 {
 
 namespace WTF {
 namespace Unicode {
 
@@ -43,100 +49,71 @@ UChar32 foldCase(UChar32 ch)
     return *ucs4Result;
 }
 
     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;
 {
     *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;
     }
         *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;
         *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;
         *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)
 }
 
 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()
 {
 
 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.
     // 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
     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];
     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
 #else
-    return new Collator(0);
+    return adoptPtr(new Collator(0));
 #endif
 }
 
 #endif
 }
 
index 97c42b7bb810b9146a32963a2f4211d271cc0112..eaa7a0783d81e4c9bee83d5ce3302dc10d12d805 100644 (file)
 #ifndef WTF_UNICODE_QT4_H
 #define WTF_UNICODE_QT4_H
 
 #ifndef WTF_UNICODE_QT4_H
 #define WTF_UNICODE_QT4_H
 
+#include "UnicodeMacrosFromICU.h"
+
 #include <QChar>
 #include <QString>
 
 #include <config.h>
 
 #include <stdint.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 {
 
 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
 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 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 {
 
 namespace WTF {
 namespace Unicode {
@@ -188,7 +156,7 @@ enum CharCategory {
 
 inline UChar32 toLower(UChar32 ch)
 {
 
 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)
 }
 
 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;
 }
 
     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)
 }
 
 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)
 {
 
 inline int toTitleCase(UChar32 c)
 {
-    return QChar::toTitleCase(c);
+    return QChar::toTitleCase(uint32_t(c));
 }
 
 inline UChar32 foldCase(UChar32 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)
 }
 
 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);
 {
     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)
 {
 }
 
 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)
 }
 
 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);
                       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)
 {
 }
 
 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)
 }
 
 inline bool hasLineBreakingPropertyComplexContext(UChar32)
@@ -367,12 +335,12 @@ inline bool hasLineBreakingPropertyComplexContext(UChar32)
 
 inline UChar32 mirroredChar(UChar32 c)
 {
 
 inline UChar32 mirroredChar(UChar32 c)
 {
-    return QChar::mirroredChar(c);
+    return QChar::mirroredChar(uint32_t(c));
 }
 
 inline uint8_t combiningClass(UChar32 c)
 {
 }
 
 inline uint8_t combiningClass(UChar32 c)
 {
-    return QChar::combiningClass(c);
+    return QChar::combiningClass(uint32_t(c));
 }
 
 inline DecompositionType decompositionType(UChar32 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)
 {
 
 inline Direction direction(UChar32 c)
 {
-    return (Direction)QChar::direction(c);
+    return (Direction)QChar::direction(uint32_t(c));
 }
 
 inline CharCategory category(UChar32 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) { }
 
     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 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()
     {
 
     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
+